diff --git a/ChangeLog b/ChangeLog index db287f281..e9645b67c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,6 +1,6 @@ -MaNGOS 0.12 (??? ??? 2008) +MaNGOS 0.13 (??? ??? 2009) - MaNGOS 0.12 - Codename "???" - adds further improvements to the + MaNGOS 0.13 - adds further improvements to the server core as well as to the majority of game classes and the game content database. @@ -12,6 +12,79 @@ MaNGOS 0.12 (??? ??? 2008) * Fixed Bugs: ??? * Total number of changes: ??? +MaNGOS 0.12 (Dec 22 2008) + + MaNGOS 0.12 - adds further improvements to the + server core as well as to the majority of game classes and the game content + database. + + ==== Game Features ==== + + * Added: Support for different difficult instances, proper instances reset and proper group/player binding to instances. + * Added: Support for arena system. + * Added: Support for declined names (with Cyrillic client). + * Added: Support for auction pending mail and 1 hour delay in money delivery to owner. + * Added: Support for possibility reject warlock's player summon by targeted player. + * Added: Support for talent based pet auras. + * Added: Support for auto-reward quests. + * Added: Support for trap arming delay in combat state. + * Added: Support for show enchantment item effect on login screen. + * Added: Support for restoration buff in battlegrounds. + * Added: Support for dependent spell disabling (instead removing) at talent reset until talent re-learning. + * Added: Support for guild/arena team leaders delete protection. + * Added: Support for areatrigger scripting. + * Added: Support for honor rewards from quests. + * Added: Support for realmd reconnect from login character list. + * Added: Support for configurable assistance aggro delaying. + * Improved: Better duels work. + * Improved: Improvements in battleground system work including really instancing battlegrounds. + * Improved: Better support game localization for players and GMs. + * Improved: More server-side re-checks for client side primary checked data for prevent cheating. + * Improved: Player can't dodge attack from behind. + * Improved: Correctly animate eating/drinking in cases sitting at chairs/etc. + * Improved: Better guardians related functionality work. + * Improved: Expected instant logout in taxi flight at logout request. + * Improved: Re-implement raid ready check code. + * Improved: Select fishing bobber activating time in more standard way. + * Improved: Better random/waypoint creature movement work including fly case. + * Improved: Evade distance is now based on the distance from the position that the creature was at when it entered combat. + * Improved: Implemented further support for contested guards. + * Improved: Show available daily quests at map as blue marks. + * Improved: Limit distance for listen say/yell text. + * Improved: Removed dismount at login hack that now unneeded. + * Improved: Better support for low character experience gain in group with high character. + * Improved: Default behavior of pets for creatures changed to REACT_DEFENSIVE. + * Improved: Better work with combo points on miss/parry/immune. + * Improved: Allow have team dependent graveyards at entrance map for instances. + * Improved: Allowed switching INVTYPE_HOLDABLE items during combat. + * Improved: Make flying creatures fall on ground when killed. + * Improved: More correct way of calculating fall damage by using fall distance and not fall time. + * plus lots of fixes for auras, effects, spells, talents, and more. + + ==== Server Features ==== + + * Added: Support for load and use multiply DBC locales data at server. + * Added: Store in `spell_chain` additional spell dependences from another spell chain for learning possibility checks. + * Added: New chat command for reload settings from mangosd.conf file without server restart need. + * Added: Set icon for realmd/mangosd binaries at Windows build. + * Added: Start use Adaptive Communication Environment (ACE) framework v.5.6.6 in server network code. + * Added: Migrate from SVN sourceforge.net to GIT github.com repository for project sources store. + * Added: Script name indexing for creature, gameobject, item, areatrigger and instance script. + * Added: The possibility to use custom process return values. + * Improved: More DB tables loading at server startup and less unneeded DB access in server work time. + * Improved: Console support for chat like commands features. Merge chat/console command list to single. + * Improved: Implement possibility output detailed and DB error log messages from scripting code. + * Improved: Better localization support for DB scripts and scripting library. + * Improved: Referenced loot data moved to new table for better sharing like data from other loot tables. + * Improved: Prevent overwriting realmd.conf and mangosd.conf on make install at Unix/Linux. + * Improved: Update Visual Leak Detector lib to Version 1.9g (beta). + * Improved: New revisions numbering and sql updates names scheme with tools support used after switch to GIT. + * Improved: Use DBC data for creating initial character items. + + ==== Statistics ==== + * Fixed Bugs: many :) + * Total number of changes: 731 (323 in git) + MaNGOS 0.11 (Jul 22 2008) MaNGOS 0.11 - adds further improvements to the diff --git a/NEWS b/NEWS index 0cac6a689..e4a7d1174 100644 --- a/NEWS +++ b/NEWS @@ -13,8 +13,15 @@ http://getmangos.com/community/ Please submit bug reports at: http://mangos.lighthouseapp.com/ -Version 0.12 +Version 0.13 * Under discussion. + * Upgrade to client version 3.0.3 (build 9183). + +Version 0.12 + * Migrate from SVN to GIT. + * Implemented arena system. + * Start using Adaptive Communication Environment (ACE) framework v.5.6.6 in server network code. + * Update Visual Leak Detector lib to Version 1.9g (beta). * Upgrade to client version 2.4.3 (build 8606). Version 0.11 diff --git a/THANKS b/THANKS index 5d5e8fded..46ed80e44 100644 --- a/THANKS +++ b/THANKS @@ -21,6 +21,9 @@ similar to this one: community with a great server. We have not gained too much help from them, but we have recieved some. + Thanks to WCell team (especially Ralek) for reseach on realm reconnect sequence, + item scaling stats algorithm, gameobject rotation issues. + The easiest policy with this file is to thank everyone who contributes to the project, without judging the value of the contribution. diff --git a/configure.ac b/configure.ac index 387c38cd1..ec2c84de2 100644 --- a/configure.ac +++ b/configure.ac @@ -14,9 +14,9 @@ ## Prelude, basic settings for Autoconf # PACKAGE: mangos -# VERSION: 0.12.0 (trunk) +# VERSION: 0.13.0 (trunk) # BUG-REPORT-ADDRESS: mangos-devs@lists.sourceforge.net -AC_INIT( [mangos], [0.12.0], [mangos-devs@lists.sourceforge.net]) +AC_INIT( [mangos], [0.13.0], [mangos-devs@lists.sourceforge.net]) AC_CONFIG_SRCDIR([src/shared/Base.cpp]) ## Prelude, basic settings for Automake diff --git a/contrib/extractor/System.cpp b/contrib/extractor/System.cpp index 978a7d2d9..85d06369f 100644 --- a/contrib/extractor/System.cpp +++ b/contrib/extractor/System.cpp @@ -16,21 +16,24 @@ extern unsigned int iRes; extern ArchiveSet gOpenArchives; -bool ConvertADT(char*,char*); +bool ConvertADT(char*, char*); -typedef struct{ +typedef struct +{ char name[64]; - unsigned int id; -}map_id; + uint32 id; +} map_id; typedef unsigned char uint8; typedef unsigned short uint16; typedef unsigned int uint32; -map_id * map_ids; -uint16 * areas; -char output_path[128]="."; -char input_path[128]="."; +map_id *map_ids; +uint16 *areas; +uint16 *LiqType; +char output_path[128] = "."; +char input_path[128] = "."; +uint32 maxAreaId = 0; enum Extract { @@ -66,46 +69,45 @@ bool FileExists( const char* FileName ) void Usage(char* prg) { - printf("Usage:\n%s -[var] [value]\n-i set input path\n-o set output path\n-r set resolution\n-e extract only MAP(1)/DBC(2) - standard: both(3)\nExample: %s -r 256 -i \"c:\\games\\game\"", - prg,prg); + printf("Usage:\n%s -[var] [value]\n-i set input path\n-o set output path\n-r set resolution\n-e extract only MAP(1)/DBC(2) - standard: both(3)\nExample: %s -r 256 -i \"c:\\games\\game\"", prg, prg); exit(1); } void HandleArgs(int argc, char * arg[]) { - for(int c=1;c 0 && extract < 4)) Usage(arg[0]); } @@ -122,12 +124,12 @@ uint32 ReadMapDBC() DBCFile dbc("DBFilesClient\\Map.dbc"); dbc.open(); - uint32 map_count=dbc.getRecordCount(); - map_ids=new map_id[map_count]; - for(unsigned int x=0;xc_str() + strlen("DBFilesClient\\")); - FILE *output=fopen(filename.c_str(), "wb"); + FILE *output = fopen(filename.c_str(), "wb"); if(!output) { printf("Can't create the output file '%s'\n", filename.c_str()); @@ -261,7 +283,9 @@ void LoadCommonMPQFiles() { char filename[512]; - sprintf(filename,"%s/Data/common.MPQ", input_path); + sprintf(filename,"%s/Data/common-2.MPQ", input_path); + new MPQArchive(filename); + sprintf(filename,"%s/Data/lichking.MPQ", input_path); new MPQArchive(filename); sprintf(filename,"%s/Data/expansion.MPQ", input_path); new MPQArchive(filename); @@ -272,7 +296,7 @@ void LoadCommonMPQFiles() if(i > 1) sprintf(ext, "-%i", i); - sprintf(filename,"%s/Data/patch%s.MPQ", input_path, ext); + sprintf(filename, "%s/Data/patch%s.MPQ", input_path, ext); if(FileExists(filename)) new MPQArchive(filename); } diff --git a/contrib/extractor/ad.exe b/contrib/extractor/ad.exe index 2dc24c087..f483f3892 100755 Binary files a/contrib/extractor/ad.exe and b/contrib/extractor/ad.exe differ diff --git a/contrib/extractor/adt.cpp b/contrib/extractor/adt.cpp index c6cb5dba0..dde87e5fc 100644 --- a/contrib/extractor/adt.cpp +++ b/contrib/extractor/adt.cpp @@ -15,16 +15,15 @@ #include "adt.h" #include "mpq_libmpq.h" -//#include -unsigned int iRes=256; -extern uint16*areas; +uint32 iRes = 256; +extern uint16 *areas; +extern uint16 *LiqType; +extern uint32 maxAreaId; vec wmoc; -Cell * cell; -uint32 wmo_count; +Cell *cell; mcell *mcells; - int holetab_h[4] = {0x1111, 0x2222, 0x4444, 0x8888}; int holetab_v[4] = {0x000F, 0x00F0, 0x0F00, 0xF000}; @@ -35,168 +34,154 @@ bool LoadADT(char* filename) if(mf.isEof()) { - //printf("No such file.\n"); + //printf("No such file %s\n", filename); return false; } - mcells=new mcell; - wmoc.x =65*TILESIZE; - wmoc.z =65*TILESIZE; + MapLiqFlag = new uint8[256]; + for(uint32 j = 0; j < 256; ++j) + MapLiqFlag[j] = 0; // no water + + MapLiqHeight = new float[16384]; + for(uint32 j = 0; j < 16384; ++j) + MapLiqHeight[j] = -999999; // no water + + mcells = new mcell; + + wmoc.x = 65 * TILESIZE; + wmoc.z = 65 * TILESIZE; size_t mcnk_offsets[256], mcnk_sizes[256]; - wmo_count=0; - bool found=false; - //uint32 fs=mf.getSize()-3; - //while (mf.getPos()offsData1 != 0) // если данные в Data1 о воде есть, то их надо конвертировать + { + // переходим по смещению из offsData1 ОТ НАЧАЛА куска + mf.seek(base_pos + LiqOffsData->offsData1); + mf.read(LiqChunkData1, 0x18); // считываем сами данные в структуру типа MH2O_Data1 + // заносим данные флага для куска + if(LiqType[LiqChunkData1->LiquidTypeId] == 0xffff) + printf("\nCan't find Liquid type for map %s\nchunk %d\n", filename, chunk_num); + else if(LiqType[LiqChunkData1->LiquidTypeId] == LIQUID_TYPE_WATER || LiqType[LiqChunkData1->LiquidTypeId] == LIQUID_TYPE_OCEAN) + MapLiqFlag[chunk_num] |= 1; // water/ocean + else if(LiqType[LiqChunkData1->LiquidTypeId] == LIQUID_TYPE_MAGMA || LiqType[LiqChunkData1->LiquidTypeId] == LIQUID_TYPE_SLIME) + MapLiqFlag[chunk_num] |= 2; // magma/slime + // предварительно заполняем весь кусок данными - нет воды + for(int j = 0; j < 81; ++j) + { + ChunkLiqHeight[j] = -999999; // no liquid/water + } + // теперь вычисляем те что с водой и перезаписываем их в куске + for(int b = 0; b <= LiqChunkData1->height; ++b) + { + for(int c = LiqChunkData1->xOffset; c <= (LiqChunkData1->xOffset + LiqChunkData1->width); ++c) + { + int n = (9 * (LiqChunkData1->yOffset + b)) + c; + ChunkLiqHeight[n] = LiqChunkData1->heightLevel1; + } + } + mf.seek(header_pos); // и не забыть вернуться на исходную позицию именно В ХИДЕРЕ + } + else // если данных в Data1 нет, то надо заполнить весь кусок, но данными - нет воды + { + for(int j = 0; j < 81; ++j) + ChunkLiqHeight[j] = -999999; // no liquid/water + } + + if(!(chunk_num % 16)) + m = 1024 * (chunk_num / 16); // смещение по рядам кусков с перекрытием = 1024 + k = m + (chunk_num % 16) * 8; // устанавливаемся на начальный индекс для заполнения ряда + // заносим данные куска в массив для карты, с перекрытием и обрезанием кусков тк данных 81 + // это аналог старого обрезания граничных правых-боковых и нижних данных + for(int p = 0; p < 72; p += 9) // нижние 8 не заносим тк они дублируется след куском + { + for(int s = 0; s < 8; ++s) // 9 значение в строке не заносим тк оно дублируется след куском, а в правых-боковых обрезается для 128х128 + { + MapLiqHeight[k] = ChunkLiqHeight[p + s]; + ++k; + } + k = k + 120; + } + } + delete LiqOffsData; + delete LiqChunkData1; + delete []ChunkLiqHeight; + + } + //case 0x4d434e4b: // MCNK + //case 0x4d46424f: // MFBO new in BC + //case 0x4d545846: // MTXF new in WotLK mf.seek(nextpos); } //printf("Loading chunks info\n"); // read individual map chunks - for (int j=0; j<16; j++) - for (int i=0; i<16; i++) - { - mf.seek((int)mcnk_offsets[j*16+i]); - LoadMapChunk(mf,&(mcells->ch[i][j])); - } - - /* - for(uint32 t=0;tch[i][j])); + ++chunk_num; + } + } mf.close(); return true; } -struct MapChunkHeader { - uint32 flags; - uint32 ix; - uint32 iy; - uint32 nLayers; - uint32 nDoodadRefs; - uint32 ofsHeight; - uint32 ofsNormal; - uint32 ofsLayer; - uint32 ofsRefs; - uint32 ofsAlpha; - uint32 sizeAlpha; - uint32 ofsShadow; - uint32 sizeShadow; - uint32 areaid; - uint32 nMapObjRefs; - uint32 holes; - uint16 s1; - uint16 s2; - uint32 d1; - uint32 d2; - uint32 d3; - uint32 predTex; - uint32 nEffectDoodad; - uint32 ofsSndEmitters; - uint32 nSndEmitters; - uint32 ofsLiquid; - uint32 sizeLiquid; - float zpos; - float xpos; - float ypos; - uint32 textureId; - uint32 props; - uint32 effectId; -}; - bool isHole(int holes, int i, int j) { - int testi = i/2; - int testj = j/4; - if(testi>3) testi = 3; - if(testj>3) testj = 3; - return (holes & holetab_h[testi] & holetab_v[testj])!=0; + int testi = i / 2; + int testj = j / 4; + if(testi > 3) testi = 3; + if(testj > 3) testj = 3; + return (holes & holetab_h[testi] & holetab_v[testj]) != 0; } -inline -void LoadMapChunk(MPQFile & mf, chunk*_chunk) +inline void LoadMapChunk(MPQFile &mf, chunk *_chunk) { float h; uint32 fourcc; @@ -207,294 +192,262 @@ void LoadMapChunk(MPQFile & mf, chunk*_chunk) mf.read(&size, 4); size_t lastpos = mf.getPos() + size; - mf.read(&header, 0x80); - _chunk->area_id =header.areaid ; - _chunk->flag =0; + mf.read(&header, 0x80); // what if header size got changed? + _chunk->area_id = header.areaid; float xbase = header.xpos; float ybase = header.ypos; float zbase = header.zpos; - zbase = TILESIZE*32-zbase; - xbase = TILESIZE*32-xbase; - if(wmoc.x >xbase)wmoc.x =xbase; - if(wmoc.z >zbase)wmoc.z =zbase; + zbase = TILESIZE * 32 - zbase; + xbase = TILESIZE * 32 - xbase; + if(wmoc.x > xbase) wmoc.x = xbase; + if(wmoc.z > zbase) wmoc.z = zbase; int chunkflags = header.flags; - float zmin=999999999.0f; - float zmax=-999999999.0f; - //must be there, bl!zz uses some crazy format - int nTextures; + //printf("LMC: flags %X\n", chunkflags); + float zmin = 999999999.0f; + float zmax = -999999999.0f; + // must be there, bl!zz uses some crazy format while (mf.getPos() < lastpos) { - mf.read(&fourcc,4); + mf.read(&fourcc, 4); mf.read(&size, 4); - //if(size!=580) - // printf("\n sz=%d",size); - size_t nextpos = mf.getPos() + size; - if(fourcc==0x4d435654) // MCVT + size_t nextpos = mf.getPos() + size; + if(fourcc == 0x4d435654) // MCVT { - for (int j=0; j<17; j++) - for (int i=0; i<((j%2)?8:9); i++) + for (int j = 0; j < 17; ++j) + { + for (int i = 0; i < ((j % 2) ? 8 : 9); ++i) { - mf.read(&h,4); - float z=h+ybase; - if (j%2) + mf.read(&h, 4); + float z = h + ybase; + if (j % 2) { - if(isHole(header.holes,i,j)) - _chunk->v8[i][j/2] = -1000; + if(isHole(header.holes, i, j)) + _chunk->v8[i][j / 2] = -1000; else - _chunk->v8[i][j/2] = z; + _chunk->v8[i][j / 2] = z; } else { - if(isHole(header.holes,i,j)) - _chunk->v9[i][j/2] = -1000; + if(isHole(header.holes, i, j)) + _chunk->v9[i][j / 2] = -1000; else - _chunk->v9[i][j/2] = z; + _chunk->v9[i][j / 2] = z; } - if(z>zmax)zmax=z; - //if(z zmax) zmax = z; + //if(z < zmin) zmin = z; } + } } - else if(fourcc==0x4d434e52) // MCNR + else if(fourcc == 0x4d434e52) // MCNR { - nextpos = mf.getPos() + 0x1C0; // size fix + nextpos = mf.getPos() + 0x1C0; // size fix } - else if(fourcc==0x4d434c51) // MCLQ + else if(fourcc == 0x4d434c51) // не будем учитывать если уже были данные в MH2O, перестраховка :) // MCLQ { // liquid / water level - //bool haswater; char fcc1[5]; - mf.read(fcc1,4); + mf.read(fcc1, 4); flipcc(fcc1); - fcc1[4]=0; + fcc1[4] = 0; + float *ChunkLiqHeight = new float[81]; - if (!strcmp(fcc1,"MCSE")) + if (!strcmp(fcc1, "MCSE")) { - for(int i=0;i<9;i++) - for(int j=0;j<9;j++) - _chunk->waterlevel[i][j]=-999999; // no liquid/water + for(int j = 0; j < 81; ++j) + { + ChunkLiqHeight[j] = -999999; // no liquid/water + } } else { float maxheight; mf.read(&maxheight, 4); + for(int j = 0; j < 81; ++j) + { + LiqData liq; + mf.read(&liq, 8); - for(int j=0;j<9;j++) - for(int i=0;i<9;i++) - { - mf.read(&h, 4); - mf.read(&h, 4); - if(h > maxheight) - _chunk->waterlevel[i][j]=-999999; - else - _chunk->waterlevel[i][j]=h; - } + if(liq.height > maxheight) + ChunkLiqHeight[j] = -999999; + else + ChunkLiqHeight[j] = h; + } if(chunkflags & 4 || chunkflags & 8) - _chunk->flag |=1; + MapLiqFlag[chunk_num] |= 1; // water if(chunkflags & 16) - _chunk->flag |=2; + MapLiqFlag[chunk_num] |= 2; // magma/slime } + // заполнем так же как в MH2O + if(!(chunk_num % 16)) + m = 1024 * (chunk_num / 16); + k = m + (chunk_num % 16) * 8; + + for(int p = 0; p < 72; p += 9) + { + for(int s = 0; s < 8; ++s) + { + MapLiqHeight[k] = ChunkLiqHeight[p + s]; + ++k; + } + k = k + 120; + } + delete []ChunkLiqHeight; break; } - else if (fourcc==0x4d434c59) // MCLY - { - // texture info - nTextures = (int)size; - } - else if (fourcc==0x4d43414c) // MCAL - { - if (nTextures<=0) - continue; - } - mf.seek(nextpos); } } double solve (vec *v,vec *p) { - double a = v[0].y *(v[1].z - v[2].z) + v[1].y *(v[2].z - v[0].z) + v[2].y *(v[0].z - v[1].z); - double b = v[0].z *(v[1].x - v[2].x) + v[1].z *(v[2].x - v[0].x) + v[2].z *(v[0].x - v[1].x); - double c = v[0].x *(v[1].y - v[2].y) + v[1].x *(v[2].y - v[0].y) + v[2].x *(v[0].y - v[1].y); - double d = v[0].x *(v[1].y*v[2].z - v[2].y*v[1].z) + v[1].x* (v[2].y*v[0].z - v[0].y*v[2].z) + v[2].x* (v[0].y*v[1].z - v[1].y*v[0].z); - //-d + double a = v[0].y * (v[1].z - v[2].z) + v[1].y * (v[2].z - v[0].z) + v[2].y * (v[0].z - v[1].z); + double b = v[0].z * (v[1].x - v[2].x) + v[1].z * (v[2].x - v[0].x) + v[2].z * (v[0].x - v[1].x); + double c = v[0].x * (v[1].y - v[2].y) + v[1].x * (v[2].y - v[0].y) + v[2].x * (v[0].y - v[1].y); + double d = v[0].x * (v[1].y * v[2].z - v[2].y * v[1].z) + v[1].x * (v[2].y * v[0].z - v[0].y * v[2].z) + v[2].x * (v[0].y * v[1].z - v[1].y * v[0].z); + // -d - //plane equation ax+by+cz+d=0 + // plane equation ax+by+cz+d=0 return ((a*p->x+c*p->z-d)/b); } -inline -double GetZ(double x,double z) +inline double GetZ(double x, double z) { vec v[3]; vec p; - - //bool inWMO=false; - - //if(!inWMO) { - //find out quadrant - int xc=(int)(x/UNITSIZE); - int zc=(int)(z/UNITSIZE); - if(xc>127)xc=127; - if(zc>127)zc=127; + // find out quadrant + int xc = (int)(x / UNITSIZE); + int zc = (int)(z / UNITSIZE); + if(xc > 127) xc = 127; + if(zc > 127) zc = 127; - double lx=x-xc*UNITSIZE; - double lz=z-zc*UNITSIZE; - p.x=lx; - p.z=lz; + double lx = x - xc * UNITSIZE; + double lz = z - zc * UNITSIZE; + p.x = lx; + p.z = lz; - v[0].x=UNITSIZE/2; - v[0].y =cell->v8[xc][zc]; - v[0].z=UNITSIZE/2; + v[0].x = UNITSIZE / 2; + v[0].y = cell->v8[xc][zc]; + v[0].z = UNITSIZE / 2; - if(lx>lz) + if(lx > lz) { - v[1].x=UNITSIZE; - v[1].y =cell->v9[xc+1][zc]; - v[1].z=0; + v[1].x = UNITSIZE; + v[1].y = cell->v9[xc + 1][zc]; + v[1].z = 0.0f; } else { - v[1].x=0.0; - v[1].y =cell->v9[xc][zc+1]; - v[1].z=UNITSIZE; + v[1].x = 0.0f; + v[1].y = cell->v9[xc][zc + 1]; + v[1].z = UNITSIZE; } - if(lz>UNITSIZE-lx) + if(lz > UNITSIZE - lx) { - v[2].x=UNITSIZE; - v[2].y =cell->v9[xc+1][zc+1]; - v[2].z=UNITSIZE; + v[2].x = UNITSIZE; + v[2].y = cell->v9[xc + 1][zc + 1]; + v[2].z = UNITSIZE; } else { - v[2].x=0; - v[2].y=cell->v9[xc][zc]; - v[2].z=0; + v[2].x = 0.0f; + v[2].y = cell->v9[xc][zc]; + v[2].z = 0.0f; } - return -solve(v,&p); + return -solve(v, &p); } } -inline -void TransformWaterData() +inline void TransformData() { - cell= new Cell; + cell = new Cell; - for(int x=0;x<128;x++) - for(int y=0;y<128;y++) - cell->v9[x][y] = mcells->ch[x/8][y/8].waterlevel[x%8][y%8]; - - //and the last 1 - cell->v9[128][128] = mcells->ch[15][15].waterlevel[8][8]; -} - -inline -void TransformData() -{ - cell= new Cell; - - for(int x=0;x<128;x++) + for(uint32 x = 0; x < 128; ++x) { - for(int y=0;y<128;y++) + for(uint32 y = 0; y < 128; ++y) { - cell->v8[x][y] = (float)mcells->ch[x/8][y/8].v8[x%8][y%8]; - cell->v9[x][y] = (float)mcells->ch[x/8][y/8].v9[x%8][y%8]; + cell->v8[x][y] = (float)mcells->ch[x / 8][y / 8].v8[x % 8][y % 8]; + cell->v9[x][y] = (float)mcells->ch[x / 8][y / 8].v9[x % 8][y % 8]; } - //extra 1 point on bounds - cell->v9[x][128] = (float)mcells->ch[x/8][15].v9[x%8][8]; - //x==y - cell->v9[128][x] = (float)mcells->ch[15][x/8].v9[8][x%8]; + // extra 1 point on bounds + cell->v9[x][128] = (float)mcells->ch[x / 8][15].v9[x % 8][8]; + // x == y + cell->v9[128][x] = (float)mcells->ch[15][x / 8].v9[8][x % 8]; } - //and the last 1 + // and the last 1 cell->v9[128][128] = (float)mcells->ch[15][15].v9[8][8]; delete mcells; } -const char MAP_MAGIC[] = "MAP_2.00"; +const char MAP_MAGIC[] = "MAP_2.01"; -bool ConvertADT(char * filename,char * filename2) +bool ConvertADT(char *filename, char *filename2) { - //if(!strstr(filename,"oth_32_48"))return false; if(!LoadADT(filename)) return false; - FILE *output=fopen(filename2,"wb"); + FILE *output=fopen(filename2, "wb"); if(!output) { - printf("Can't create the output file '%s'\n",filename2); + printf("Can't create the output file '%s'\n", filename2); + delete [] MapLiqHeight; + delete [] MapLiqFlag; return false; } // write magic header - fwrite(MAP_MAGIC,1,8,output); + fwrite(MAP_MAGIC, 1, 8, output); - for(unsigned int x=0;x<16;x++) + for(uint32 x = 0; x < 16; ++x) { - for(unsigned int y=0;y<16;y++) + for(uint32 y = 0; y < 16; ++y) { - if(mcells->ch[y][x].area_id && mcells->ch[y][x].area_id < 0x102D) + if(mcells->ch[y][x].area_id && mcells->ch[y][x].area_id <= maxAreaId) { - if(areas[mcells->ch[y][x].area_id]==0xffff) - printf("\nCan't find area flag for areaid %u.\n",mcells->ch[y][x].area_id); + if(areas[mcells->ch[y][x].area_id] == 0xffff) + printf("\nCan't find area flag for areaid %u.\n", mcells->ch[y][x].area_id); - fwrite(&areas[mcells->ch[y][x].area_id],1,2,output); + fwrite(&areas[mcells->ch[y][x].area_id], 1, 2, output); } else { - uint16 flag=0xffff; - fwrite(&flag,1,2,output); + uint16 flag = 0xffff; + fwrite(&flag, 1, 2, output); } } } - for(unsigned int x=0;x<16;x++) - for(unsigned int y=0;y<16;y++) - fwrite(&mcells->ch[y][x].flag,1,1,output); + fwrite(MapLiqFlag, 1, 256, output); + delete [] MapLiqFlag; - TransformWaterData(); + fwrite(MapLiqHeight, sizeof(float), 16384, output); + delete [] MapLiqHeight; - for(unsigned int x=0;x<128;x++) - for(unsigned int y=0;y<128;y++) - fwrite(&cell->v9[y][x],1,sizeof(float),output); - - delete cell; TransformData(); - for(unsigned int x=0;x::iterator it = wmos.begin(); it != wmos.end(); ++it) - wmomanager.delbyname(*it); - - wmos.clear(); - wmois.clear(); - - for (std::vector::iterator it = wmomodel.begin(); it != wmomodel.end(); ++it) - { - it->tr.clear(); - - } - //printf("\n %d \n",in); - wmomodel.clear(); - //polygons.clear();*/ + return true; } diff --git a/contrib/extractor/adt.h b/contrib/extractor/adt.h index bae687f6b..52196c4e7 100644 --- a/contrib/extractor/adt.h +++ b/contrib/extractor/adt.h @@ -9,45 +9,120 @@ typedef unsigned char uint8; typedef unsigned short uint16; typedef unsigned int uint32; class Liquid; -typedef struct { -float x; -float y; -float z; -}svec; - -typedef struct { -double x; -double y; -double z; -}vec; - -typedef struct{ - vec v[3]; -}triangle; - -typedef struct{ -float v9[16*8+1][16*8+1]; -float v8[16*8][16*8]; -}Cell; - -typedef struct{ -double v9[9][9]; -double v8[8][8]; -uint16 area_id; -//Liquid *lq; -float waterlevel[9][9]; -uint8 flag; -}chunk; - -class WMO; -class WMOManager; -void fixname(std::string &name); +typedef struct +{ + float x; + float y; + float z; +} svec; typedef struct { -chunk ch[16][16]; -}mcell; + double x; + double y; + double z; +} vec; + +typedef struct +{ + vec v[3]; +} triangle; + +typedef struct +{ + float v9[16 * 8 + 1][16 * 8 + 1]; + float v8[16 * 8][16 * 8]; +} Cell; + +typedef struct +{ + double v9[9][9]; + double v8[8][8]; + uint16 area_id; +} chunk; + +typedef struct +{ + chunk ch[16][16]; +} mcell; + +struct MapChunkHeader +{ + uint32 flags; + uint32 ix; + uint32 iy; + uint32 nLayers; + uint32 nDoodadRefs; + uint32 ofsHeight; + uint32 ofsNormal; + uint32 ofsLayer; + uint32 ofsRefs; + uint32 ofsAlpha; + uint32 sizeAlpha; + uint32 ofsShadow; + uint32 sizeShadow; + uint32 areaid; + uint32 nMapObjRefs; + uint32 holes; + uint16 s1; + uint16 s2; + uint32 d1; + uint32 d2; + uint32 d3; + uint32 predTex; + uint32 nEffectDoodad; + uint32 ofsSndEmitters; + uint32 nSndEmitters; + uint32 ofsLiquid; // not use in WotLK + uint32 sizeLiquid; // not use in WotLK + float zpos; + float xpos; + float ypos; + uint32 textureId; // new offsColorValues in WotLK + uint32 props; + uint32 effectId; +}; + +typedef struct +{ + uint32 offsData1; + uint32 used; + uint32 offsData2; +} MH2O_offsData; + +typedef struct +{ + uint16 LiquidTypeId; + uint16 type; + float heightLevel1; + float heightLevel2; + uint8 xOffset; + uint8 yOffset; + uint8 width; + uint8 height; + uint32 ofsData2a; + uint32 ofsData2b; +} MH2O_Data1; + +typedef struct +{ + uint16 unk1; + uint16 unk2; + float height; +} LiqData; + +enum LiquidType +{ + LIQUID_TYPE_WATER = 0, + LIQUID_TYPE_OCEAN = 1, + LIQUID_TYPE_MAGMA = 2, + LIQUID_TYPE_SLIME = 3 +}; + class MPQFile; -void LoadMapChunk(MPQFile &,chunk*); -bool LoadWMO(char* filename); + +float *MapLiqHeight; +uint8 *MapLiqFlag; +uint32 k, m, chunk_num; +void LoadMapChunk(MPQFile &, chunk*); #endif diff --git a/contrib/vmap_extract_assembler_bin/vmap_assembler.exe b/contrib/vmap_extract_assembler_bin/vmap_assembler.exe index 5cb08f770..a6ef74dc0 100644 Binary files a/contrib/vmap_extract_assembler_bin/vmap_assembler.exe and b/contrib/vmap_extract_assembler_bin/vmap_assembler.exe differ diff --git a/contrib/vmap_extract_assembler_bin/vmapextract_v2.exe b/contrib/vmap_extract_assembler_bin/vmapextract_v2.exe index c38b6e64f..03c769076 100644 Binary files a/contrib/vmap_extract_assembler_bin/vmapextract_v2.exe and b/contrib/vmap_extract_assembler_bin/vmapextract_v2.exe differ diff --git a/contrib/vmap_extractor_v2/vmapextract/model.cpp b/contrib/vmap_extractor_v2/vmapextract/model.cpp index 7dca7841d..1d0c17d52 100644 --- a/contrib/vmap_extractor_v2/vmapextract/model.cpp +++ b/contrib/vmap_extractor_v2/vmapextract/model.cpp @@ -1,11 +1,7 @@ -//#include "common.h" #include "model.h" -//#include "world.h" #include #include -//int globalTime = 0; - Model::Model(std::string &filename) : filename(filename) { } @@ -24,121 +20,31 @@ bool Model::open() } memcpy(&header, f.getBuffer(), sizeof(ModelHeader)); - if(header.nBoundingTriangles > 0) { - -#if 0 - animated = isAnimated(f); - if(animated) + if(header.nBoundingTriangles > 0) + { + f.seek(0); + f.seekRelative(header.ofsBoundingVertices); + vertices = new Vec3D[header.nBoundingVertices]; + f.read(vertices,header.nBoundingVertices*12); + for (uint32 i=0; iofsIndex); - uint16 *triangles = (uint16*)(f.getBuffer() + view->ofsTris); - - nIndices = view->nTris; - indices = new uint16[nIndices]; - for (size_t i = 0; i0) { - ModelBoneDef &bb = bo[verts[i].bones[b]]; - if (bb.translation.type || bb.rotation.type || bb.scaling.type || (bb.flags&8)) { - if (bb.flags&8) { - // if we have billboarding, the model will need per-instance animation - ind = true; - } - animGeometry = true; - break; - } - } - } - } - - if (animGeometry) animBones = true; - else { - for (size_t i=0; i 0; - - bool animMisc = header.nCameras>0 || // why waste time, pretty much all models with cameras need animation - header.nLights>0 || // same here - header.nParticleEmitters>0 || - header.nRibbonEmitters>0; - - if (animMisc) animBones = true; - - // animated colors - if (header.nColors) { - ModelColorDef *cols = (ModelColorDef*)(f.getBuffer() + header.ofsColors); - for (size_t i=0; i0) + fwrite(&nIndexes, sizeof(uint32), 1, output); + if(nIndexes >0) { - fwrite(indices, sizeof(unsigned short), nIdexes, output); + fwrite(indices, sizeof(unsigned short), nIndexes, output); } fwrite("VERT",4, 1, output); wsize = sizeof(int) + sizeof(float) * 3 * nVertices; @@ -178,7 +86,7 @@ bool Model::ConvertToVMAPModel(char * outfilename) fwrite(&nVertices, sizeof(int), 1, output); if(nVertices >0) { - for(int vpos=0; vpos class Model; @@ -18,18 +17,14 @@ Vec3D fixCoordSystem(Vec3D v); class Model { public: + ModelHeader header; - ModelAnimation *anims; - int *globalSequences; public: - bool animGeometry,animTextures,animBones; - bool animated; - bool isAnimated(MPQFile &f); - ModelVertex *origVertices; - Vec3D *vertices, *normals; - uint16 *indices; + uint32 offsBB_vertices, offsBB_indices; + Vec3D *BB_vertices, *vertices; + uint16 *BB_indices, *indices; size_t nIndices; bool open(); @@ -38,12 +33,6 @@ public: public: bool ok; - bool ind; - - float rad; - float trans; - bool animcalc; - int anim, animtime; Model(std::string &filename); ~Model(); @@ -59,15 +48,9 @@ public: Model *model; int id; - Vec3D pos, rot; unsigned int d1, scale; - - float frot,w,sc; - - int light; - Vec3D ldir; - Vec3D lcol; + float w,sc; ModelInstance() {} ModelInstance(MPQFile &f,const char* ModelInstName,const char*MapName, FILE *pDirfile); diff --git a/contrib/vmap_extractor_v2/vmapextract/modelheaders.h b/contrib/vmap_extractor_v2/vmapextract/modelheaders.h index 7d5e800e7..c35b983c1 100644 --- a/contrib/vmap_extractor_v2/vmapextract/modelheaders.h +++ b/contrib/vmap_extractor_v2/vmapextract/modelheaders.h @@ -15,289 +15,67 @@ struct ModelHeader { uint8 version[4]; uint32 nameLength; uint32 nameOfs; - uint32 type; - + uint32 type; uint32 nGlobalSequences; uint32 ofsGlobalSequences; uint32 nAnimations; uint32 ofsAnimations; - uint32 nC; - uint32 ofsC; - uint32 nD; - uint32 ofsD; - uint32 nBones; - uint32 ofsBones; - uint32 nF; - uint32 ofsF; - + uint32 nAnimationLookup; + uint32 ofsAnimationLookup; + uint32 nBones; + uint32 ofsBones; + uint32 nKeyBoneLookup; + uint32 ofsKeyBoneLookup; uint32 nVertices; uint32 ofsVertices; uint32 nViews; - uint32 ofsViews; - uint32 nColors; uint32 ofsColors; - uint32 nTextures; uint32 ofsTextures; - - uint32 nTransparency; // H + uint32 nTransparency; uint32 ofsTransparency; - uint32 nI; // always unused ? - uint32 ofsI; - uint32 nTexAnims; // J - uint32 ofsTexAnims; - uint32 nK; - uint32 ofsK; - - uint32 nTexFlags; - uint32 ofsTexFlags; - uint32 nY; - uint32 ofsY; - - uint32 nTexLookup; - uint32 ofsTexLookup; - - uint32 nTexUnitLookup; // L - uint32 ofsTexUnitLookup; - uint32 nTransparencyLookup; // M - uint32 ofsTransparencyLookup; - uint32 nTexAnimLookup; - uint32 ofsTexAnimLookup; - - float floats[14]; - - uint32 nBoundingTriangles; - uint32 ofsBoundingTriangles; - uint32 nBoundingVertices; - uint32 ofsBoundingVertices; - uint32 nBoundingNormals; - uint32 ofsBoundingNormals; - - uint32 nO; - uint32 ofsO; - uint32 nP; - uint32 ofsP; - uint32 nQ; - uint32 ofsQ; - uint32 nLights; // R - uint32 ofsLights; - uint32 nCameras; // S - uint32 ofsCameras; - uint32 nT; - uint32 ofsT; - uint32 nRibbonEmitters; // U - uint32 ofsRibbonEmitters; - uint32 nParticleEmitters; // V - uint32 ofsParticleEmitters; - + uint32 nTextureanimations; + uint32 ofsTextureanimations; + uint32 nTexReplace; + uint32 ofsTexReplace; + uint32 nRenderFlags; + uint32 ofsRenderFlags; + uint32 nBoneLookupTable; + uint32 ofsBoneLookupTable; + uint32 nTexLookup; + uint32 ofsTexLookup; + uint32 nTexUnits; + uint32 ofsTexUnits; + uint32 nTransLookup; + uint32 ofsTransLookup; + uint32 nTexAnimLookup; + uint32 ofsTexAnimLookup; + float floats[14]; + uint32 nBoundingTriangles; + uint32 ofsBoundingTriangles; + uint32 nBoundingVertices; + uint32 ofsBoundingVertices; + uint32 nBoundingNormals; + uint32 ofsBoundingNormals; + uint32 nAttachments; + uint32 ofsAttachments; + uint32 nAttachLookup; + uint32 ofsAttachLookup; + uint32 nAttachments_2; + uint32 ofsAttachments_2; + uint32 nLights; + uint32 ofsLights; + uint32 nCameras; + uint32 ofsCameras; + uint32 nCameraLookup; + uint32 ofsCameraLookup; + uint32 nRibbonEmitters; + uint32 ofsRibbonEmitters; + uint32 nParticleEmitters; + uint32 ofsParticleEmitters; }; -// block B - animations -struct ModelAnimation { - uint32 animID; - uint32 timeStart; - uint32 timeEnd; - - float moveSpeed; - - uint32 loopType; - uint32 flags; - uint32 d1; - uint32 d2; - uint32 playSpeed; // note: this can't be play speed because it's 0 for some models - - Vec3D boxA, boxB; - float rad; - - int16 s[2]; -}; - - -// sub-block in block E - animation data -struct AnimationBlock { - int16 type; // interpolation type (0=none, 1=linear, 2=hermite) - int16 seq; // global sequence id or -1 - uint32 nRanges; - uint32 ofsRanges; - uint32 nTimes; - uint32 ofsTimes; - uint32 nKeys; - uint32 ofsKeys; -}; - -// block E - bones -struct ModelBoneDef { - int32 animid; - int32 flags; - int16 parent; // parent bone index - int16 geoid; - // new int added to the bone definitions. Added in WoW 2.0 - int32 unknown; - AnimationBlock translation; - AnimationBlock rotation; - AnimationBlock scaling; - Vec3D pivot; -}; - -struct ModelTexAnimDef { - AnimationBlock trans, rot, scale; -}; - -struct ModelVertex { - Vec3D pos; - uint8 weights[4]; - uint8 bones[4]; - Vec3D normal; - Vec2D texcoords; - int unk1, unk2; // always 0,0 so this is probably unused -}; - -struct ModelView { - uint32 nIndex, ofsIndex; // Vertices in this model (index into vertices[]) - uint32 nTris, ofsTris; // indices - uint32 nProps, ofsProps; // additional vtx properties - uint32 nSub, ofsSub; // materials/renderops/submeshes - uint32 nTex, ofsTex; // material properties/textures - int32 lod; // LOD bias? -}; - - -/// One material + render operation -struct ModelGeoset { - uint16 d1; // mesh part id? - uint16 d2; // ? - uint16 vstart; // first vertex - uint16 vcount; // num vertices - uint16 istart; // first index - uint16 icount; // num indices - uint16 d3; // number of bone indices - uint16 d4; // offset into bone index list - uint16 d5; // ? - uint16 d6; // root bone? - Vec3D v; - float unknown[4]; // Added in WoW 2.0? -}; - -/// A texture unit (sub of material) -struct ModelTexUnit{ - // probably the texture units - // size always >=number of materials it seems - uint16 flags; // Flags - uint16 order; // ? - uint16 op; // Material this texture is part of (index into mat) - uint16 op2; // Always same as above? - int16 colorIndex; // color or -1 - uint16 flagsIndex; // more flags... - uint16 texunit; // Texture unit (0 or 1) - uint16 d4; // ? (seems to be always 1) - uint16 textureid; // Texture id (index into global texture list) - uint16 texunit2; // copy of texture unit value? - uint16 transid; // transparency id (index into transparency list) - uint16 texanimid; // texture animation id -}; - -// block X - render flags -struct ModelRenderFlags { - uint16 flags; - uint16 blend; -}; - -// block G - color defs -struct ModelColorDef { - AnimationBlock color; - AnimationBlock opacity; -}; - -// block H - transp defs -struct ModelTransDef { - AnimationBlock trans; -}; - -struct ModelTextureDef { - uint32 type; - uint32 flags; - uint32 nameLen; - uint32 nameOfs; -}; - -struct ModelLightDef { - int16 type; - int16 bone; - Vec3D pos; - AnimationBlock ambColor; - AnimationBlock ambIntensity; - AnimationBlock color; - AnimationBlock intensity; - AnimationBlock attStart; - AnimationBlock attEnd; - AnimationBlock unk1; -}; - -struct ModelCameraDef { - int32 id; - float fov, farclip, nearclip; - AnimationBlock transPos; - Vec3D pos; - AnimationBlock transTarget; - Vec3D target; - AnimationBlock rot; -}; - - -struct ModelParticleParams { - float mid; - uint32 colors[3]; - float sizes[3]; - int16 d[10]; - float unk[3]; - float scales[3]; - float slowdown; - float rotation; - float f2[16]; -}; - -struct ModelParticleEmitterDef { - int32 id; - int32 flags; - Vec3D pos; - int16 bone; - int16 texture; - int32 nZero1; - int32 ofsZero1; - int32 nZero2; - int32 ofsZero2; - int16 blend; - int16 type; - int16 s1; - int16 s2; - int16 cols; - int16 rows; - AnimationBlock params[10]; - ModelParticleParams p; - AnimationBlock unk; -}; - - -struct ModelRibbonEmitterDef { - int32 id; - int32 bone; - Vec3D pos; - int32 nTextures; - int32 ofsTextures; - int32 nUnknown; - int32 ofsUnknown; - AnimationBlock color; - AnimationBlock opacity; - AnimationBlock above; - AnimationBlock below; - float res, length, unk; - int16 s1, s2; - AnimationBlock unk1; - AnimationBlock unk2; -}; - - #pragma pack(pop) diff --git a/contrib/vmap_extractor_v2/vmapextract/vmapexport.cpp b/contrib/vmap_extractor_v2/vmapextract/vmapexport.cpp index dfc7cddcf..0d2b39f8d 100644 --- a/contrib/vmap_extractor_v2/vmapextract/vmapexport.cpp +++ b/contrib/vmap_extractor_v2/vmapextract/vmapexport.cpp @@ -421,6 +421,10 @@ bool fillArchiveNameVector(std::vector& pArchiveNames) { // open expansion and common files printf("Opening data files from data directory.\n"); + sprintf(path, "%slichking.mpq", input_path); + pArchiveNames.push_back(path); + sprintf(path, "%scommon-2.mpq", input_path); + pArchiveNames.push_back(path); sprintf(path, "%sexpansion.mpq", input_path); pArchiveNames.push_back(path); sprintf(path, "%scommon.mpq", input_path); @@ -432,6 +436,8 @@ bool fillArchiveNameVector(std::vector& pArchiveNames) { for (std::vector::iterator i = locales.begin(); i != locales.end(); i++) { printf("Locale: %s\n", i->c_str()); + sprintf(path, "%s%s\\lichking-locale-%s.mpq", input_path, i->c_str(), i->c_str()); + pArchiveNames.push_back(path); sprintf(path, "%s%s\\expansion-locale-%s.mpq", input_path, i->c_str(), i->c_str()); pArchiveNames.push_back(path); sprintf(path, "%s%s\\locale-%s.mpq", input_path, i->c_str(), i->c_str()); diff --git a/sql/characters.sql b/sql/characters.sql index f73ca3c78..0dffc512e 100644 --- a/sql/characters.sql +++ b/sql/characters.sql @@ -21,7 +21,7 @@ DROP TABLE IF EXISTS `character_db_version`; CREATE TABLE `character_db_version` ( - `required_2008_12_03_01_character_guild_member` bit(1) default NULL + `required_2008_12_22_19_characters_item_instance` bit(1) default NULL ) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=FIXED COMMENT='Last applied sql update to DB'; -- @@ -35,6 +35,28 @@ INSERT INTO `character_db_version` VALUES /*!40000 ALTER TABLE `character_db_version` ENABLE KEYS */; UNLOCK TABLES; +-- +-- Table structure for table `account_data` +-- + +DROP TABLE IF EXISTS `account_data`; +CREATE TABLE `account_data` ( + `account` int(11) unsigned NOT NULL default '0', + `type` int(11) unsigned NOT NULL default '0', + `time` bigint(11) unsigned NOT NULL default '0', + `data` longtext NOT NULL, + PRIMARY KEY (`account`,`type`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + +-- +-- Dumping data for table `account_data` +-- + +LOCK TABLES `account_data` WRITE; +/*!40000 ALTER TABLE `account_data` DISABLE KEYS */; +/*!40000 ALTER TABLE `account_data` ENABLE KEYS */; +UNLOCK TABLES; + -- -- Table structure for table `arena_team` -- @@ -73,7 +95,8 @@ CREATE TABLE `arena_team_member` ( `played_week` int(10) unsigned NOT NULL default '0', `wons_week` int(10) unsigned NOT NULL default '0', `played_season` int(10) unsigned NOT NULL default '0', - `wons_season` int(10) unsigned NOT NULL default '0' + `wons_season` int(10) unsigned NOT NULL default '0', + `personal_rating` int(10) UNSIGNED NOT NULL DEFAULT '0' ) ENGINE=InnoDB DEFAULT CHARSET=utf8; -- @@ -201,6 +224,7 @@ CREATE TABLE `characters` ( `zone` int(11) unsigned NOT NULL default '0', `death_expire_time` bigint(20) unsigned NOT NULL default '0', `taxi_path` text, + `arena_pending_points` int(10) UNSIGNED NOT NULL default '0', PRIMARY KEY (`guid`), KEY `idx_account` (`account`), KEY `idx_online` (`online`), @@ -216,6 +240,49 @@ LOCK TABLES `characters` WRITE; /*!40000 ALTER TABLE `characters` ENABLE KEYS */; UNLOCK TABLES; +-- +-- Table structure for table `character_achievement` +-- + +DROP TABLE IF EXISTS `character_achievement`; +CREATE TABLE `character_achievement` ( + `guid` int(11) NOT NULL, + `achievement` int(11) NOT NULL, + `date` int(11) NOT NULL, + PRIMARY KEY (`guid`,`achievement`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; + +-- +-- Dumping data for table `character_achievement` +-- + +LOCK TABLES `character_achievement` WRITE; +/*!40000 ALTER TABLE `character_achievement` DISABLE KEYS */; +/*!40000 ALTER TABLE `character_achievement` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `character_achievement_progress` +-- + +DROP TABLE IF EXISTS `character_achievement_progress`; +CREATE TABLE `character_achievement_progress` ( + `guid` int(11) NOT NULL, + `criteria` int(11) NOT NULL, + `counter` int(11) NOT NULL, + `date` int(11) NOT NULL, + PRIMARY KEY (`guid`,`criteria`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; + +-- +-- Dumping data for table `character_achievement_progress` +-- + +LOCK TABLES `character_achievement_progress` WRITE; +/*!40000 ALTER TABLE `character_achievement_progress` DISABLE KEYS */; +/*!40000 ALTER TABLE `character_achievement_progress` ENABLE KEYS */; +UNLOCK TABLES; + -- -- Table structure for table `character_action` -- @@ -398,9 +465,7 @@ CREATE TABLE `character_pet` ( `level` int(11) unsigned NOT NULL default '1', `exp` int(11) unsigned NOT NULL default '0', `Reactstate` tinyint(1) unsigned NOT NULL default '0', - `loyaltypoints` int(11) NOT NULL default '0', - `loyalty` int(11) unsigned NOT NULL default '0', - `trainpoint` int(11) NOT NULL default '0', + `talentpoints` int(11) unsigned NOT NULL default '0', `name` varchar(100) default 'Pet', `renamed` tinyint(1) unsigned NOT NULL default '0', `slot` int(11) unsigned NOT NULL default '0', @@ -1222,6 +1287,7 @@ CREATE TABLE `petition_sign` ( `type` int(10) unsigned NOT NULL default '0', PRIMARY KEY (`petitionguid`,`playerguid`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC COMMENT='Guild System'; + -- -- Dumping data for table `petition_sign` -- @@ -1232,6 +1298,26 @@ LOCK TABLES `petition_sign` WRITE; UNLOCK TABLES; /*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */; +-- +-- Table structure for table `saved_variables` +-- + +DROP TABLE IF EXISTS `saved_variables`; +CREATE TABLE `saved_variables` ( + `NextArenaPointDistributionTime` bigint(40) UNSIGNED NOT NULL DEFAULT '0' +) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=FIXED COMMENT='Variable Saves'; + +-- +-- Dumping data for table `saved_variables` +-- + +LOCK TABLES `saved_variables` WRITE; +/*!40000 ALTER TABLE `saved_variables` DISABLE KEYS */; +/*!40000 ALTER TABLE `saved_variables` ENABLE KEYS */; +UNLOCK TABLES; +/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */; + + /*!40101 SET SQL_MODE=@OLD_SQL_MODE */; /*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */; /*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */; diff --git a/sql/mangos.sql b/sql/mangos.sql index 7c5817f30..6cf7f0541 100644 --- a/sql/mangos.sql +++ b/sql/mangos.sql @@ -22,7 +22,7 @@ DROP TABLE IF EXISTS `db_version`; CREATE TABLE `db_version` ( `version` varchar(120) default NULL, - `required_2008_11_29_02_mangos_spell_elixir` bit(1) default NULL + `required_2008_12_22_17_mangos_item_template` bit(1) default NULL ) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=FIXED COMMENT='Used DB version notes'; -- @@ -251,6 +251,7 @@ INSERT INTO `command` VALUES ('event start',2,'Syntax: .event start #event_id\r\nStart event #event_id. Set start time for event to current moment (change not saved in DB).'), ('event stop',2,'Syntax: .event stop #event_id\r\nStop event #event_id. Set start time for event to time in past that make current moment is event stop time (change not saved in DB).'), ('explorecheat',3,'Syntax: .explorecheat #flag\r\n\r\nReveal or hide all maps for the selected player. If no player is selected, hide or reveal maps to you.\r\n\r\nUse a #flag of value 1 to reveal, use a #flag value of 0 to hide all maps.'), +('flusharenapoints','3','Syntax: .flusharenapoints\r\n\r\nUse it to distribute arena points based on arena team ratings, and start a new week.'), ('gm',1,'Syntax: .gm [on/off]\r\n\r\nEnable or Disable in game GM MODE or show current state of on/off not provided.'), ('gm chat',1,'Syntax: .gm chat [on/off]\r\n\r\nEnable or disable chat GM MODE (show gm badge in messages) or show current state of on/off not provided.'), ('gm fly',3,'Syntax: .gm fly on/off\r\nEnable/disable gm fly mode.'), @@ -519,15 +520,9 @@ UNLOCK TABLES; DROP TABLE IF EXISTS `creature_equip_template`; CREATE TABLE `creature_equip_template` ( `entry` mediumint(8) unsigned NOT NULL default '0' COMMENT 'Unique entry', - `equipmodel1` mediumint(8) unsigned NOT NULL default '0', - `equipmodel2` mediumint(8) unsigned NOT NULL default '0', - `equipmodel3` mediumint(8) unsigned NOT NULL default '0', - `equipinfo1` int(10) unsigned NOT NULL default '0', - `equipinfo2` int(10) unsigned NOT NULL default '0', - `equipinfo3` int(10) unsigned NOT NULL default '0', - `equipslot1` int(11) NOT NULL default '0', - `equipslot2` int(11) NOT NULL default '0', - `equipslot3` int(11) NOT NULL default '0', + `equipentry1` mediumint(8) unsigned NOT NULL default '0', + `equipentry2` mediumint(8) unsigned NOT NULL default '0', + `equipentry3` mediumint(8) unsigned NOT NULL default '0', PRIMARY KEY (`entry`) ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COMMENT='Creature System (Equipment)'; @@ -1547,6 +1542,7 @@ CREATE TABLE `item_template` ( `maxcount` smallint(5) unsigned NOT NULL default '0', `stackable` smallint(5) unsigned NOT NULL default '1', `ContainerSlots` tinyint(3) unsigned NOT NULL default '0', + `StatsCount` tinyint(3) unsigned NOT NULL default '0', `stat_type1` tinyint(3) unsigned NOT NULL default '0', `stat_value1` smallint(6) NOT NULL default '0', `stat_type2` tinyint(3) unsigned NOT NULL default '0', @@ -1567,6 +1563,8 @@ CREATE TABLE `item_template` ( `stat_value9` smallint(6) NOT NULL default '0', `stat_type10` tinyint(3) unsigned NOT NULL default '0', `stat_value10` smallint(6) NOT NULL default '0', + `ScalingStatDistribution` smallint(6) NOT NULL default '0', + `ScalingStatValue` smallint(6) NOT NULL default '0', `dmg_min1` float NOT NULL default '0', `dmg_max1` float NOT NULL default '0', `dmg_type1` tinyint(3) unsigned NOT NULL default '0', @@ -1644,7 +1642,7 @@ CREATE TABLE `item_template` ( `area` mediumint(8) unsigned NOT NULL default '0', `Map` smallint(6) NOT NULL default '0', `BagFamily` mediumint(9) NOT NULL default '0', - `TotemCategory` tinyint(4) NOT NULL default '0', + `TotemCategory` mediumint(9) NOT NULL default '0', `socketColor_1` tinyint(4) NOT NULL default '0', `socketContent_1` mediumint(9) NOT NULL default '0', `socketColor_2` tinyint(4) NOT NULL default '0', @@ -1655,12 +1653,13 @@ CREATE TABLE `item_template` ( `GemProperties` mediumint(9) NOT NULL default '0', `RequiredDisenchantSkill` smallint(6) NOT NULL default '-1', `ArmorDamageModifier` float NOT NULL default '0', + `Duration` int(11) NOT NULL default '0' COMMENT 'Duration in seconds. Negative value means realtime, postive value ingame time', + `ItemLimitCategory` smallint(6) NOT NULL default '0', `ScriptName` varchar(64) NOT NULL default '', `DisenchantID` mediumint(8) unsigned NOT NULL default '0', `FoodType` tinyint(3) unsigned NOT NULL default '0', `minMoneyLoot` int(10) unsigned NOT NULL default '0', `maxMoneyLoot` int(10) unsigned NOT NULL default '0', - `Duration` int(11) NOT NULL default '0' COMMENT 'Duration in seconds. Negative value means realtime, postive value ingame time', PRIMARY KEY (`entry`), KEY `items_index` (`class`) ) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=FIXED COMMENT='Item System'; @@ -1672,79 +1671,93 @@ CREATE TABLE `item_template` ( LOCK TABLES `item_template` WRITE; /*!40000 ALTER TABLE `item_template` DISABLE KEYS */; INSERT INTO `item_template` VALUES -(25,2,7,-1,'Worn Shortsword',1542,1,0,1,35,7,21,32767,511,2,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1900,0,0,0,0,0,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,1,0,0,0,1,3,0,0,0,0,20,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,'internalItemHandler',0,0,0,0,0), -(35,2,10,-1,'Bent Staff',472,1,0,1,47,9,17,2047,255,2,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2900,0,0,0,0,0,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,2,2,0,0,0,0,25,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,'internalItemHandler',0,0,0,0,0), -(36,2,4,-1,'Worn Mace',5194,1,0,1,38,7,21,2047,255,2,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1900,0,0,0,0,0,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,2,3,0,0,0,0,20,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,'internalItemHandler',0,0,0,0,0), -(37,2,0,-1,'Worn Axe',14029,1,0,1,38,7,21,2047,255,2,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2000,0,0,0,0,0,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,1,3,0,0,0,0,20,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,'internalItemHandler',0,0,0,0,0), -(38,4,0,-1,'Recruit\'s Shirt',9891,1,0,1,1,1,4,-1,-1,1,0,0,0,0,0,0,0,0,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,-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,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,'internalItemHandler',0,0,0,0,0), -(39,4,1,-1,'Recruit\'s Pants',9892,0,0,1,5,1,7,32767,511,1,1,0,0,0,0,0,0,0,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,2,0,0,0,0,0,0,0,0,0,0,0,0,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,7,0,0,0,0,0,25,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,'internalItemHandler',0,0,0,0,0), -(40,4,0,-1,'Recruit\'s Boots',10141,1,0,1,4,1,8,32767,511,1,0,0,0,0,0,0,0,0,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,-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,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,'internalItemHandler',0,0,0,0,0), -(43,4,0,-1,'Squire\'s Boots',9938,1,0,1,4,1,8,2047,255,1,1,0,0,0,0,0,0,0,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,1000,0,0,0,0,0,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,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,'internalItemHandler',0,0,0,0,0), -(44,4,1,-1,'Squire\'s Pants',9937,0,0,1,4,1,7,2047,255,1,1,0,0,0,0,0,0,0,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,2,0,0,0,0,0,0,1000,0,0,0,0,0,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,7,0,0,0,0,0,25,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,'internalItemHandler',0,0,0,0,0), -(45,4,0,-1,'Squire\'s Shirt',3265,1,0,1,1,1,4,2047,255,1,1,0,0,0,0,0,0,0,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,1000,0,0,0,0,0,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,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,'internalItemHandler',0,0,0,0,0), -(47,4,0,-1,'Footpad\'s Shoes',9915,1,0,1,4,1,8,2047,255,1,1,0,0,0,0,0,0,0,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,1000,0,0,0,0,0,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,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,'internalItemHandler',0,0,0,0,0), -(48,4,1,-1,'Footpad\'s Pants',9913,0,0,1,4,1,7,2047,255,1,1,0,0,0,0,0,0,0,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,2,0,0,0,0,0,0,1000,0,0,0,0,0,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,7,0,0,0,0,0,25,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,'internalItemHandler',0,0,0,0,0), -(49,4,0,-1,'Footpad\'s Shirt',9906,1,0,1,1,1,4,2047,255,1,1,0,0,0,0,0,0,0,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,1000,0,0,0,0,0,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,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,'internalItemHandler',0,0,0,0,0), -(51,4,0,-1,'Neophyte\'s Boots',9946,1,0,1,5,1,8,2047,255,1,1,0,0,0,0,0,0,0,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,1000,0,0,0,0,0,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,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,'internalItemHandler',0,0,0,0,0), -(52,4,1,-1,'Neophyte\'s Pants',9945,0,0,1,5,1,7,2047,255,1,1,0,0,0,0,0,0,0,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,2,0,0,0,0,0,0,1000,0,0,0,0,0,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,7,0,0,0,0,0,25,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,'internalItemHandler',0,0,0,0,0), -(53,4,0,-1,'Neophyte\'s Shirt',9944,1,0,1,1,1,4,2047,255,1,1,0,0,0,0,0,0,0,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,1000,0,0,0,0,0,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,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,'internalItemHandler',0,0,0,0,0), -(55,4,0,-1,'Apprentice\'s Boots',9929,1,0,1,5,1,8,2047,255,1,1,0,0,0,0,0,0,0,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,1000,0,0,0,0,0,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,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,'internalItemHandler',0,0,0,0,0), -(56,4,1,-1,'Apprentice\'s Robe',12647,0,0,1,5,1,20,2047,255,1,1,0,0,0,0,0,0,0,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,3,0,0,0,0,0,0,1000,0,0,0,0,0,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,7,0,0,0,0,0,35,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,'internalItemHandler',0,0,0,0,0), -(57,4,1,-1,'Acolyte\'s Robe',12645,0,0,1,5,1,20,2047,255,1,1,0,0,0,0,0,0,0,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,3,0,0,0,0,0,0,1000,0,0,0,0,0,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,7,0,0,0,0,0,35,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,'internalItemHandler',0,0,0,0,0), -(59,4,0,-1,'Acolyte\'s Shoes',3261,1,0,1,5,1,8,2047,255,1,1,0,0,0,0,0,0,0,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,1000,0,0,0,0,0,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,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,'internalItemHandler',0,0,0,0,0), -(117,0,0,-1,'Tough Jerky',2473,1,0,6,25,1,0,2047,255,5,1,0,0,0,0,0,0,0,0,20,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1000,0,0,433,0,-1,0,-1,11,1000,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,'internalItemHandler',0,0,0,0,0), -(120,4,1,-1,'Thug Pants',10006,0,0,1,4,1,7,2047,255,1,1,0,0,0,0,0,0,0,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,2,0,0,0,0,0,0,1000,0,0,0,0,0,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,7,0,0,0,0,0,25,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,'internalItemHandler',0,0,0,0,0), -(121,4,0,-1,'Thug Boots',10008,1,0,1,4,1,8,2047,255,1,1,0,0,0,0,0,0,0,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,1000,0,0,0,0,0,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,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,'internalItemHandler',0,0,0,0,0), -(127,4,0,-1,'Trapper\'s Shirt',9996,1,0,1,1,1,4,2047,255,1,1,0,0,0,0,0,0,0,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,1000,0,0,0,0,0,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,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,'internalItemHandler',0,0,0,0,0), -(139,4,1,-1,'Brawler\'s Pants',9988,0,0,1,4,1,7,2047,255,1,1,0,0,0,0,0,0,0,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,2,0,0,0,0,0,0,1000,0,0,0,0,0,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,7,0,0,0,0,0,25,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,'internalItemHandler',0,0,0,0,0), -(140,4,0,-1,'Brawler\'s Boots',9992,1,0,1,4,1,8,2047,255,1,1,0,0,0,0,0,0,0,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,1000,0,0,0,0,0,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,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,'internalItemHandler',0,0,0,0,0), -(147,4,1,-1,'Rugged Trapper\'s Pants',9975,0,0,1,5,1,7,2047,255,1,1,0,0,0,0,0,0,0,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,2,0,0,0,0,0,0,1000,0,0,0,0,0,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,7,0,0,0,0,0,25,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,'internalItemHandler',0,0,0,0,0), -(148,4,0,-1,'Rugged Trapper\'s Shirt',9976,1,0,1,1,1,4,2047,255,1,1,0,0,0,0,0,0,0,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,1000,0,0,0,0,0,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,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,'internalItemHandler',0,0,0,0,0), -(153,4,2,-1,'Primitive Kilt',10050,0,0,1,5,1,7,2047,255,1,1,0,0,0,0,0,0,0,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,14,0,0,0,0,0,0,1000,0,0,0,0,0,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,8,0,0,0,0,0,30,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,'internalItemHandler',0,0,0,0,0), -(154,4,0,-1,'Primitive Mantle',10058,1,0,1,1,1,4,2047,255,1,1,0,0,0,0,0,0,0,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,1000,0,0,0,0,0,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,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,'internalItemHandler',0,0,0,0,0), -(159,0,0,-1,'Refreshing Spring Water',18084,1,0,6,25,1,0,2047,255,5,1,0,0,0,0,0,0,0,0,20,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1000,0,0,430,0,-1,0,-1,59,1000,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,'internalItemHandler',0,0,0,0,0), -(1395,4,1,-1,'Apprentice\'s Pants',9924,0,0,1,5,1,7,2047,255,1,1,0,0,0,0,0,0,0,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,2,0,0,0,0,0,0,1000,0,0,0,0,0,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,7,0,0,0,0,0,25,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,'internalItemHandler',0,0,0,0,0), -(1396,4,1,-1,'Acolyte\'s Pants',3260,0,0,1,4,1,7,2047,255,1,1,0,0,0,0,0,0,0,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,2,0,0,0,0,0,0,1000,0,0,0,0,0,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,7,0,0,0,0,0,25,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,'internalItemHandler',0,0,0,0,0), -(2070,0,0,-1,'Darnassian Bleu',6353,1,0,6,25,1,0,2047,255,5,1,0,0,0,0,0,0,0,0,20,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1000,0,0,433,0,-1,0,-1,11,1000,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,'internalItemHandler',0,0,0,0,0), -(2092,2,15,-1,'Worn Dagger',6442,1,0,1,35,7,13,2047,255,2,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1600,0,0,0,0,0,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,1,3,0,0,0,0,16,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,'internalItemHandler',0,0,0,0,0), -(2101,1,2,-1,'Light Quiver',21328,1,0,1,4,1,18,2047,255,1,1,0,0,0,0,0,0,0,0,1,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,1000,0,0,14824,1,0,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,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,-1,0,'internalItemHandler',0,0,0,0,0), -(2102,1,3,-1,'Small Ammo Pouch',1816,1,0,1,4,1,18,2047,255,1,1,0,0,0,0,0,0,0,0,1,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,1000,0,0,14824,1,0,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,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,-1,0,'internalItemHandler',0,0,0,0,0), -(2105,4,0,-1,'Thug Shirt',10005,1,0,1,5,1,4,2047,255,1,1,0,0,0,0,0,0,0,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,1000,0,0,0,0,0,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,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,'internalItemHandler',0,0,0,0,0), -(2361,2,5,-1,'Battleworn Hammer',8690,1,0,1,45,9,17,2047,255,2,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2900,0,0,0,0,0,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,2,1,0,0,0,0,25,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,'internalItemHandler',0,0,0,0,0), -(2362,4,6,-1,'Worn Wooden Shield',18730,0,0,1,7,1,14,32767,511,1,1,0,0,0,0,0,0,0,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,5,0,0,0,0,0,0,0,0,0,0,0,0,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,1,4,0,0,1,0,20,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,'internalItemHandler',0,0,0,0,0), -(2504,2,2,-1,'Worn Shortbow',8106,1,0,1,29,5,15,2047,255,2,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2300,2,0,0,0,0,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,2,0,0,0,0,0,20,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,'internalItemHandler',0,0,0,0,0), -(2508,2,3,-1,'Old Blunderbuss',6606,1,0,1,27,5,26,2047,255,2,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2300,3,0,0,0,0,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,1,0,0,0,0,0,20,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,'internalItemHandler',0,0,0,0,0), -(2512,6,2,-1,'Rough Arrow',5996,1,0,1,10,0,24,2047,255,5,1,0,0,0,0,0,0,0,0,200,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3000,0,0,0,0,0,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,2,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,-1,0,'internalItemHandler',0,0,0,0,0), -(2516,6,3,-1,'Light Shot',5998,1,0,1,10,0,24,2047,255,5,1,0,0,0,0,0,0,0,0,200,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3000,0,0,0,0,0,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,2,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,-1,0,'internalItemHandler',0,0,0,0,0), -(2947,2,16,-1,'Small Throwing Knife',16754,1,0,1,15,0,25,2047,255,3,1,0,0,0,0,0,0,0,0,200,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2000,4,0,0,0,0,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,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,'internalItemHandler',0,0,0,0,0), -(3661,2,10,-1,'Handcrafted Staff',18530,1,0,1,45,9,17,2047,255,2,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2900,0,0,0,0,0,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,2,2,0,0,0,0,25,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,'internalItemHandler',0,0,0,0,0), -(4536,0,0,-1,'Shiny Red Apple',6410,1,0,6,25,1,0,2047,255,5,1,0,0,0,0,0,0,0,0,20,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1000,0,0,433,0,-1,0,-1,11,100,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,'internalItemHandler',0,0,0,0,0), -(4540,0,0,-1,'Tough Hunk of Bread',6399,1,0,6,25,1,0,2047,255,5,1,0,0,0,0,0,0,0,0,20,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1000,0,0,433,0,-1,0,-1,11,1000,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,'internalItemHandler',0,0,0,0,0), -(4604,0,0,-1,'Forest Mushroom Cap',15852,1,0,6,25,1,0,2047,255,5,1,0,0,0,0,0,0,0,0,20,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1000,0,0,433,0,-1,0,-1,11,1000,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,'internalItemHandler',0,0,0,0,0), -(6096,4,0,-1,'Apprentice\'s Shirt',2163,1,0,1,1,1,4,2047,255,1,1,0,0,0,0,0,0,0,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,1000,0,0,0,0,0,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,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,'internalItemHandler',0,0,0,0,0), -(6097,4,0,-1,'Acolyte\'s Shirt',2470,1,0,1,1,1,4,2047,255,1,1,0,0,0,0,0,0,0,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,1000,0,0,0,0,0,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,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,'internalItemHandler',0,0,0,0,0), -(6098,4,1,-1,'Neophyte\'s Robe',12679,0,0,1,4,1,20,2047,255,1,1,0,0,0,0,0,0,0,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,3,0,0,0,0,0,0,1000,0,0,0,0,0,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,7,0,0,0,0,0,35,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,'internalItemHandler',0,0,0,0,0), -(6119,4,1,-1,'Neophyte\'s Robe',12681,0,0,1,4,1,20,2047,255,1,1,0,0,0,0,0,0,0,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,3,0,0,0,0,0,0,1000,0,0,0,0,0,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,7,0,0,0,0,0,35,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,'internalItemHandler',0,0,0,0,0), -(6123,4,1,-1,'Novice\'s Robe',12683,0,0,1,4,1,20,2047,255,1,1,0,0,0,0,0,0,0,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,3,0,0,0,0,0,0,1000,0,0,0,0,0,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,7,0,0,0,0,0,35,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,'internalItemHandler',0,0,0,0,0), -(6124,4,1,-1,'Novice\'s Pants',9987,0,0,1,5,1,7,2047,255,1,1,0,0,0,0,0,0,0,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,2,0,0,0,0,0,0,1000,0,0,0,0,0,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,7,0,0,0,0,0,25,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,'internalItemHandler',0,0,0,0,0), -(6125,4,0,-1,'Brawler\'s Harness',9995,1,0,1,1,1,4,2047,255,1,1,0,0,0,0,0,0,0,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,1000,0,0,0,0,0,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,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,'internalItemHandler',0,0,0,0,0), -(6126,4,1,-1,'Trapper\'s Pants',10002,0,0,1,5,1,7,2047,255,1,1,0,0,0,0,0,0,0,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,2,0,0,0,0,0,0,1000,0,0,0,0,0,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,7,0,0,0,0,0,25,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,'internalItemHandler',0,0,0,0,0), -(6127,4,0,-1,'Trapper\'s Boots',10003,1,0,1,5,1,8,2047,255,1,1,0,0,0,0,0,0,0,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,1000,0,0,0,0,0,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,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,'internalItemHandler',0,0,0,0,0), -(6129,4,1,-1,'Acolyte\'s Robe',12646,0,0,1,5,1,20,2047,255,1,1,0,0,0,0,0,0,0,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,3,0,0,0,0,0,0,1000,0,0,0,0,0,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,7,0,0,0,0,0,35,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,'internalItemHandler',0,0,0,0,0), -(6134,4,0,-1,'Primitive Mantle',10108,1,0,1,1,1,4,2047,255,1,1,0,0,0,0,0,0,0,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,1000,0,0,0,0,0,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,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,'internalItemHandler',0,0,0,0,0), -(6135,4,2,-1,'Primitive Kilt',10109,0,0,1,5,1,7,2047,255,1,1,0,0,0,0,0,0,0,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,14,0,0,0,0,0,0,1000,0,0,0,0,0,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,8,0,0,0,0,0,30,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,'internalItemHandler',0,0,0,0,0), -(6139,4,1,-1,'Novice\'s Robe',12684,0,0,1,4,1,20,2047,255,1,1,0,0,0,0,0,0,0,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,3,0,0,0,0,0,0,1000,0,0,0,0,0,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,7,0,0,0,0,0,35,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,'internalItemHandler',0,0,0,0,0), -(6140,4,1,-1,'Apprentice\'s Robe',12649,0,0,1,4,1,20,2047,255,1,1,0,0,0,0,0,0,0,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,3,0,0,0,0,0,0,1000,0,0,0,0,0,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,7,0,0,0,0,0,35,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,'internalItemHandler',0,0,0,0,0), -(6144,4,1,-1,'Neophyte\'s Robe',12680,0,0,1,5,1,20,2047,255,1,1,0,0,0,0,0,0,0,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,3,0,0,0,0,0,0,1000,0,0,0,0,0,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,7,0,0,0,0,0,35,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,'internalItemHandler',0,0,0,0,0), -(6948,15,0,-1,'Hearthstone',6418,1,64,1,0,0,0,32767,511,1,0,0,0,0,0,0,0,0,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,8690,0,0,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,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,-1,0,'internalItemHandler',0,0,0,0,0), -(12282,2,1,-1,'Worn Battleaxe',22291,1,0,1,43,8,17,2047,255,2,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2900,0,0,0,0,0,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,1,1,0,0,0,0,25,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,'internalItemHandler',0,0,0,0,0), -(14646,12,0,-1,'Northshire Gift Voucher',18499,1,0,1,0,0,0,2047,255,1,1,0,0,0,0,0,0,0,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,1000,0,0,0,0,0,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,4,'',0,0,0,5805,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,'internalItemHandler',0,0,0,0,0), -(14647,12,0,-1,'Coldridge Valley Gift Voucher',18499,1,0,1,0,0,0,2047,255,1,1,0,0,0,0,0,0,0,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,1000,0,0,0,0,0,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,4,'',0,0,0,5841,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,'internalItemHandler',0,0,0,0,0), -(14648,12,0,-1,'Shadowglen Gift Voucher',18499,1,0,1,0,0,0,2047,255,1,1,0,0,0,0,0,0,0,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,1000,0,0,0,0,0,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,4,'',0,0,0,5842,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,'internalItemHandler',0,0,0,0,0), -(14649,12,0,-1,'Valley of Trials Gift Voucher',18499,1,0,1,0,0,0,2047,255,1,1,0,0,0,0,0,0,0,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,1000,0,0,0,0,0,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,4,'',0,0,0,5843,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,'internalItemHandler',0,0,0,0,0), -(14650,12,0,-1,'Camp Narache Gift Voucher',18499,1,0,1,0,0,0,2047,255,1,1,0,0,0,0,0,0,0,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,1000,0,0,0,0,0,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,4,'',0,0,0,5844,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,'internalItemHandler',0,0,0,0,0), -(14651,12,0,-1,'Deathknell Gift Voucher',18499,1,0,1,0,0,0,2047,255,1,1,0,0,0,0,0,0,0,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,1000,0,0,0,0,0,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,4,'',0,0,0,5847,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,'internalItemHandler',0,0,0,0,0), -(25861,2,16,-1,'Crude Throwing Axe',20777,1,0,1,15,0,25,2047,255,3,1,0,0,0,0,0,0,0,0,200,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2000,4,0,0,0,0,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,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,'internalItemHandler',0,0,0,0,0); +(25,2,7,-1,'Worn Shortsword',1542,1,0,1,35,7,21,32767,511,2,1,0,0,0,0,0,0,0,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,1,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1900,0,0,0,0,0,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,1,0,0,0,1,3,0,0,0,0,20,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,'internalItemHandler',0,0,0,0,0), +(35,2,10,-1,'Bent Staff',472,1,0,1,47,9,17,2047,255,2,1,0,0,0,0,0,0,0,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,3,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2900,0,0,0,0,0,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,2,2,0,0,0,0,25,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,'internalItemHandler',0,0,0,0,0), +(36,2,4,-1,'Worn Mace',5194,1,0,1,38,7,21,2047,255,2,1,0,0,0,0,0,0,0,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,1,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1900,0,0,0,0,0,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,2,3,0,0,0,0,20,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,'internalItemHandler',0,0,0,0,0), +(37,2,0,-1,'Worn Axe',14029,1,0,1,38,7,21,2047,255,2,1,0,0,0,0,0,0,0,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,1,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2000,0,0,0,0,0,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,1,3,0,0,0,0,20,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,'internalItemHandler',0,0,0,0,0), +(38,4,0,-1,'Recruit\'s Shirt',9891,1,0,1,1,1,4,-1,-1,1,0,0,0,0,0,0,0,0,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,-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,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,'internalItemHandler',0,0,0,0,0), +(39,4,1,-1,'Recruit\'s Pants',9892,0,0,1,5,1,7,32767,511,1,1,0,0,0,0,0,0,0,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,2,0,0,0,0,0,0,0,0,0,0,0,0,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,7,0,0,0,0,0,25,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,'internalItemHandler',0,0,0,0,0), +(40,4,0,-1,'Recruit\'s Boots',10141,1,0,1,4,1,8,32767,511,1,0,0,0,0,0,0,0,0,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,-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,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,'internalItemHandler',0,0,0,0,0), +(43,4,0,-1,'Squire\'s Boots',9938,1,0,1,4,1,8,2047,255,1,1,0,0,0,0,0,0,0,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,1000,0,0,0,0,0,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,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,'internalItemHandler',0,0,0,0,0), +(44,4,1,-1,'Squire\'s Pants',9937,0,0,1,4,1,7,2047,255,1,1,0,0,0,0,0,0,0,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,2,0,0,0,0,0,0,1000,0,0,0,0,0,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,7,0,0,0,0,0,25,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,'internalItemHandler',0,0,0,0,0), +(45,4,0,-1,'Squire\'s Shirt',3265,1,0,1,1,1,4,2047,255,1,1,0,0,0,0,0,0,0,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,1000,0,0,0,0,0,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,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,'internalItemHandler',0,0,0,0,0), +(47,4,0,-1,'Footpad\'s Shoes',9915,1,0,1,4,1,8,2047,255,1,1,0,0,0,0,0,0,0,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,1000,0,0,0,0,0,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,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,'internalItemHandler',0,0,0,0,0), +(48,4,1,-1,'Footpad\'s Pants',9913,0,0,1,4,1,7,2047,255,1,1,0,0,0,0,0,0,0,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,2,0,0,0,0,0,0,1000,0,0,0,0,0,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,7,0,0,0,0,0,25,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,'internalItemHandler',0,0,0,0,0), +(49,4,0,-1,'Footpad\'s Shirt',9906,1,0,1,1,1,4,2047,255,1,1,0,0,0,0,0,0,0,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,1000,0,0,0,0,0,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,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,'internalItemHandler',0,0,0,0,0), +(51,4,0,-1,'Neophyte\'s Boots',9946,1,0,1,5,1,8,2047,255,1,1,0,0,0,0,0,0,0,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,1000,0,0,0,0,0,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,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,'internalItemHandler',0,0,0,0,0), +(52,4,1,-1,'Neophyte\'s Pants',9945,0,0,1,5,1,7,2047,255,1,1,0,0,0,0,0,0,0,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,2,0,0,0,0,0,0,1000,0,0,0,0,0,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,7,0,0,0,0,0,25,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,'internalItemHandler',0,0,0,0,0), +(53,4,0,-1,'Neophyte\'s Shirt',9944,1,0,1,1,1,4,2047,255,1,1,0,0,0,0,0,0,0,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,1000,0,0,0,0,0,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,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,'internalItemHandler',0,0,0,0,0), +(55,4,0,-1,'Apprentice\'s Boots',9929,1,0,1,5,1,8,2047,255,1,1,0,0,0,0,0,0,0,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,1000,0,0,0,0,0,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,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,'internalItemHandler',0,0,0,0,0), +(56,4,1,-1,'Apprentice\'s Robe',12647,0,0,1,5,1,20,2047,255,1,1,0,0,0,0,0,0,0,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,3,0,0,0,0,0,0,1000,0,0,0,0,0,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,7,0,0,0,0,0,35,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,'internalItemHandler',0,0,0,0,0), +(57,4,1,-1,'Acolyte\'s Robe',12645,0,0,1,5,1,20,2047,255,1,1,0,0,0,0,0,0,0,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,3,0,0,0,0,0,0,1000,0,0,0,0,0,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,7,0,0,0,0,0,35,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,'internalItemHandler',0,0,0,0,0), +(59,4,0,-1,'Acolyte\'s Shoes',3261,1,0,1,5,1,8,2047,255,1,1,0,0,0,0,0,0,0,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,1000,0,0,0,0,0,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,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,'internalItemHandler',0,0,0,0,0), +(117,0,0,-1,'Tough Jerky',2473,1,0,6,25,1,0,2047,255,5,1,0,0,0,0,0,0,0,0,20,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1000,0,0,433,0,-1,0,-1,11,1000,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,'internalItemHandler',0,0,0,0,0), +(120,4,1,-1,'Thug Pants',10006,0,0,1,4,1,7,2047,255,1,1,0,0,0,0,0,0,0,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,2,0,0,0,0,0,0,1000,0,0,0,0,0,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,7,0,0,0,0,0,25,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,'internalItemHandler',0,0,0,0,0), +(121,4,0,-1,'Thug Boots',10008,1,0,1,4,1,8,2047,255,1,1,0,0,0,0,0,0,0,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,1000,0,0,0,0,0,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,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,'internalItemHandler',0,0,0,0,0), +(127,4,0,-1,'Trapper\'s Shirt',9996,1,0,1,1,1,4,2047,255,1,1,0,0,0,0,0,0,0,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,1000,0,0,0,0,0,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,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,'internalItemHandler',0,0,0,0,0), +(139,4,1,-1,'Brawler\'s Pants',9988,0,0,1,4,1,7,2047,255,1,1,0,0,0,0,0,0,0,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,2,0,0,0,0,0,0,1000,0,0,0,0,0,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,7,0,0,0,0,0,25,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,'internalItemHandler',0,0,0,0,0), +(140,4,0,-1,'Brawler\'s Boots',9992,1,0,1,4,1,8,2047,255,1,1,0,0,0,0,0,0,0,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,1000,0,0,0,0,0,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,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,'internalItemHandler',0,0,0,0,0), +(147,4,1,-1,'Rugged Trapper\'s Pants',9975,0,0,1,5,1,7,2047,255,1,1,0,0,0,0,0,0,0,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,2,0,0,0,0,0,0,1000,0,0,0,0,0,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,7,0,0,0,0,0,25,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,'internalItemHandler',0,0,0,0,0), +(148,4,0,-1,'Rugged Trapper\'s Shirt',9976,1,0,1,1,1,4,2047,255,1,1,0,0,0,0,0,0,0,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,1000,0,0,0,0,0,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,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,'internalItemHandler',0,0,0,0,0), +(153,4,2,-1,'Primitive Kilt',10050,0,0,1,5,1,7,2047,255,1,1,0,0,0,0,0,0,0,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,14,0,0,0,0,0,0,1000,0,0,0,0,0,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,8,0,0,0,0,0,30,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,'internalItemHandler',0,0,0,0,0), +(154,4,0,-1,'Primitive Mantle',10058,1,0,1,1,1,4,2047,255,1,1,0,0,0,0,0,0,0,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,1000,0,0,0,0,0,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,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,'internalItemHandler',0,0,0,0,0), +(159,0,0,-1,'Refreshing Spring Water',18084,1,0,6,25,1,0,2047,255,5,1,0,0,0,0,0,0,0,0,20,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1000,0,0,430,0,-1,0,-1,59,1000,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,'internalItemHandler',0,0,0,0,0), +(1395,4,1,-1,'Apprentice\'s Pants',9924,0,0,1,5,1,7,2047,255,1,1,0,0,0,0,0,0,0,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,2,0,0,0,0,0,0,1000,0,0,0,0,0,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,7,0,0,0,0,0,25,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,'internalItemHandler',0,0,0,0,0), +(1396,4,1,-1,'Acolyte\'s Pants',3260,0,0,1,4,1,7,2047,255,1,1,0,0,0,0,0,0,0,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,2,0,0,0,0,0,0,1000,0,0,0,0,0,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,7,0,0,0,0,0,25,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,'internalItemHandler',0,0,0,0,0), +(2070,0,0,-1,'Darnassian Bleu',6353,1,0,6,25,1,0,2047,255,5,1,0,0,0,0,0,0,0,0,20,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1000,0,0,433,0,-1,0,-1,11,1000,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,'internalItemHandler',0,0,0,0,0), +(2092,2,15,-1,'Worn Dagger',6442,1,0,1,35,7,13,2047,255,2,1,0,0,0,0,0,0,0,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,1,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1600,0,0,0,0,0,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,1,3,0,0,0,0,16,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,'internalItemHandler',0,0,0,0,0), +(2101,1,2,-1,'Light Quiver',21328,1,0,1,4,1,18,2047,255,1,1,0,0,0,0,0,0,0,0,1,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,1000,0,0,14824,1,0,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,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,-1,0,0,'internalItemHandler',0,0,0,0,0), +(2102,1,3,-1,'Small Ammo Pouch',1816,1,0,1,4,1,18,2047,255,1,1,0,0,0,0,0,0,0,0,1,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,1000,0,0,14824,1,0,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,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,-1,0,0,'internalItemHandler',0,0,0,0,0), +(2105,4,0,-1,'Thug Shirt',10005,1,0,1,5,1,4,2047,255,1,1,0,0,0,0,0,0,0,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,1000,0,0,0,0,0,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,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,'internalItemHandler',0,0,0,0,0), +(2361,2,5,-1,'Battleworn Hammer',8690,1,0,1,45,9,17,2047,255,2,1,0,0,0,0,0,0,0,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,3,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2900,0,0,0,0,0,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,2,1,0,0,0,0,25,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,'internalItemHandler',0,0,0,0,0), +(2362,4,6,-1,'Worn Wooden Shield',18730,0,0,1,7,1,14,32767,511,1,1,0,0,0,0,0,0,0,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,5,0,0,0,0,0,0,0,0,0,0,0,0,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,1,4,0,0,1,0,20,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,'internalItemHandler',0,0,0,0,0), +(2504,2,2,-1,'Worn Shortbow',8106,1,0,1,29,5,15,2047,255,2,1,0,0,0,0,0,0,0,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,2,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2300,2,0,0,0,0,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,2,0,0,0,0,0,20,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,'internalItemHandler',0,0,0,0,0), +(2508,2,3,-1,'Old Blunderbuss',6606,1,0,1,27,5,26,2047,255,2,1,0,0,0,0,0,0,0,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,2,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2300,3,0,0,0,0,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,1,0,0,0,0,0,20,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,'internalItemHandler',0,0,0,0,0), +(2512,6,2,-1,'Rough Arrow',5996,1,0,1,10,0,24,2047,255,5,1,0,0,0,0,0,0,0,0,200,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3000,0,0,0,0,0,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,2,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,-1,0,0,'internalItemHandler',0,0,0,0,0), +(2516,6,3,-1,'Light Shot',5998,1,0,1,10,0,24,2047,255,5,1,0,0,0,0,0,0,0,0,200,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3000,0,0,0,0,0,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,2,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,-1,0,0,'internalItemHandler',0,0,0,0,0), +(2947,2,16,-1,'Small Throwing Knife',16754,1,0,1,15,0,25,2047,255,3,1,0,0,0,0,0,0,0,0,200,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2000,4,0,0,0,0,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,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,'internalItemHandler',0,0,0,0,0), +(3661,2,10,-1,'Handcrafted Staff',18530,1,0,1,45,9,17,2047,255,2,1,0,0,0,0,0,0,0,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,3,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2900,0,0,0,0,0,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,2,2,0,0,0,0,25,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,'internalItemHandler',0,0,0,0,0), +(4536,0,0,-1,'Shiny Red Apple',6410,1,0,6,25,1,0,2047,255,5,1,0,0,0,0,0,0,0,0,20,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1000,0,0,433,0,-1,0,-1,11,100,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,'internalItemHandler',0,0,0,0,0), +(4540,0,0,-1,'Tough Hunk of Bread',6399,1,0,6,25,1,0,2047,255,5,1,0,0,0,0,0,0,0,0,20,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1000,0,0,433,0,-1,0,-1,11,1000,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,'internalItemHandler',0,0,0,0,0), +(4604,0,0,-1,'Forest Mushroom Cap',15852,1,0,6,25,1,0,2047,255,5,1,0,0,0,0,0,0,0,0,20,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1000,0,0,433,0,-1,0,-1,11,1000,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,'internalItemHandler',0,0,0,0,0), +(6096,4,0,-1,'Apprentice\'s Shirt',2163,1,0,1,1,1,4,2047,255,1,1,0,0,0,0,0,0,0,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,1000,0,0,0,0,0,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,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,'internalItemHandler',0,0,0,0,0), +(6097,4,0,-1,'Acolyte\'s Shirt',2470,1,0,1,1,1,4,2047,255,1,1,0,0,0,0,0,0,0,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,1000,0,0,0,0,0,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,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,'internalItemHandler',0,0,0,0,0), +(6098,4,1,-1,'Neophyte\'s Robe',12679,0,0,1,4,1,20,2047,255,1,1,0,0,0,0,0,0,0,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,3,0,0,0,0,0,0,1000,0,0,0,0,0,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,7,0,0,0,0,0,35,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,'internalItemHandler',0,0,0,0,0), +(6119,4,1,-1,'Neophyte\'s Robe',12681,0,0,1,4,1,20,2047,255,1,1,0,0,0,0,0,0,0,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,3,0,0,0,0,0,0,1000,0,0,0,0,0,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,7,0,0,0,0,0,35,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,'internalItemHandler',0,0,0,0,0), +(6123,4,1,-1,'Novice\'s Robe',12683,0,0,1,4,1,20,2047,255,1,1,0,0,0,0,0,0,0,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,3,0,0,0,0,0,0,1000,0,0,0,0,0,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,7,0,0,0,0,0,35,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,'internalItemHandler',0,0,0,0,0), +(6124,4,1,-1,'Novice\'s Pants',9987,0,0,1,5,1,7,2047,255,1,1,0,0,0,0,0,0,0,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,2,0,0,0,0,0,0,1000,0,0,0,0,0,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,7,0,0,0,0,0,25,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,'internalItemHandler',0,0,0,0,0), +(6125,4,0,-1,'Brawler\'s Harness',9995,1,0,1,1,1,4,2047,255,1,1,0,0,0,0,0,0,0,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,1000,0,0,0,0,0,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,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,'internalItemHandler',0,0,0,0,0), +(6126,4,1,-1,'Trapper\'s Pants',10002,0,0,1,5,1,7,2047,255,1,1,0,0,0,0,0,0,0,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,2,0,0,0,0,0,0,1000,0,0,0,0,0,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,7,0,0,0,0,0,25,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,'internalItemHandler',0,0,0,0,0), +(6127,4,0,-1,'Trapper\'s Boots',10003,1,0,1,5,1,8,2047,255,1,1,0,0,0,0,0,0,0,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,1000,0,0,0,0,0,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,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,'internalItemHandler',0,0,0,0,0), +(6129,4,1,-1,'Acolyte\'s Robe',12646,0,0,1,5,1,20,2047,255,1,1,0,0,0,0,0,0,0,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,3,0,0,0,0,0,0,1000,0,0,0,0,0,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,7,0,0,0,0,0,35,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,'internalItemHandler',0,0,0,0,0), +(6134,4,0,-1,'Primitive Mantle',10108,1,0,1,1,1,4,2047,255,1,1,0,0,0,0,0,0,0,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,1000,0,0,0,0,0,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,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,'internalItemHandler',0,0,0,0,0), +(6135,4,2,-1,'Primitive Kilt',10109,0,0,1,5,1,7,2047,255,1,1,0,0,0,0,0,0,0,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,14,0,0,0,0,0,0,1000,0,0,0,0,0,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,8,0,0,0,0,0,30,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,'internalItemHandler',0,0,0,0,0), +(6139,4,1,-1,'Novice\'s Robe',12684,0,0,1,4,1,20,2047,255,1,1,0,0,0,0,0,0,0,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,3,0,0,0,0,0,0,1000,0,0,0,0,0,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,7,0,0,0,0,0,35,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,'internalItemHandler',0,0,0,0,0), +(6140,4,1,-1,'Apprentice\'s Robe',12649,0,0,1,4,1,20,2047,255,1,1,0,0,0,0,0,0,0,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,3,0,0,0,0,0,0,1000,0,0,0,0,0,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,7,0,0,0,0,0,35,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,'internalItemHandler',0,0,0,0,0), +(6144,4,1,-1,'Neophyte\'s Robe',12680,0,0,1,5,1,20,2047,255,1,1,0,0,0,0,0,0,0,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,3,0,0,0,0,0,0,1000,0,0,0,0,0,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,7,0,0,0,0,0,35,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,'internalItemHandler',0,0,0,0,0), +(6948,15,0,-1,'Hearthstone',6418,1,64,1,0,0,0,32767,511,1,0,0,0,0,0,0,0,0,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,8690,0,0,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,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,-1,0,0,'internalItemHandler',0,0,0,0,0), +(12282,2,1,-1,'Worn Battleaxe',22291,1,0,1,43,8,17,2047,255,2,1,0,0,0,0,0,0,0,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,3,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2900,0,0,0,0,0,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,1,1,0,0,0,0,25,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,'internalItemHandler',0,0,0,0,0), +(14646,12,0,-1,'Northshire Gift Voucher',18499,1,0,1,0,0,0,2047,255,1,1,0,0,0,0,0,0,0,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,1000,0,0,0,0,0,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,4,'',0,0,0,5805,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,'internalItemHandler',0,0,0,0,0), +(14647,12,0,-1,'Coldridge Valley Gift Voucher',18499,1,0,1,0,0,0,2047,255,1,1,0,0,0,0,0,0,0,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,1000,0,0,0,0,0,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,4,'',0,0,0,5841,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,'internalItemHandler',0,0,0,0,0), +(14648,12,0,-1,'Shadowglen Gift Voucher',18499,1,0,1,0,0,0,2047,255,1,1,0,0,0,0,0,0,0,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,1000,0,0,0,0,0,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,4,'',0,0,0,5842,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,'internalItemHandler',0,0,0,0,0), +(14649,12,0,-1,'Valley of Trials Gift Voucher',18499,1,0,1,0,0,0,2047,255,1,1,0,0,0,0,0,0,0,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,1000,0,0,0,0,0,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,4,'',0,0,0,5843,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,'internalItemHandler',0,0,0,0,0), +(14650,12,0,-1,'Camp Narache Gift Voucher',18499,1,0,1,0,0,0,2047,255,1,1,0,0,0,0,0,0,0,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,1000,0,0,0,0,0,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,4,'',0,0,0,5844,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,'internalItemHandler',0,0,0,0,0), +(14651,12,0,-1,'Deathknell Gift Voucher',18499,1,0,1,0,0,0,2047,255,1,1,0,0,0,0,0,0,0,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,1000,0,0,0,0,0,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,4,'',0,0,0,5847,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,'internalItemHandler',0,0,0,0,0), +(25861,2,16,-1,'Crude Throwing Axe',20777,1,0,1,15,0,25,2047,255,3,1,0,0,0,0,0,0,0,0,200,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2000,4,0,0,0,0,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,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,'internalItemHandler',0,0,0,0,0), +(34648,4,4,-1,'Acherus Knight\'s Greaves',51496,2,32768,1,51,10,8,-1,-1,60,55,0,0,0,0,0,0,0,0,1,0,3,4,10,7,12,3,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,392,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,-1,0,0,0,0,-1,0,-1,0,0,0,0,-1,0,-1,0,0,0,0,-1,0,-1,0,0,0,0,-1,0,-1,1,'',0,0,0,0,0,6,0,0,0,0,0,55,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,0,'',0,0,0,0), +(34649,4,4,-1,'Acherus Knight\'s Gauntlets',51498,2,32768,1,34,6,10,-1,-1,60,55,0,0,0,0,0,0,0,0,1,0,3,4,15,7,6,32,8,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,356,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,-1,0,0,0,0,-1,0,-1,0,0,0,0,-1,0,-1,0,0,0,0,-1,0,-1,0,0,0,0,-1,0,-1,1,'',0,0,0,0,0,6,0,0,0,0,0,40,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,0,'',0,0,0,0), +(34650,4,4,-1,'Acherus Knight\'s Tunic',51494,2,32768,1,69,13,5,-1,-1,60,55,0,0,0,0,0,0,0,0,1,0,3,4,20,7,11,32,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,570,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,-1,0,0,0,0,-1,0,-1,0,0,0,0,-1,0,-1,0,0,0,0,-1,0,-1,0,0,0,0,-1,0,-1,1,'',0,0,0,0,0,6,0,0,0,0,0,115,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,0,'',0,0,0,0), +(34651,4,4,-1,'Acherus Knight\'s Girdle',51497,2,32768,1,35,7,6,-1,-1,60,55,0,0,0,0,0,0,0,0,1,0,2,4,10,32,15,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,320,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,-1,0,0,0,0,-1,0,-1,0,0,0,0,-1,0,-1,0,0,0,0,-1,0,-1,0,0,0,0,-1,0,-1,1,'',0,0,0,0,0,6,0,0,0,0,0,40,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,0,'',0,0,0,0), +(34652,4,4,-1,'Acherus Knight\'s Hood',51495,2,32768,1,52,10,1,-1,-1,60,55,0,0,0,0,0,0,0,0,1,0,3,4,15,7,15,32,9,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,463,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,-1,0,0,0,0,-1,0,-1,0,0,0,0,-1,0,-1,0,0,0,0,-1,0,-1,0,0,0,0,-1,0,-1,1,'',0,0,0,0,0,6,0,0,0,0,0,70,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,0,'',0,0,0,0), +(34653,4,4,-1,'Acherus Knight\'s Wristguard',51500,2,32768,1,36,7,9,-1,-1,60,55,0,0,0,0,0,0,0,0,1,0,3,4,7,31,7,7,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,249,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,-1,0,0,0,0,-1,0,-1,0,0,0,0,-1,0,-1,0,0,0,0,-1,0,-1,0,0,0,0,-1,0,-1,1,'',0,0,0,0,0,6,0,0,0,0,0,40,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,0,'',0,0,0,0), +(34655,4,4,-1,'Acherus Knight\'s Pauldrons',51501,2,32768,1,54,10,3,-1,-1,60,55,0,0,0,0,0,0,0,0,1,0,3,4,11,3,9,7,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,427,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,-1,0,0,0,0,-1,0,-1,0,0,0,0,-1,0,-1,0,0,0,0,-1,0,-1,0,0,0,0,-1,0,-1,1,'',0,0,0,0,0,6,0,0,0,0,0,70,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,0,'',0,0,0,0), +(34656,4,4,-1,'Acherus Knight\'s Cover',51499,2,32768,1,73,14,7,-1,-1,60,55,0,0,0,0,0,0,0,0,1,0,3,4,13,3,10,7,15,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,499,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,-1,0,0,0,0,-1,0,-1,0,0,0,0,-1,0,-1,0,0,0,0,-1,0,-1,0,0,0,0,-1,0,-1,1,'',0,0,0,0,0,6,0,0,0,0,0,85,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,0,'',0,0,0,0), +(34657,4,0,-1,'Choker of Damnation',6539,2,32768,1,2303,575,2,-1,-1,60,55,0,0,0,0,0,0,0,0,1,0,3,4,9,7,8,31,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,-1,0,0,0,0,-1,0,-1,0,0,0,0,-1,0,-1,0,0,0,0,-1,0,-1,0,0,0,0,-1,0,-1,1,'',0,0,0,0,0,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,0,'',0,0,0,0), +(34658,4,0,-1,'Plague Band',963,2,32768,1,534,133,11,-1,-1,60,55,0,0,0,0,0,0,0,0,1,0,3,4,11,3,6,7,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,-1,0,0,0,0,-1,0,-1,0,0,0,0,-1,0,-1,0,0,0,0,-1,0,-1,0,0,0,0,-1,0,-1,1,'',0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,0,'',0,0,0,0), +(34659,4,1,-1,'Acherus Knight\'s Shroud',49738,2,32768,1,31,6,16,-1,-1,60,55,0,0,0,0,0,0,0,0,1,0,2,4,12,7,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,39,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,-1,0,0,0,0,-1,0,-1,0,0,0,0,-1,0,-1,0,0,0,0,-1,0,-1,0,0,0,0,-1,0,-1,1,'',0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,0,'',0,0,0,0), +(38145,1,0,-1,'Deathweave Bag',1282,1,32768,1,0,0,18,-1,-1,35,0,0,0,0,0,0,0,0,0,1,12,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,-1,0,0,0,0,-1,0,-1,0,0,0,0,-1,0,-1,0,0,0,0,-1,0,-1,0,0,0,0,-1,0,-1,1,'',0,0,0,0,0,8,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,0,'',0,0,0,0), +(38147,4,0,-1,'Corrupted Band',963,2,32768,1,534,133,11,-1,-1,60,55,0,0,0,0,0,0,0,0,1,0,3,4,11,3,6,32,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,-1,0,0,0,0,-1,0,-1,0,0,0,0,-1,0,-1,0,0,0,0,-1,0,-1,0,0,0,0,-1,0,-1,1,'',0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,0,'',0,0,0,0), +(41751,0,5,-1,'Black Mushroom',36728,1,0,1,100,5,0,-1,-1,65,55,0,0,0,0,0,0,0,0,20,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,27094,0,-1,0,0,11,1000,0,0,0,0,-1,0,-1,0,0,0,0,-1,0,-1,0,0,0,0,-1,0,-1,0,0,0,0,-1,0,-1,0,'',0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,0,'',0,0,0,0); /*!40000 ALTER TABLE `item_template` ENABLE KEYS */; UNLOCK TABLES; @@ -2462,6 +2475,8 @@ INSERT INTO `mangos_string` VALUES (342,'%s is now not following you.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), (343,'Creature (Entry: %u) cannot be tamed.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), (344,'You already have pet.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(345,'Forced customize for player %s will be requested at next login.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(346,'Forced customize for player %s (GUID #%u) will be requested at next login.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), (400,'|cffff0000[System Message]:|rScripts reloaded',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), (401,'You change security level of account %s to %i.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), (402,'%s changed your security level to %i.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), @@ -2753,10 +2768,54 @@ INSERT INTO `mangos_string` VALUES (1118,'%d - guild: %s (guid: %u) %s',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), (1119,'You must use male or female as gender.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), (1120,'You change gender of %s to %s.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), -(1121,'Your gender changed to %s by %s.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL); +(1121,'Your gender changed to %s by %s.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1122,'Your group is too large for this battleground. Please regroup to join.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1123,'Your group is too large for this arena. Please regroup to join.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1124,'Your group has members not in your arena team. Please regroup to join.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1125,'Your group does not have enough players to join this match.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1126,'The Gold Team wins!',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1127,'The Green Team wins!',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1128,'There aren\'t enough players in this battleground. It will end soon unless some more players join to balance the fight.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1129,'Your group has an offline member. Please remove him before joining.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1130,'Your group has players from the opposing faction. You can\'t join the battleground as a group.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1131,'Your group has players from different battleground brakets. You can\'t join as group.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1132,'Someone in your party is already in this battleground queue. (S)he must leave it before joining as group.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1133,'Someone in your party is Deserter. You can\'t join as group.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1134,'Someone in your party is already in three battleground queues. You cannot join as group.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1135,'You cannot teleport to a battleground or arena map.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1136,'You cannot summon players to a battleground or arena map.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1137,'You must be in GM mode to teleport to a player in a battleground.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1138,'You cannot teleport to a battleground from another battleground. Please leave the current battleground first.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL); /*!40000 ALTER TABLE `mangos_string` ENABLE KEYS */; UNLOCK TABLES; +-- +-- Table structure for table `milling_loot_template` +-- + +DROP TABLE IF EXISTS `milling_loot_template`; +CREATE TABLE `milling_loot_template` ( + `entry` mediumint(8) unsigned NOT NULL default '0', + `item` mediumint(8) unsigned NOT NULL default '0', + `ChanceOrQuestChance` float NOT NULL default '100', + `groupid` tinyint(3) unsigned NOT NULL default '0', + `mincountOrRef` mediumint(9) NOT NULL default '1', + `maxcount` tinyint(3) unsigned NOT NULL default '1', + `lootcondition` tinyint(3) unsigned NOT NULL default '0', + `condition_value1` mediumint(8) unsigned NOT NULL default '0', + `condition_value2` mediumint(8) unsigned NOT NULL default '0', + PRIMARY KEY (`entry`,`item`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=FIXED COMMENT='Loot System'; + +-- +-- Dumping data for table `milling_loot_template` +-- + +LOCK TABLES `milling_loot_template` WRITE; +/*!40000 ALTER TABLE `milling_loot_template` DISABLE KEYS */; +/*!40000 ALTER TABLE `milling_loot_template` ENABLE KEYS */; +UNLOCK TABLES; + -- -- Table structure for table `npc_gossip` -- @@ -3444,6 +3503,16 @@ INSERT INTO `player_classlevelstats` VALUES (1,68,3774,0), (1,69,4109,0), (1,70,4444,0), +(1,71,4720,0), +(1,72,5013,0), +(1,73,5325,0), +(1,74,5656,0), +(1,75,6008,0), +(1,76,6381,0), +(1,77,6778,0), +(1,78,7198,0), +(1,79,7646,0), +(1,80,8121,0), (2,1,28,60), (2,2,36,78), (2,3,44,98), @@ -3514,6 +3583,16 @@ INSERT INTO `player_classlevelstats` VALUES (2,68,2901,2665), (2,69,3134,2809), (2,70,3377,2953), +(2,71,3629,3097), +(2,72,3900,3241), +(2,73,4191,3385), +(2,74,4503,3529), +(2,75,4839,3673), +(2,76,5200,3817), +(2,77,5588,3962), +(2,78,6005,4106), +(2,79,6453,4250), +(2,80,6934,4394), (3,1,46,65), (3,2,53,70), (3,3,60,76), @@ -3584,6 +3663,16 @@ INSERT INTO `player_classlevelstats` VALUES (3,68,3075,3050), (3,69,3316,3217), (3,70,3568,3383), +(3,71,3834,3549), +(3,72,4120,3716), +(3,73,4427,3882), +(3,74,4757,4048), +(3,75,5112,4215), +(3,76,5493,4381), +(3,77,5903,4547), +(3,78,6343,4713), +(3,79,6816,4880), +(3,80,7324,5046), (4,1,25,0), (4,2,32,0), (4,3,49,0), @@ -3654,6 +3743,16 @@ INSERT INTO `player_classlevelstats` VALUES (4,68,3190,0), (4,69,3450,0), (4,70,3704,0), +(4,71,3980,0), +(4,72,4277,0), +(4,73,4596,0), +(4,74,4939,0), +(4,75,5307,0), +(4,76,5703,0), +(4,77,6128,0), +(4,78,6585,0), +(4,79,7076,0), +(4,80,7604,0), (5,1,52,73), (5,2,57,76), (5,3,72,95), @@ -3724,6 +3823,96 @@ INSERT INTO `player_classlevelstats` VALUES (5,68,2936,2371), (5,69,3160,2495), (5,70,3391,2620), +(5,71,3644,2744), +(5,72,3916,2868), +(5,73,4208,2993), +(5,74,4522,3117), +(5,75,4859,3242), +(5,76,5221,3366), +(5,77,5610,3490), +(5,78,6028,3615), +(5,79,6477,3739), +(5,80,6960,3863), +(6,1,22,0), +(6,2,27,0), +(6,3,32,0), +(6,4,37,0), +(6,5,42,0), +(6,6,47,0), +(6,7,52,0), +(6,8,58,0), +(6,9,64,0), +(6,10,70,0), +(6,11,77,0), +(6,12,84,0), +(6,13,92,0), +(6,14,100,0), +(6,15,117,0), +(6,16,127,0), +(6,17,138,0), +(6,18,150,0), +(6,19,163,0), +(6,20,177,0), +(6,21,192,0), +(6,22,208,0), +(6,23,225,0), +(6,24,239,0), +(6,25,258,0), +(6,26,278,0), +(6,27,299,0), +(6,28,321,0), +(6,29,344,0), +(6,30,368,0), +(6,31,393,0), +(6,32,419,0), +(6,33,446,0), +(6,34,474,0), +(6,35,503,0), +(6,36,533,0), +(6,37,564,0), +(6,38,596,0), +(6,39,629,0), +(6,40,698,0), +(6,41,698,0), +(6,42,734,0), +(6,43,771,0), +(6,44,809,0), +(6,45,849,0), +(6,46,891,0), +(6,47,935,0), +(6,48,981,0), +(6,49,1029,0), +(6,50,1079,0), +(6,51,1131,0), +(6,52,1185,0), +(6,53,1241,0), +(6,54,1299,0), +(6,55,1359,0), +(6,56,1421,0), +(6,57,1485,0), +(6,58,1551,0), +(6,59,1619,0), +(6,60,1689,0), +(6,61,1902,0), +(6,62,2129,0), +(6,63,2357,0), +(6,64,2612,0), +(6,65,2883,0), +(6,66,3169,0), +(6,67,3455,0), +(6,68,3774,0), +(6,69,4109,0), +(6,70,4444,0), +(6,71,4720,0), +(6,72,5013,0), +(6,73,5325,0), +(6,74,5656,0), +(6,75,6008,0), +(6,76,6381,0), +(6,77,6778,0), +(6,78,7199,0), +(6,79,7646,0), +(6,80,8121,0), (7,1,37,85), (7,2,44,91), (7,3,51,98), @@ -3794,6 +3983,16 @@ INSERT INTO `player_classlevelstats` VALUES (7,68,2713,2670), (7,69,2931,2814), (7,70,3159,2958), +(7,71,3395,3102), +(7,72,3648,3246), +(7,73,3920,3389), +(7,74,4212,3533), +(7,75,4526,3677), +(7,76,4863,3821), +(7,77,5226,3965), +(7,78,5616,4108), +(7,79,6035,4252), +(7,80,6485,4396), (8,1,32,100), (8,2,47,110), (8,3,52,106), @@ -3864,6 +4063,16 @@ INSERT INTO `player_classlevelstats` VALUES (8,68,2906,2035), (8,69,3136,2138), (8,70,3393,2241), +(8,71,3646,2343), +(8,72,3918,2446), +(8,73,4210,2549), +(8,74,4524,2652), +(8,75,4861,2754), +(8,76,5223,2857), +(8,77,5612,2960), +(8,78,6030,3063), +(8,79,6480,3165), +(8,80,6963,3268), (9,1,23,90), (9,2,28,98), (9,3,43,107), @@ -3934,6 +4143,16 @@ INSERT INTO `player_classlevelstats` VALUES (9,68,2991,2366), (9,69,3235,2490), (9,70,3490,2615), +(9,71,3750,2739), +(9,72,4025,2863), +(9,73,4330,2987), +(9,74,4646,3111), +(9,75,4997,3235), +(9,76,5373,3360), +(9,77,5774,3483), +(9,78,6207,3608), +(9,79,6667,3732), +(9,80,7136,3856), (11,1,44,60), (11,2,51,66), (11,3,58,73), @@ -4003,7 +4222,17 @@ INSERT INTO `player_classlevelstats` VALUES (11,67,2872,2032), (11,68,3114,2145), (11,69,3351,2257), -(11,70,3614,2370); +(11,70,3614,2370), +(11,71,3883,2482), +(11,72,4172,2595), +(11,73,4483,2708), +(11,74,4817,2820), +(11,75,5176,2933), +(11,76,5562,3045), +(11,77,5977,3158), +(11,78,6423,3270), +(11,79,6902,3383), +(11,80,7417,3496); /*!40000 ALTER TABLE `player_classlevelstats` ENABLE KEYS */; UNLOCK TABLES; @@ -4101,6 +4330,16 @@ INSERT INTO `player_levelstats` VALUES (1,1,68,140,93,129,32,50), (1,1,69,143,95,131,33,50), (1,1,70,145,96,133,33,51), +(1,1,71,148,97,140,33,53), +(1,1,72,156,99,143,33,54), +(1,1,73,162,101,148,33,55), +(1,1,74,162,102,148,34,55), +(1,1,75,165,104,150,34,56), +(1,1,76,171,106,156,34,57), +(1,1,77,171,108,157,35,58), +(1,1,78,174,109,159,35,58), +(1,1,79,181,111,165,35,59), +(1,1,80,184,113,168,36,60), (1,2,1,22,20,22,20,21), (1,2,2,23,21,23,21,22), (1,2,3,24,21,24,21,22), @@ -4171,6 +4410,16 @@ INSERT INTO `player_levelstats` VALUES (1,2,68,122,75,116,81,86), (1,2,69,124,76,118,82,88), (1,2,70,126,77,120,83,89), +(1,2,71,148,78,122,84,92), +(1,2,72,150,79,125,86,94), +(1,2,73,152,80,127,87,96), +(1,2,74,156,82,129,89,97), +(1,2,75,158,83,131,90,99), +(1,2,76,162,84,134,92,100), +(1,2,77,164,86,136,93,103), +(1,2,78,167,87,138,95,105), +(1,2,79,170,88,153,96,106), +(1,2,80,173,90,160,98,108), (1,4,1,21,23,21,20,20), (1,4,2,22,24,22,20,20), (1,4,3,23,26,22,20,21), @@ -4241,6 +4490,16 @@ INSERT INTO `player_levelstats` VALUES (1,4,68,92,153,86,38,57), (1,4,69,94,156,88,39,57), (1,4,70,95,158,89,39,58), +(1,4,71,97,161,90,39,60), +(1,4,72,99,164,92,40,60), +(1,4,73,100,167,94,40,61), +(1,4,74,102,170,95,41,62), +(1,4,75,104,173,97,41,63), +(1,4,76,105,176,98,41,64), +(1,4,77,107,179,100,42,65), +(1,4,78,109,183,106,42,66), +(1,4,79,111,186,107,43,67), +(1,4,80,113,189,109,43,69), (1,5,1,20,20,20,22,23), (1,5,2,20,20,20,23,24), (1,5,3,20,20,21,25,26), @@ -4311,6 +4570,96 @@ INSERT INTO `player_levelstats` VALUES (1,5,68,38,44,57,140,146), (1,5,69,39,44,57,143,149), (1,5,70,39,45,58,145,151), +(1,5,71,39,46,59,148,158), +(1,5,72,40,46,59,151,161), +(1,5,73,40,47,60,154,164), +(1,5,74,41,47,61,156,167), +(1,5,75,41,48,62,159,170), +(1,5,76,41,49,63,162,174), +(1,5,77,42,49,64,165,177), +(1,5,78,42,50,65,168,180), +(1,5,79,43,50,66,171,183), +(1,5,80,43,51,67,174,186), +(1,6,1,23,20,22,20,20), +(1,6,2,24,21,23,20,20), +(1,6,3,26,22,24,20,21), +(1,6,4,27,22,26,20,21), +(1,6,5,28,23,27,20,21), +(1,6,6,30,24,28,20,21), +(1,6,7,31,25,29,21,22), +(1,6,8,32,26,30,21,22), +(1,6,9,34,26,32,21,22), +(1,6,10,35,27,33,21,23), +(1,6,11,36,28,34,21,23), +(1,6,12,38,29,35,21,23), +(1,6,13,39,30,37,21,24), +(1,6,14,41,31,38,21,24), +(1,6,15,42,32,39,21,24), +(1,6,16,44,33,41,21,25), +(1,6,17,45,34,42,22,25), +(1,6,18,47,34,43,22,25), +(1,6,19,48,35,45,22,26), +(1,6,20,50,36,46,22,26), +(1,6,21,51,37,48,22,26), +(1,6,22,53,38,49,22,27), +(1,6,23,54,39,51,22,27), +(1,6,24,56,40,52,23,28), +(1,6,25,58,41,53,23,28), +(1,6,26,59,42,55,23,28), +(1,6,27,61,43,56,23,29), +(1,6,28,63,44,58,23,29), +(1,6,29,64,45,59,23,30), +(1,6,30,66,46,61,24,30), +(1,6,31,68,47,62,24,30), +(1,6,32,69,48,64,24,31), +(1,6,33,71,50,66,24,31), +(1,6,34,73,51,67,24,32), +(1,6,35,74,52,69,24,32), +(1,6,36,76,53,70,25,33), +(1,6,37,78,54,72,25,33), +(1,6,38,80,55,74,25,34), +(1,6,39,82,56,75,25,34), +(1,6,40,83,57,77,25,35), +(1,6,41,85,58,79,26,35), +(1,6,42,87,60,80,26,35), +(1,6,43,89,61,82,26,36), +(1,6,44,91,62,84,26,36), +(1,6,45,93,63,85,26,37), +(1,6,46,95,64,87,27,37), +(1,6,47,97,66,89,27,38), +(1,6,48,99,67,91,27,38), +(1,6,49,101,68,93,27,39), +(1,6,50,103,69,94,28,40), +(1,6,51,105,71,96,28,40), +(1,6,52,106,72,97,28,41), +(1,6,53,107,72,98,28,41), +(1,6,54,107,73,98,29,42), +(1,6,55,108,73,99,29,43), +(1,6,56,111,75,102,29,44), +(1,6,57,113,76,104,29,44), +(1,6,58,118,77,106,30,45), +(1,6,59,118,79,108,30,45), +(1,6,60,123,80,110,30,46), +(1,6,61,125,81,112,30,47), +(1,6,62,128,83,114,30,47), +(1,6,63,130,84,117,31,48), +(1,6,64,130,86,119,31,48), +(1,6,65,140,87,128,31,49), +(1,6,66,143,89,131,31,50), +(1,6,67,146,90,133,32,50), +(1,6,68,148,92,135,32,51), +(1,6,69,151,93,138,32,52), +(1,6,70,154,95,140,32,52), +(1,6,71,162,97,144,33,53), +(1,6,72,164,98,146,33,54), +(1,6,73,165,100,148,33,55), +(1,6,74,166,102,151,33,55), +(1,6,75,169,103,154,34,56), +(1,6,76,172,105,157,34,57), +(1,6,77,175,107,157,34,58), +(1,6,78,176,108,157,34,58), +(1,6,79,177,110,157,35,59), +(1,6,80,180,112,160,35,60), (1,8,1,20,20,20,23,22), (1,8,2,20,20,20,24,23), (1,8,3,20,20,21,26,25), @@ -4381,6 +4730,16 @@ INSERT INTO `player_levelstats` VALUES (1,8,68,32,38,50,146,140), (1,8,69,33,39,50,149,143), (1,8,70,33,39,51,151,145), +(1,8,71,33,39,52,154,152), +(1,8,72,33,40,53,160,155), +(1,8,73,33,40,54,160,158), +(1,8,74,34,41,54,163,160), +(1,8,75,34,41,55,166,163), +(1,8,76,34,41,56,169,166), +(1,8,77,35,42,57,172,169), +(1,8,78,35,42,57,175,173), +(1,8,79,35,43,58,178,176), +(1,8,80,36,43,59,181,179), (1,9,1,20,20,21,22,22), (1,9,2,20,20,22,23,23), (1,9,3,21,21,22,24,24), @@ -4451,6 +4810,16 @@ INSERT INTO `player_levelstats` VALUES (1,9,68,50,57,74,129,127), (1,9,69,50,57,75,131,129), (1,9,70,51,58,76,133,131), +(1,9,71,52,59,78,135,146), +(1,9,72,53,59,79,138,148), +(1,9,73,54,60,80,140,151), +(1,9,74,54,61,89,143,154), +(1,9,75,55,62,91,145,156), +(1,9,76,56,63,92,148,159), +(1,9,77,57,64,93,151,162), +(1,9,78,57,65,95,153,165), +(1,9,79,58,66,96,156,168), +(1,9,80,59,67,97,159,170), (2,1,1,26,17,24,17,23), (2,1,2,27,18,25,17,23), (2,1,3,29,19,26,17,24), @@ -4521,6 +4890,16 @@ INSERT INTO `player_levelstats` VALUES (2,1,68,143,90,131,29,53), (2,1,69,146,92,133,30,53), (2,1,70,148,93,135,30,54), +(2,1,71,157,94,142,30,55), +(2,1,72,162,96,148,30,56), +(2,1,73,165,98,150,30,57), +(2,1,74,168,99,153,31,57), +(2,1,75,170,101,154,31,58), +(2,1,76,172,103,156,31,59), +(2,1,77,174,105,159,32,60), +(2,1,78,179,106,162,32,60), +(2,1,79,184,108,167,32,61), +(2,1,80,187,110,170,33,62), (2,3,1,23,20,23,17,24), (2,3,2,23,21,24,18,25), (2,3,3,24,23,25,18,25), @@ -4591,6 +4970,16 @@ INSERT INTO `player_levelstats` VALUES (2,3,68,65,143,107,72,84), (2,3,69,66,146,108,73,85), (2,3,70,67,148,110,74,86), +(2,3,71,68,151,112,75,87), +(2,3,72,69,154,114,76,88), +(2,3,73,70,157,116,77,90), +(2,3,74,71,160,118,79,91), +(2,3,75,72,163,120,80,93), +(2,3,76,73,166,122,81,94), +(2,3,77,74,169,124,83,96), +(2,3,78,75,172,126,84,97), +(2,3,79,76,175,128,85,99), +(2,3,80,77,178,130,87,100), (2,4,1,24,20,23,17,23), (2,4,2,25,21,24,17,23), (2,4,3,25,23,24,17,24), @@ -4661,6 +5050,96 @@ INSERT INTO `player_levelstats` VALUES (2,4,68,95,150,88,35,59), (2,4,69,97,153,90,36,60), (2,4,70,98,155,91,36,61), +(2,4,71,100,158,92,36,62), +(2,4,72,102,161,94,37,62), +(2,4,73,103,164,99,37,63), +(2,4,74,105,167,100,38,64), +(2,4,75,107,170,102,38,65), +(2,4,76,108,173,102,38,66), +(2,4,77,110,176,102,39,67), +(2,4,78,112,180,103,39,68), +(2,4,79,114,183,105,40,69), +(2,4,80,116,186,107,40,70), +(2,6,1,26,17,24,17,23), +(2,6,2,27,18,25,17,23), +(2,6,3,29,19,26,17,24), +(2,6,4,30,19,27,17,24), +(2,6,5,31,20,29,17,24), +(2,6,6,32,21,30,17,24), +(2,6,7,34,22,31,18,25), +(2,6,8,35,23,32,18,25), +(2,6,9,37,24,34,18,25), +(2,6,10,38,24,35,18,26), +(2,6,11,39,25,36,18,26), +(2,6,12,41,26,37,18,26), +(2,6,13,42,27,39,18,27), +(2,6,14,44,28,40,18,27), +(2,6,15,45,29,41,18,27), +(2,6,16,47,30,43,19,28), +(2,6,17,48,31,44,19,28), +(2,6,18,50,32,45,19,28), +(2,6,19,51,33,47,19,29), +(2,6,20,53,34,48,19,29), +(2,6,21,54,34,50,19,29), +(2,6,22,56,35,51,19,30), +(2,6,23,57,36,52,20,30), +(2,6,24,59,37,54,20,30), +(2,6,25,60,38,55,20,31), +(2,6,26,62,39,57,20,31), +(2,6,27,64,40,58,20,32), +(2,6,28,65,41,60,20,32), +(2,6,29,67,43,61,21,32), +(2,6,30,69,44,63,21,33), +(2,6,31,70,45,64,21,33), +(2,6,32,72,46,66,21,34), +(2,6,33,74,47,67,21,34), +(2,6,34,76,48,69,21,35), +(2,6,35,77,49,71,22,35), +(2,6,36,79,50,72,22,36), +(2,6,37,81,51,74,22,36), +(2,6,38,83,52,76,22,36), +(2,6,39,84,53,77,22,37), +(2,6,40,86,55,79,23,37), +(2,6,41,88,56,81,23,38), +(2,6,42,90,57,82,23,38), +(2,6,43,92,58,84,23,39), +(2,6,44,94,59,86,23,39), +(2,6,45,96,60,87,24,40), +(2,6,46,98,62,89,24,40), +(2,6,47,100,63,91,24,41), +(2,6,48,101,64,93,24,41), +(2,6,49,103,65,94,25,42), +(2,6,50,105,66,96,25,42), +(2,6,51,107,68,98,25,43), +(2,6,52,109,69,100,25,43), +(2,6,53,110,69,100,25,44), +(2,6,54,111,70,101,26,45), +(2,6,55,111,70,101,26,45), +(2,6,56,114,72,104,26,46), +(2,6,57,116,73,106,26,46), +(2,6,58,118,74,108,27,47), +(2,6,59,124,76,110,27,47), +(2,6,60,126,77,112,27,48), +(2,6,61,128,78,114,27,49), +(2,6,62,131,80,116,27,49), +(2,6,63,133,81,119,28,50), +(2,6,64,136,83,121,28,50), +(2,6,65,136,84,123,28,51), +(2,6,66,142,86,126,28,52), +(2,6,67,145,87,128,29,52), +(2,6,68,147,89,130,29,53), +(2,6,69,150,90,133,29,54), +(2,6,70,157,92,135,29,54), +(2,6,71,160,94,138,30,55), +(2,6,72,163,95,140,30,56), +(2,6,73,166,97,151,30,57), +(2,6,74,169,99,154,30,57), +(2,6,75,172,100,156,31,58), +(2,6,76,175,102,160,31,59), +(2,6,77,179,104,162,31,60), +(2,6,78,182,105,165,31,60), +(2,6,79,191,107,168,32,61), +(2,6,80,194,109,171,32,62), (2,7,1,24,17,23,18,25), (2,7,2,25,17,24,19,26), (2,7,3,26,18,25,20,27), @@ -4731,6 +5210,16 @@ INSERT INTO `player_levelstats` VALUES (2,7,68,102,59,113,102,119), (2,7,69,103,60,114,103,121), (2,7,70,105,61,116,105,123), +(2,7,71,106,62,118,117,125), +(2,7,72,108,63,120,119,128), +(2,7,73,110,64,122,122,130), +(2,7,74,112,65,125,124,132), +(2,7,75,114,66,127,126,134), +(2,7,76,116,67,129,128,137), +(2,7,77,117,68,131,128,139), +(2,7,78,119,69,133,133,141), +(2,7,79,121,70,136,135,144), +(2,7,80,123,71,138,137,146), (2,9,1,23,17,23,19,25), (2,9,2,23,17,24,20,26), (2,9,3,24,18,24,21,27), @@ -4801,6 +5290,16 @@ INSERT INTO `player_levelstats` VALUES (2,9,68,53,54,76,126,130), (2,9,69,53,54,77,128,132), (2,9,70,54,55,78,130,134), +(2,9,71,55,56,88,134,145), +(2,9,72,56,56,89,135,147), +(2,9,73,57,57,90,137,150), +(2,9,74,57,58,91,142,153), +(2,9,75,58,59,93,142,155), +(2,9,76,59,60,94,145,158), +(2,9,77,60,61,95,148,161), +(2,9,78,60,62,97,150,164), +(2,9,79,61,63,98,153,167), +(2,9,80,62,64,99,156,169), (3,1,1,25,16,25,19,19), (3,1,2,26,17,26,19,19), (3,1,3,28,18,27,19,20), @@ -4871,6 +5370,16 @@ INSERT INTO `player_levelstats` VALUES (3,1,68,142,89,132,31,49), (3,1,69,145,91,134,32,49), (3,1,70,147,92,136,32,50), +(3,1,71,150,93,138,32,51), +(3,1,72,152,95,141,32,52), +(3,1,73,164,97,151,32,53), +(3,1,74,164,98,151,33,53), +(3,1,75,170,100,156,33,54), +(3,1,76,173,102,160,33,55), +(3,1,77,173,104,160,34,56), +(3,1,78,176,105,162,34,56), +(3,1,79,183,107,168,34,57), +(3,1,80,186,109,171,35,58), (3,2,1,24,16,25,19,20), (3,2,2,25,17,26,20,21), (3,2,3,26,17,27,20,21), @@ -4941,6 +5450,16 @@ INSERT INTO `player_levelstats` VALUES (3,2,68,124,71,119,80,85), (3,2,69,126,72,121,81,87), (3,2,70,128,73,123,82,88), +(3,2,71,150,74,125,83,89), +(3,2,72,152,75,128,85,91), +(3,2,73,156,76,130,86,93), +(3,2,74,158,78,132,88,94), +(3,2,75,161,79,134,89,96), +(3,2,76,164,80,137,91,97), +(3,2,77,166,82,139,92,99), +(3,2,78,170,83,141,94,101), +(3,2,79,172,84,144,95,102), +(3,2,80,175,86,146,97,104), (3,3,1,22,19,24,19,20), (3,3,2,22,20,25,20,21), (3,3,3,23,22,26,20,21), @@ -5011,6 +5530,16 @@ INSERT INTO `player_levelstats` VALUES (3,3,68,64,142,108,74,80), (3,3,69,65,145,109,75,81), (3,3,70,66,147,111,76,82), +(3,3,71,67,150,113,77,83), +(3,3,72,68,153,115,78,84), +(3,3,73,69,156,117,79,86), +(3,3,74,70,159,119,81,87), +(3,3,75,71,162,121,82,89), +(3,3,76,72,165,123,83,90), +(3,3,77,73,168,125,85,92), +(3,3,78,74,171,127,86,93), +(3,3,79,75,174,129,87,95), +(3,3,80,76,177,131,89,96), (3,4,1,23,19,24,19,19), (3,4,2,24,20,25,19,19), (3,4,3,24,22,25,19,20), @@ -5081,6 +5610,16 @@ INSERT INTO `player_levelstats` VALUES (3,4,68,94,149,89,37,56), (3,4,69,96,152,91,38,56), (3,4,70,97,154,92,38,57), +(3,4,71,99,157,93,38,58), +(3,4,72,101,160,96,39,58), +(3,4,73,102,163,97,39,59), +(3,4,74,104,166,98,40,60), +(3,4,75,106,169,100,40,61), +(3,4,76,107,172,101,40,62), +(3,4,77,109,175,103,41,63), +(3,4,78,111,179,105,41,64), +(3,4,79,113,182,106,42,65), +(3,4,80,115,185,108,42,66), (3,5,1,22,16,23,21,22), (3,5,2,22,16,23,22,23), (3,5,3,22,16,24,24,25), @@ -5151,6 +5690,96 @@ INSERT INTO `player_levelstats` VALUES (3,5,68,40,40,59,139,145), (3,5,69,41,40,60,142,148), (3,5,70,41,41,61,144,150), +(3,5,71,41,42,62,147,153), +(3,5,72,42,42,62,150,163), +(3,5,73,42,43,63,153,166), +(3,5,74,43,43,64,155,170), +(3,5,75,43,44,65,158,173), +(3,5,76,43,45,66,161,176), +(3,5,77,44,45,67,164,179), +(3,5,78,44,46,68,167,182), +(3,5,79,45,46,69,170,184), +(3,5,80,45,47,70,173,189), +(3,6,1,25,16,25,19,19), +(3,6,2,26,17,26,19,19), +(3,6,3,28,18,27,19,20), +(3,6,4,29,18,28,19,20), +(3,6,5,30,19,30,19,20), +(3,6,6,31,20,31,19,20), +(3,6,7,33,21,32,20,21), +(3,6,8,34,22,33,20,21), +(3,6,9,36,23,35,20,21), +(3,6,10,37,23,36,20,22), +(3,6,11,38,24,37,20,22), +(3,6,12,40,25,38,20,22), +(3,6,13,41,26,40,20,23), +(3,6,14,43,27,41,20,23), +(3,6,15,44,28,42,20,23), +(3,6,16,46,29,44,21,24), +(3,6,17,47,30,45,21,24), +(3,6,18,49,31,46,21,24), +(3,6,19,50,32,48,21,25), +(3,6,20,52,33,49,21,25), +(3,6,21,53,34,51,21,26), +(3,6,22,55,34,52,21,26), +(3,6,23,56,35,53,21,26), +(3,6,24,58,36,55,22,27), +(3,6,25,59,37,56,22,27), +(3,6,26,61,38,58,22,27), +(3,6,27,63,39,59,22,28), +(3,6,28,64,41,61,22,28), +(3,6,29,66,42,62,22,29), +(3,6,30,68,43,64,23,29), +(3,6,31,69,44,65,23,30), +(3,6,32,71,45,67,23,30), +(3,6,33,73,46,68,23,30), +(3,6,34,75,47,70,23,31), +(3,6,35,76,48,72,24,31), +(3,6,36,78,49,73,24,32), +(3,6,37,80,50,75,24,32), +(3,6,38,82,51,76,24,33), +(3,6,39,84,52,78,24,33), +(3,6,40,85,54,80,24,34), +(3,6,41,87,55,81,25,34), +(3,6,42,89,56,83,25,35), +(3,6,43,91,57,85,25,35), +(3,6,44,93,58,87,25,36), +(3,6,45,95,59,88,26,36), +(3,6,46,97,61,90,26,37), +(3,6,47,99,62,92,26,37), +(3,6,48,101,63,94,26,38), +(3,6,49,102,64,95,26,38), +(3,6,50,104,65,97,27,39), +(3,6,51,106,67,99,27,39), +(3,6,52,108,68,99,27,40), +(3,6,53,109,68,101,27,40), +(3,6,54,110,69,101,28,41), +(3,6,55,110,69,102,28,41), +(3,6,56,113,71,105,28,42), +(3,6,57,118,72,107,28,42), +(3,6,58,120,73,109,29,43), +(3,6,59,123,75,111,29,43), +(3,6,60,125,76,113,29,44), +(3,6,61,126,77,115,29,45), +(3,6,62,127,79,117,29,45), +(3,6,63,129,80,120,30,46), +(3,6,64,132,82,122,30,46), +(3,6,65,135,83,124,30,47), +(3,6,66,137,85,127,30,48), +(3,6,67,144,86,129,31,48), +(3,6,68,146,88,131,31,49), +(3,6,69,149,89,133,31,50), +(3,6,70,152,91,136,31,50), +(3,6,71,154,93,139,32,51), +(3,6,72,157,94,141,32,52), +(3,6,73,160,96,144,32,53), +(3,6,74,163,98,146,32,53), +(3,6,75,166,99,150,33,54), +(3,6,76,169,101,152,33,55), +(3,6,77,172,103,155,33,56), +(3,6,78,176,104,157,33,56), +(3,6,79,179,106,160,34,57), +(3,6,80,182,108,163,34,58), (4,1,1,20,25,21,20,20), (4,1,2,21,26,22,20,20), (4,1,3,23,27,23,20,21), @@ -5221,6 +5850,16 @@ INSERT INTO `player_levelstats` VALUES (4,1,68,138,98,128,32,50), (4,1,69,140,100,130,33,50), (4,1,70,142,101,132,33,51), +(4,1,71,145,102,134,33,52), +(4,1,72,147,104,137,33,53), +(4,1,73,150,106,139,33,54), +(4,1,74,153,107,142,34,54), +(4,1,75,156,109,144,34,55), +(4,1,76,159,111,148,34,56), +(4,1,77,162,113,150,35,57), +(4,1,78,165,114,152,35,57), +(4,1,79,178,116,164,35,58), +(4,1,80,181,118,167,36,59), (4,3,1,17,28,20,20,21), (4,3,2,17,29,21,21,22), (4,3,3,18,31,22,21,22), @@ -5291,6 +5930,16 @@ INSERT INTO `player_levelstats` VALUES (4,3,68,59,151,104,75,81), (4,3,69,60,154,105,76,82), (4,3,70,61,156,107,77,83), +(4,3,71,62,159,109,78,84), +(4,3,72,63,162,111,79,85), +(4,3,73,64,165,113,80,87), +(4,3,74,65,168,115,82,88), +(4,3,75,66,171,117,83,90), +(4,3,76,67,174,119,84,91), +(4,3,77,68,177,121,86,93), +(4,3,78,69,180,123,87,94), +(4,3,79,70,190,125,91,96), +(4,3,80,71,193,127,93,97), (4,4,1,18,28,20,20,20), (4,4,2,19,29,21,20,20), (4,4,3,20,31,21,20,21), @@ -5361,6 +6010,16 @@ INSERT INTO `player_levelstats` VALUES (4,4,68,89,158,85,38,57), (4,4,69,91,160,87,39,57), (4,4,70,92,163,88,39,58), +(4,4,71,94,166,90,39,59), +(4,4,72,96,169,91,40,59), +(4,4,73,97,172,93,40,60), +(4,4,74,99,175,94,41,61), +(4,4,75,101,178,96,41,62), +(4,4,76,102,181,97,41,63), +(4,4,77,104,184,99,42,64), +(4,4,78,106,188,101,42,65), +(4,4,79,108,191,102,43,66), +(4,4,80,110,194,104,43,67), (4,5,1,17,25,19,22,23), (4,5,2,17,25,19,23,24), (4,5,3,17,25,20,25,26), @@ -5431,6 +6090,96 @@ INSERT INTO `player_levelstats` VALUES (4,5,68,35,49,56,140,146), (4,5,69,36,49,56,143,149), (4,5,70,36,50,57,145,151), +(4,5,71,36,51,58,148,161), +(4,5,72,37,51,58,151,164), +(4,5,73,37,52,59,154,168), +(4,5,74,38,52,60,156,171), +(4,5,75,38,53,61,159,174), +(4,5,76,38,54,62,162,177), +(4,5,77,39,54,63,165,180), +(4,5,78,39,55,64,168,183), +(4,5,79,40,55,65,171,186), +(4,5,80,40,56,66,200,191), +(4,6,1,20,25,21,20,20), +(4,6,2,21,26,22,20,20), +(4,6,3,23,27,23,20,21), +(4,6,4,24,27,25,20,21), +(4,6,5,25,28,26,20,21), +(4,6,6,27,29,27,20,21), +(4,6,7,28,30,28,21,22), +(4,6,8,29,31,29,21,22), +(4,6,9,31,31,31,21,22), +(4,6,10,32,32,32,21,23), +(4,6,11,33,33,33,21,23), +(4,6,12,35,34,34,21,23), +(4,6,13,36,35,36,21,24), +(4,6,14,38,36,37,21,24), +(4,6,15,39,37,38,21,24), +(4,6,16,41,37,40,21,25), +(4,6,17,42,38,41,22,25), +(4,6,18,44,39,43,22,25), +(4,6,19,45,40,44,22,26), +(4,6,20,47,41,45,22,26), +(4,6,21,48,42,47,22,26), +(4,6,22,50,43,48,22,27), +(4,6,23,52,44,50,22,27), +(4,6,24,53,45,51,23,28), +(4,6,25,55,46,52,23,28), +(4,6,26,56,47,54,23,28), +(4,6,27,58,48,55,23,29), +(4,6,28,60,49,57,23,29), +(4,6,29,61,50,58,23,30), +(4,6,30,63,51,60,24,30), +(4,6,31,65,52,62,24,30), +(4,6,32,66,53,63,24,31), +(4,6,33,68,54,65,24,31), +(4,6,34,70,55,66,24,32), +(4,6,35,72,56,68,24,32), +(4,6,36,73,58,69,25,33), +(4,6,37,75,59,71,25,33), +(4,6,38,77,60,73,25,34), +(4,6,39,79,61,74,25,34), +(4,6,40,81,62,76,25,35), +(4,6,41,82,63,78,26,35), +(4,6,42,84,64,79,26,35), +(4,6,43,86,66,81,26,36), +(4,6,44,88,67,83,26,36), +(4,6,45,90,68,85,26,37), +(4,6,46,92,69,86,27,37), +(4,6,47,94,70,88,27,38), +(4,6,48,96,72,90,27,38), +(4,6,49,98,73,92,27,39), +(4,6,50,100,74,93,28,40), +(4,6,51,101,75,94,28,40), +(4,6,52,102,76,95,28,41), +(4,6,53,103,77,96,28,41), +(4,6,54,104,77,97,29,42), +(4,6,55,105,78,98,29,42), +(4,6,56,108,80,101,29,43), +(4,6,57,113,81,103,29,43), +(4,6,58,115,82,105,30,44), +(4,6,59,115,84,107,30,44), +(4,6,60,120,85,109,30,45), +(4,6,61,122,86,111,30,46), +(4,6,62,122,88,113,30,46), +(4,6,63,127,89,116,31,47), +(4,6,64,127,91,118,31,47), +(4,6,65,133,92,120,31,48), +(4,6,66,135,94,123,31,49), +(4,6,67,136,95,125,32,49), +(4,6,68,137,97,127,32,50), +(4,6,69,140,98,130,32,51), +(4,6,70,147,100,132,32,51), +(4,6,71,154,102,135,33,52), +(4,6,72,156,103,137,33,53), +(4,6,73,157,105,140,33,54), +(4,6,74,158,107,142,33,54), +(4,6,75,161,108,145,34,55), +(4,6,76,164,110,148,34,56), +(4,6,77,167,112,150,34,57), +(4,6,78,170,113,153,34,57), +(4,6,79,172,115,156,35,58), +(4,6,80,177,117,159,35,59), (4,11,1,18,25,19,22,22), (4,11,2,19,25,20,23,23), (4,11,3,19,26,20,24,24), @@ -5501,6 +6250,16 @@ INSERT INTO `player_levelstats` VALUES (4,11,68,71,73,80,116,129), (4,11,69,72,74,81,118,131), (4,11,70,73,75,82,120,133), +(4,11,71,75,76,83,122,135), +(4,11,72,76,78,85,125,138), +(4,11,73,77,79,86,127,140), +(4,11,74,78,80,88,131,143), +(4,11,75,80,81,89,133,145), +(4,11,76,81,82,91,134,148), +(4,11,77,82,83,92,136,151), +(4,11,78,84,85,94,138,153), +(4,11,79,85,86,95,141,156), +(4,11,80,86,87,97,143,159), (5,1,1,22,18,23,18,25), (5,1,2,23,19,24,18,25), (5,1,3,25,20,25,18,26), @@ -5571,6 +6330,16 @@ INSERT INTO `player_levelstats` VALUES (5,1,68,139,91,130,30,55), (5,1,69,142,93,132,31,55), (5,1,70,144,94,134,31,56), +(5,1,71,147,95,136,31,57), +(5,1,72,150,97,139,31,58), +(5,1,73,152,99,141,31,59), +(5,1,74,155,100,144,32,59), +(5,1,75,158,102,146,32,60), +(5,1,76,163,104,149,32,61), +(5,1,77,167,106,152,33,62), +(5,1,78,167,107,154,33,62), +(5,1,79,170,109,157,33,63), +(5,1,80,173,111,160,34,64), (5,4,1,20,21,22,18,25), (5,4,2,21,22,23,18,25), (5,4,3,22,24,23,18,26), @@ -5641,6 +6410,16 @@ INSERT INTO `player_levelstats` VALUES (5,4,68,91,151,87,36,61), (5,4,69,93,154,89,37,62), (5,4,70,94,156,90,37,63), +(5,4,71,96,159,91,37,64), +(5,4,72,98,162,93,38,64), +(5,4,73,99,165,95,38,65), +(5,4,74,101,168,96,39,66), +(5,4,75,103,171,98,39,67), +(5,4,76,104,174,99,39,68), +(5,4,77,106,177,101,40,69), +(5,4,78,108,181,103,40,70), +(5,4,79,110,184,104,41,71), +(5,4,80,112,187,106,41,72), (5,5,1,19,18,21,20,28), (5,5,2,19,18,21,21,29), (5,5,3,19,18,22,23,31), @@ -5711,6 +6490,96 @@ INSERT INTO `player_levelstats` VALUES (5,5,68,37,42,58,138,151), (5,5,69,38,42,58,141,154), (5,5,70,38,43,59,143,156), +(5,5,71,38,44,60,146,159), +(5,5,72,39,44,60,149,162), +(5,5,73,39,45,61,152,165), +(5,5,74,40,45,62,157,168), +(5,5,75,40,46,63,157,171), +(5,5,76,40,47,64,160,174), +(5,5,77,41,47,65,163,177), +(5,5,78,41,48,66,166,180), +(5,5,79,42,48,67,169,183), +(5,5,80,42,49,68,172,186), +(5,6,1,22,18,23,18,25), +(5,6,2,23,19,24,18,25), +(5,6,3,25,20,25,18,26), +(5,6,4,26,20,26,18,26), +(5,6,5,27,21,28,18,26), +(5,6,6,29,22,29,18,26), +(5,6,7,30,23,30,19,27), +(5,6,8,31,24,31,19,27), +(5,6,9,33,25,33,19,27), +(5,6,10,34,25,34,19,28), +(5,6,11,35,26,35,19,28), +(5,6,12,37,27,36,19,28), +(5,6,13,38,28,38,19,28), +(5,6,14,40,29,39,19,29), +(5,6,15,41,30,40,19,29), +(5,6,16,43,31,42,20,29), +(5,6,17,44,32,43,20,30), +(5,6,18,46,33,44,20,30), +(5,6,19,47,34,46,20,31), +(5,6,20,49,34,47,20,31), +(5,6,21,50,35,49,20,31), +(5,6,22,52,36,50,20,32), +(5,6,23,53,37,51,21,32), +(5,6,24,55,38,53,21,32), +(5,6,25,57,39,54,21,33), +(5,6,26,58,40,56,21,33), +(5,6,27,60,41,57,21,34), +(5,6,28,62,42,59,21,34), +(5,6,29,63,43,60,21,34), +(5,6,30,65,44,62,22,35), +(5,6,31,67,46,63,22,35), +(5,6,32,68,47,65,22,36), +(5,6,33,70,48,67,22,36), +(5,6,34,72,49,68,22,36), +(5,6,35,74,50,70,23,37), +(5,6,36,75,51,71,23,37), +(5,6,37,77,52,73,23,38), +(5,6,38,79,53,75,23,38), +(5,6,39,81,54,76,23,39), +(5,6,40,83,55,78,24,39), +(5,6,41,84,57,80,24,40), +(5,6,42,86,58,81,24,40), +(5,6,43,88,59,83,24,41), +(5,6,44,90,60,85,24,41), +(5,6,45,92,61,86,25,42), +(5,6,46,94,62,88,25,42), +(5,6,47,96,64,90,25,43), +(5,6,48,98,65,92,25,43), +(5,6,49,100,66,93,25,44), +(5,6,50,102,67,95,26,44), +(5,6,51,103,67,96,26,45), +(5,6,52,104,68,97,26,45), +(5,6,53,105,69,98,26,46), +(5,6,54,106,70,99,27,46), +(5,6,55,107,71,100,27,47), +(5,6,56,110,73,103,27,48), +(5,6,57,112,74,105,27,48), +(5,6,58,114,75,107,28,49), +(5,6,59,119,77,109,28,49), +(5,6,60,122,78,111,28,50), +(5,6,61,124,79,113,28,51), +(5,6,62,127,81,115,28,51), +(5,6,63,129,82,118,29,52), +(5,6,64,136,84,120,29,52), +(5,6,65,137,85,123,29,53), +(5,6,66,138,87,125,29,54), +(5,6,67,141,88,127,30,54), +(5,6,68,143,90,129,30,55), +(5,6,69,146,91,132,30,56), +(5,6,70,149,93,134,30,56), +(5,6,71,152,95,137,31,57), +(5,6,72,154,96,139,31,58), +(5,6,73,157,98,142,31,59), +(5,6,74,158,100,145,31,59), +(5,6,75,159,101,147,32,60), +(5,6,76,162,103,150,32,61), +(5,6,77,167,105,152,32,62), +(5,6,78,173,106,155,32,62), +(5,6,79,174,108,158,33,63), +(5,6,80,174,110,161,33,64), (5,8,1,19,18,21,21,27), (5,8,2,19,18,21,22,28), (5,8,3,19,18,22,24,30), @@ -5781,6 +6650,16 @@ INSERT INTO `player_levelstats` VALUES (5,8,68,31,36,51,144,145), (5,8,69,32,37,51,147,148), (5,8,70,32,37,52,149,150), +(5,8,71,32,37,53,152,153), +(5,8,72,32,38,54,155,156), +(5,8,73,32,38,55,158,159), +(5,8,74,33,39,55,161,161), +(5,8,75,33,39,56,164,164), +(5,8,76,33,39,57,167,167), +(5,8,77,34,40,58,170,170), +(5,8,78,34,40,58,173,173), +(5,8,79,34,41,59,176,176), +(5,8,80,35,41,60,179,179), (5,9,1,19,18,22,20,27), (5,9,2,19,18,23,21,28), (5,9,3,20,19,23,22,29), @@ -5851,6 +6730,16 @@ INSERT INTO `player_levelstats` VALUES (5,9,68,49,55,75,127,132), (5,9,69,49,55,76,129,134), (5,9,70,50,56,77,131,136), +(5,9,71,51,57,86,135,147), +(5,9,72,52,57,88,136,149), +(5,9,73,53,58,89,138,152), +(5,9,74,53,59,90,141,155), +(5,9,75,54,60,92,143,157), +(5,9,76,55,61,93,146,160), +(5,9,77,56,62,94,149,163), +(5,9,78,56,63,96,151,166), +(5,9,79,57,64,97,154,169), +(5,9,80,58,65,99,157,171), (6,1,1,28,15,24,15,22), (6,1,2,29,16,25,15,22), (6,1,3,31,17,26,15,23), @@ -5921,6 +6810,16 @@ INSERT INTO `player_levelstats` VALUES (6,1,68,145,88,131,27,52), (6,1,69,148,90,133,28,52), (6,1,70,150,91,135,28,53), +(6,1,71,153,92,137,28,54), +(6,1,72,155,94,140,28,55), +(6,1,73,158,96,142,28,56), +(6,1,74,161,97,145,29,56), +(6,1,75,164,99,147,29,57), +(6,1,76,167,101,150,29,58), +(6,1,77,170,103,153,30,59), +(6,1,78,173,104,155,30,59), +(6,1,79,176,106,164,30,60), +(6,1,80,179,108,170,31,61), (6,3,1,25,18,23,15,23), (6,3,2,25,19,24,16,24), (6,3,3,26,21,25,16,24), @@ -5991,6 +6890,96 @@ INSERT INTO `player_levelstats` VALUES (6,3,68,67,141,107,70,83), (6,3,69,68,144,108,71,84), (6,3,70,69,146,110,72,85), +(6,3,71,70,149,112,73,86), +(6,3,72,71,152,114,74,87), +(6,3,73,72,155,116,75,89), +(6,3,74,73,158,118,77,90), +(6,3,75,74,161,120,78,92), +(6,3,76,75,164,122,79,93), +(6,3,77,76,167,124,81,95), +(6,3,78,77,176,126,85,96), +(6,3,79,78,179,128,86,98), +(6,3,80,79,183,130,88,99), +(6,6,1,28,15,24,15,22), +(6,6,2,29,16,25,15,22), +(6,6,3,31,17,26,15,23), +(6,6,4,32,17,27,15,23), +(6,6,5,33,18,29,15,23), +(6,6,6,34,19,30,15,23), +(6,6,7,36,20,31,16,24), +(6,6,8,37,21,32,16,24), +(6,6,9,38,22,34,16,24), +(6,6,10,40,22,35,16,25), +(6,6,11,41,23,36,16,25), +(6,6,12,43,24,37,16,25), +(6,6,13,44,25,39,16,26), +(6,6,14,46,26,40,16,26), +(6,6,15,47,27,41,17,26), +(6,6,16,48,28,43,17,27), +(6,6,17,50,29,44,17,27), +(6,6,18,51,30,45,17,27), +(6,6,19,53,31,47,17,28), +(6,6,20,54,32,48,17,28), +(6,6,21,56,33,50,17,28), +(6,6,22,58,34,51,18,29), +(6,6,23,59,35,52,18,29), +(6,6,24,61,36,54,18,30), +(6,6,25,62,37,55,18,30), +(6,6,26,64,38,57,18,30), +(6,6,27,66,39,58,18,31), +(6,6,28,67,40,60,18,31), +(6,6,29,69,41,61,19,32), +(6,6,30,71,42,63,19,32), +(6,6,31,72,43,64,19,32), +(6,6,32,74,44,66,19,33), +(6,6,33,76,45,67,19,33), +(6,6,34,77,46,69,20,34), +(6,6,35,79,47,71,20,34), +(6,6,36,81,48,72,20,35), +(6,6,37,83,49,74,20,35), +(6,6,38,85,50,76,20,35), +(6,6,39,86,51,77,21,36), +(6,6,40,88,53,79,21,36), +(6,6,41,90,54,81,21,37), +(6,6,42,92,55,82,21,37), +(6,6,43,94,56,84,21,38), +(6,6,44,96,57,86,22,38), +(6,6,45,98,58,87,22,39), +(6,6,46,99,60,89,22,39), +(6,6,47,101,60,91,22,40), +(6,6,48,103,61,93,22,40), +(6,6,49,105,62,94,23,41), +(6,6,50,107,63,96,23,41), +(6,6,51,109,64,97,23,42), +(6,6,52,110,65,98,23,42), +(6,6,53,111,66,99,24,43), +(6,6,54,112,67,100,24,44), +(6,6,55,113,68,101,24,44), +(6,6,56,116,70,104,24,45), +(6,6,57,121,71,106,24,45), +(6,6,58,123,72,108,25,46), +(6,6,59,123,74,110,25,46), +(6,6,60,125,75,112,25,47), +(6,6,61,127,76,114,25,48), +(6,6,62,133,78,116,25,48), +(6,6,63,135,79,119,26,49), +(6,6,64,139,81,121,26,49), +(6,6,65,142,82,123,26,50), +(6,6,66,146,84,126,26,51), +(6,6,67,150,85,132,27,51), +(6,6,68,153,87,137,27,52), +(6,6,69,157,88,140,27,53), +(6,6,70,160,90,143,27,53), +(6,6,71,163,92,146,28,54), +(6,6,72,165,93,148,28,55), +(6,6,73,167,95,150,28,56), +(6,6,74,171,97,153,28,56), +(6,6,75,174,98,156,29,57), +(6,6,76,178,100,156,29,58), +(6,6,77,179,102,156,29,59), +(6,6,78,179,103,156,29,59), +(6,6,79,182,105,159,30,60), +(6,6,80,185,107,162,30,61), (6,7,1,26,15,23,16,24), (6,7,2,27,15,24,17,25), (6,7,3,28,16,25,18,26), @@ -6061,6 +7050,16 @@ INSERT INTO `player_levelstats` VALUES (6,7,68,104,57,113,100,118), (6,7,69,105,58,114,101,120), (6,7,70,107,59,116,103,122), +(6,7,71,108,60,118,113,124), +(6,7,72,110,61,120,117,127), +(6,7,73,112,62,122,119,129), +(6,7,74,114,63,125,122,131), +(6,7,75,116,64,127,124,133), +(6,7,76,118,65,129,126,136), +(6,7,77,119,66,131,128,138), +(6,7,78,121,67,133,130,140), +(6,7,79,123,68,136,133,143), +(6,7,80,125,69,138,135,145), (6,11,1,26,15,22,17,24), (6,11,2,27,16,23,18,25), (6,11,3,27,16,23,19,26), @@ -6131,6 +7130,16 @@ INSERT INTO `player_levelstats` VALUES (6,11,68,79,63,83,111,131), (6,11,69,80,64,84,113,133), (6,11,70,81,65,85,115,135), +(6,11,71,83,66,86,117,137), +(6,11,72,84,68,88,120,140), +(6,11,73,85,69,89,122,142), +(6,11,74,86,70,91,124,145), +(6,11,75,88,71,92,126,147), +(6,11,76,89,72,94,128,150), +(6,11,77,90,73,95,131,153), +(6,11,78,92,75,97,133,155), +(6,11,79,93,76,98,136,158), +(6,11,80,94,77,100,138,185), (7,1,1,18,23,21,24,20), (7,1,2,19,24,22,24,20), (7,1,3,21,25,23,24,21), @@ -6201,6 +7210,16 @@ INSERT INTO `player_levelstats` VALUES (7,1,68,136,96,128,36,50), (7,1,69,138,98,130,37,50), (7,1,70,140,99,132,37,51), +(7,1,71,143,100,134,37,52), +(7,1,72,145,102,137,37,53), +(7,1,73,148,104,139,37,54), +(7,1,74,151,105,142,38,54), +(7,1,75,154,107,144,38,55), +(7,1,76,157,109,147,38,56), +(7,1,77,163,111,153,39,57), +(7,1,78,169,112,158,39,57), +(7,1,79,172,114,161,39,58), +(7,1,80,175,116,164,40,59), (7,4,1,16,26,20,24,20), (7,4,2,17,27,21,24,20), (7,4,3,18,29,21,24,21), @@ -6271,6 +7290,96 @@ INSERT INTO `player_levelstats` VALUES (7,4,68,87,156,85,42,57), (7,4,69,89,158,87,43,57), (7,4,70,90,161,88,43,58), +(7,4,71,92,164,89,44,59), +(7,4,72,94,167,91,45,59), +(7,4,73,95,170,93,45,60), +(7,4,74,97,173,94,46,61), +(7,4,75,99,176,96,46,62), +(7,4,76,100,179,97,46,63), +(7,4,77,102,182,102,47,64), +(7,4,78,104,186,105,47,65), +(7,4,79,106,189,106,48,66), +(7,4,80,108,192,108,48,67), +(7,6,1,18,23,21,24,20), +(7,6,2,19,24,22,24,20), +(7,6,3,21,25,23,24,21), +(7,6,4,22,25,25,24,21), +(7,6,5,23,26,26,24,21), +(7,6,6,25,27,27,24,21), +(7,6,7,26,28,28,24,22), +(7,6,8,27,29,29,25,22), +(7,6,9,29,29,31,25,22), +(7,6,10,30,30,32,25,23), +(7,6,11,32,31,33,25,23), +(7,6,12,33,32,34,25,23), +(7,6,13,34,33,36,25,24), +(7,6,14,36,34,37,25,24), +(7,6,15,37,35,38,25,24), +(7,6,16,39,36,40,25,25), +(7,6,17,40,36,41,25,25), +(7,6,18,42,37,43,26,25), +(7,6,19,43,38,44,26,26), +(7,6,20,45,39,45,26,26), +(7,6,21,47,40,47,26,26), +(7,6,22,48,41,48,26,27), +(7,6,23,50,42,50,26,27), +(7,6,24,51,43,51,26,28), +(7,6,25,53,44,52,27,28), +(7,6,26,55,45,54,27,28), +(7,6,27,56,46,55,27,29), +(7,6,28,58,47,57,27,29), +(7,6,29,59,48,58,27,30), +(7,6,30,61,49,60,27,30), +(7,6,31,63,50,62,27,30), +(7,6,32,65,51,63,28,31), +(7,6,33,66,52,65,28,31), +(7,6,34,68,53,66,28,32), +(7,6,35,70,55,68,28,32), +(7,6,36,72,56,69,28,33), +(7,6,37,73,57,71,29,33), +(7,6,38,75,58,73,29,34), +(7,6,39,77,59,74,29,34), +(7,6,40,79,60,76,29,35), +(7,6,41,81,61,78,29,35), +(7,6,42,82,62,79,30,35), +(7,6,43,84,64,81,30,36), +(7,6,44,86,65,83,30,36), +(7,6,45,88,66,85,30,37), +(7,6,46,90,67,86,30,37), +(7,6,47,92,68,88,31,38), +(7,6,48,94,70,90,31,38), +(7,6,49,96,71,92,31,39), +(7,6,50,98,72,93,31,40), +(7,6,51,99,72,93,32,40), +(7,6,52,100,73,95,32,41), +(7,6,53,101,74,96,32,41), +(7,6,54,102,75,97,32,42), +(7,6,55,103,76,98,33,42), +(7,6,56,106,78,101,33,43), +(7,6,57,111,79,103,33,43), +(7,6,58,113,80,105,34,44), +(7,6,59,116,82,107,34,44), +(7,6,60,118,83,109,34,45), +(7,6,61,120,84,111,34,46), +(7,6,62,127,86,119,34,46), +(7,6,63,129,87,122,35,47), +(7,6,64,132,89,125,35,47), +(7,6,65,135,90,127,35,48), +(7,6,66,137,92,130,35,49), +(7,6,67,138,93,130,36,49), +(7,6,68,140,95,131,36,50), +(7,6,69,142,96,131,36,51), +(7,6,70,145,98,132,36,51), +(7,6,71,148,100,135,37,52), +(7,6,72,150,101,137,37,53), +(7,6,73,153,103,140,37,54), +(7,6,74,154,105,142,37,54), +(7,6,75,155,106,145,38,55), +(7,6,76,158,108,151,38,56), +(7,6,77,161,110,157,38,57), +(7,6,78,164,111,162,38,57), +(7,6,79,167,113,165,39,58), +(7,6,80,170,115,168,39,59), (7,8,1,15,23,19,27,22), (7,8,2,15,23,19,28,23), (7,8,3,15,23,20,30,25), @@ -6341,6 +7450,16 @@ INSERT INTO `player_levelstats` VALUES (7,8,68,27,41,49,150,140), (7,8,69,28,42,49,153,143), (7,8,70,28,42,50,155,145), +(7,8,71,28,42,51,168,148), +(7,8,72,28,43,52,168,151), +(7,8,73,28,43,53,171,154), +(7,8,74,29,44,53,174,156), +(7,8,75,29,44,54,177,159), +(7,8,76,29,44,55,180,162), +(7,8,77,30,45,56,183,165), +(7,8,78,30,45,56,186,168), +(7,8,79,30,46,57,190,171), +(7,8,80,31,46,58,193,174), (7,9,1,15,23,20,26,22), (7,9,2,15,23,21,27,23), (7,9,3,16,24,21,28,24), @@ -6411,6 +7530,16 @@ INSERT INTO `player_levelstats` VALUES (7,9,68,45,59,73,133,127), (7,9,69,45,60,74,135,129), (7,9,70,46,61,75,137,131), +(7,9,71,47,62,84,147,142), +(7,9,72,48,62,85,148,144), +(7,9,73,49,63,85,153,147), +(7,9,74,49,64,88,153,150), +(7,9,75,50,65,90,155,152), +(7,9,76,51,66,91,158,155), +(7,9,77,52,67,92,161,158), +(7,9,78,52,68,93,163,161), +(7,9,79,53,69,95,166,164), +(7,9,80,54,70,96,170,166), (8,1,1,24,22,23,16,21), (8,1,2,25,23,24,16,21), (8,1,3,27,24,25,16,22), @@ -6481,6 +7610,16 @@ INSERT INTO `player_levelstats` VALUES (8,1,68,141,95,130,28,51), (8,1,69,144,97,132,29,51), (8,1,70,146,98,134,29,52), +(8,1,71,149,99,136,29,53), +(8,1,72,151,101,139,29,54), +(8,1,73,154,103,141,29,55), +(8,1,74,157,104,144,30,55), +(8,1,75,166,106,151,30,56), +(8,1,76,172,108,157,30,57), +(8,1,77,175,110,161,31,58), +(8,1,78,179,111,163,31,58), +(8,1,79,182,113,164,31,59), +(8,1,80,185,115,169,32,60), (8,3,1,21,25,22,16,22), (8,3,2,21,26,23,17,23), (8,3,3,22,28,24,17,23), @@ -6551,6 +7690,16 @@ INSERT INTO `player_levelstats` VALUES (8,3,68,63,148,106,71,82), (8,3,69,64,151,107,72,83), (8,3,70,65,153,109,73,84), +(8,3,71,66,156,111,74,85), +(8,3,72,67,159,113,75,86), +(8,3,73,68,162,115,76,88), +(8,3,74,69,165,117,78,89), +(8,3,75,70,174,119,82,91), +(8,3,76,71,177,121,83,92), +(8,3,77,72,180,123,85,94), +(8,3,78,73,184,125,86,95), +(8,3,79,74,187,127,87,97), +(8,3,80,75,190,129,89,98), (8,4,1,22,25,22,16,21), (8,4,2,23,26,23,16,21), (8,4,3,24,28,23,16,22), @@ -6621,6 +7770,16 @@ INSERT INTO `player_levelstats` VALUES (8,4,68,93,155,87,34,58), (8,4,69,95,157,89,35,58), (8,4,70,96,160,90,35,59), +(8,4,71,98,163,94,35,60), +(8,4,72,100,166,96,36,60), +(8,4,73,101,169,96,36,61), +(8,4,74,103,172,97,37,62), +(8,4,75,105,175,98,37,63), +(8,4,76,106,178,99,37,64), +(8,4,77,108,181,105,38,65), +(8,4,78,110,185,107,38,66), +(8,4,79,112,188,109,39,67), +(8,4,80,114,191,110,39,68), (8,5,1,21,22,21,18,24), (8,5,2,21,22,21,19,25), (8,5,3,21,22,22,21,27), @@ -6691,6 +7850,96 @@ INSERT INTO `player_levelstats` VALUES (8,5,68,39,46,58,136,147), (8,5,69,40,46,58,139,150), (8,5,70,40,47,59,141,152), +(8,5,71,40,48,60,144,155), +(8,5,72,41,48,60,147,158), +(8,5,73,41,49,61,150,161), +(8,5,74,42,49,62,152,164), +(8,5,75,42,50,63,155,167), +(8,5,76,42,51,64,158,170), +(8,5,77,43,51,65,161,173), +(8,5,78,43,52,66,164,176), +(8,5,79,44,52,67,167,179), +(8,5,80,44,53,68,170,182), +(8,6,1,24,22,23,16,21), +(8,6,2,25,23,24,16,21), +(8,6,3,27,24,25,16,22), +(8,6,4,28,24,26,16,22), +(8,6,5,29,25,28,16,22), +(8,6,6,31,26,29,16,22), +(8,6,7,32,27,30,17,23), +(8,6,8,33,28,31,17,23), +(8,6,9,35,28,33,17,23), +(8,6,10,36,29,34,17,24), +(8,6,11,37,30,35,17,24), +(8,6,12,39,31,36,17,24), +(8,6,13,40,32,38,17,25), +(8,6,14,42,33,39,17,25), +(8,6,15,43,34,40,18,25), +(8,6,16,45,35,42,18,26), +(8,6,17,46,35,43,18,26), +(8,6,18,48,36,44,18,26), +(8,6,19,49,37,46,18,27), +(8,6,20,51,38,47,18,27), +(8,6,21,52,39,49,18,27), +(8,6,22,54,40,50,18,28), +(8,6,23,55,41,51,19,28), +(8,6,24,57,42,53,19,29), +(8,6,25,59,43,54,19,29), +(8,6,26,60,44,56,19,29), +(8,6,27,62,45,57,19,30), +(8,6,28,63,46,59,19,30), +(8,6,29,65,47,60,20,31), +(8,6,30,67,48,62,20,31), +(8,6,31,69,49,63,20,31), +(8,6,32,70,50,65,20,32), +(8,6,33,72,51,67,20,32), +(8,6,34,74,53,68,20,33), +(8,6,35,75,54,70,21,33), +(8,6,36,77,55,71,21,34), +(8,6,37,79,56,73,21,34), +(8,6,38,81,57,75,21,35), +(8,6,39,83,58,76,21,35), +(8,6,40,84,59,78,22,35), +(8,6,41,86,60,80,22,36), +(8,6,42,88,62,81,22,36), +(8,6,43,90,63,83,22,37), +(8,6,44,92,64,85,22,37), +(8,6,45,94,65,86,23,38), +(8,6,46,96,66,88,23,38), +(8,6,47,98,67,90,23,39), +(8,6,48,100,69,92,23,39), +(8,6,49,102,70,93,24,40), +(8,6,50,103,71,95,24,40), +(8,6,51,105,72,96,24,41), +(8,6,52,106,74,97,24,42), +(8,6,53,107,73,98,25,42), +(8,6,54,108,74,99,25,43), +(8,6,55,109,75,100,25,43), +(8,6,56,112,77,103,25,44), +(8,6,57,114,78,105,25,44), +(8,6,58,118,79,107,26,45), +(8,6,59,119,81,109,26,45), +(8,6,60,121,82,111,26,46), +(8,6,61,123,83,113,26,47), +(8,6,62,126,85,115,26,47), +(8,6,63,128,86,118,27,48), +(8,6,64,131,88,120,27,48), +(8,6,65,138,89,122,27,49), +(8,6,66,140,91,125,27,50), +(8,6,67,143,92,127,28,50), +(8,6,68,145,94,129,28,51), +(8,6,69,148,95,132,28,52), +(8,6,70,151,97,134,28,52), +(8,6,71,154,99,137,29,53), +(8,6,72,156,100,139,29,54), +(8,6,73,159,102,142,29,55), +(8,6,74,162,104,144,29,55), +(8,6,75,165,105,147,30,56), +(8,6,76,168,107,150,30,57), +(8,6,77,169,109,153,30,58), +(8,6,78,170,110,155,30,58), +(8,6,79,178,112,158,31,59), +(8,6,80,181,114,161,31,60), (8,7,1,22,22,22,17,23), (8,7,2,23,22,23,18,24), (8,7,3,24,23,24,19,25), @@ -6761,6 +8010,16 @@ INSERT INTO `player_levelstats` VALUES (8,7,68,100,64,112,101,117), (8,7,69,101,65,113,102,119), (8,7,70,103,66,115,104,121), +(8,7,71,104,67,117,116,123), +(8,7,72,106,68,119,118,126), +(8,7,73,108,69,121,121,128), +(8,7,74,110,70,124,123,130), +(8,7,75,112,71,126,125,132), +(8,7,76,114,72,128,127,135), +(8,7,77,115,73,130,129,137), +(8,7,78,117,74,132,132,139), +(8,7,79,119,75,135,134,142), +(8,7,80,121,76,137,136,144), (8,8,1,21,22,21,19,23), (8,8,2,21,22,21,20,24), (8,8,3,21,22,22,22,26), @@ -6831,6 +8090,16 @@ INSERT INTO `player_levelstats` VALUES (8,8,68,33,40,51,142,141), (8,8,69,34,41,51,145,144), (8,8,70,34,41,52,147,146), +(8,8,71,34,41,53,150,149), +(8,8,72,34,42,54,153,152), +(8,8,73,34,42,55,156,155), +(8,8,74,35,43,55,159,157), +(8,8,75,35,43,56,162,160), +(8,8,76,35,43,57,168,163), +(8,8,77,36,44,58,168,166), +(8,8,78,36,44,58,171,169), +(8,8,79,36,45,59,177,172), +(8,8,80,37,45,60,177,175), (10,2,1,19,22,21,24,20), (10,2,2,20,23,22,25,21), (10,2,3,21,23,23,25,21), @@ -6901,6 +8170,16 @@ INSERT INTO `player_levelstats` VALUES (10,2,68,119,77,115,85,85), (10,2,69,121,78,117,86,87), (10,2,70,123,79,119,87,88), +(10,2,71,125,80,120,88,89), +(10,2,72,128,81,123,90,91), +(10,2,73,130,82,125,91,93), +(10,2,74,133,84,127,93,94), +(10,2,75,135,85,129,94,96), +(10,2,76,137,86,132,96,97), +(10,2,77,140,88,134,97,99), +(10,2,78,143,89,136,99,101), +(10,2,79,145,90,139,100,102), +(10,2,80,148,92,141,102,104), (10,3,1,17,25,20,24,20), (10,3,2,17,26,21,25,21), (10,3,3,18,28,22,25,21), @@ -6971,6 +8250,16 @@ INSERT INTO `player_levelstats` VALUES (10,3,68,59,148,104,79,80), (10,3,69,60,151,105,80,81), (10,3,70,61,153,107,81,82), +(10,3,71,62,156,108,82,83), +(10,3,72,63,159,110,83,84), +(10,3,73,64,162,112,84,86), +(10,3,74,65,165,114,86,87), +(10,3,75,66,168,116,87,89), +(10,3,76,67,171,118,89,90), +(10,3,77,68,174,120,90,92), +(10,3,78,69,177,122,91,93), +(10,3,79,70,180,124,92,95), +(10,3,80,71,183,126,94,96), (10,4,1,18,25,20,24,19), (10,4,2,19,26,21,24,19), (10,4,3,20,28,21,24,20), @@ -7041,6 +8330,16 @@ INSERT INTO `player_levelstats` VALUES (10,4,68,89,155,85,42,56), (10,4,69,91,157,87,43,56), (10,4,70,92,160,88,43,57), +(10,4,71,94,163,88,43,58), +(10,4,72,96,166,90,44,58), +(10,4,73,97,169,92,44,59), +(10,4,74,99,172,93,45,60), +(10,4,75,101,175,95,45,61), +(10,4,76,102,178,96,45,62), +(10,4,77,104,181,101,46,63), +(10,4,78,106,185,104,46,64), +(10,4,79,108,188,105,47,65), +(10,4,80,110,191,107,47,66), (10,5,1,17,22,19,26,22), (10,5,2,17,22,19,27,23), (10,5,3,17,22,20,29,25), @@ -7111,6 +8410,96 @@ INSERT INTO `player_levelstats` VALUES (10,5,68,35,46,56,144,145), (10,5,69,36,46,56,147,148), (10,5,70,36,47,57,149,150), +(10,5,71,36,48,57,152,153), +(10,5,72,37,48,57,155,156), +(10,5,73,37,49,58,158,159), +(10,5,74,38,49,59,160,163), +(10,5,75,38,50,60,163,165), +(10,5,76,38,51,61,166,170), +(10,5,77,39,51,62,168,175), +(10,5,78,39,52,63,172,174), +(10,5,79,40,52,64,175,177), +(10,5,80,40,53,65,178,180), +(10,6,1,18,23,21,24,20), +(10,6,2,19,24,22,24,20), +(10,6,3,21,25,23,24,21), +(10,6,4,22,25,25,24,21), +(10,6,5,23,26,26,24,21), +(10,6,6,25,27,27,24,21), +(10,6,7,26,28,28,24,22), +(10,6,8,27,29,29,25,22), +(10,6,9,29,29,31,25,22), +(10,6,10,30,30,32,25,23), +(10,6,11,32,31,33,25,23), +(10,6,12,33,32,34,25,23), +(10,6,13,34,33,36,25,24), +(10,6,14,36,34,37,25,24), +(10,6,15,37,35,38,25,24), +(10,6,16,39,36,40,25,25), +(10,6,17,40,36,41,25,25), +(10,6,18,42,37,43,26,25), +(10,6,19,43,38,44,26,26), +(10,6,20,45,39,45,26,26), +(10,6,21,47,40,47,26,26), +(10,6,22,48,41,48,26,27), +(10,6,23,50,42,50,26,27), +(10,6,24,51,43,51,26,28), +(10,6,25,53,44,52,27,28), +(10,6,26,55,45,54,27,28), +(10,6,27,56,46,55,27,29), +(10,6,28,58,47,57,27,29), +(10,6,29,59,48,58,27,30), +(10,6,30,61,49,60,27,30), +(10,6,31,63,50,62,27,30), +(10,6,32,65,51,63,28,31), +(10,6,33,66,52,65,28,31), +(10,6,34,68,53,66,28,32), +(10,6,35,70,55,68,28,32), +(10,6,36,72,56,69,28,33), +(10,6,37,73,57,71,29,33), +(10,6,38,75,58,73,29,34), +(10,6,39,77,59,74,29,34), +(10,6,40,79,60,76,29,35), +(10,6,41,81,61,78,29,35), +(10,6,42,82,62,79,30,35), +(10,6,43,84,64,81,30,36), +(10,6,44,86,65,83,30,36), +(10,6,45,88,66,85,30,37), +(10,6,46,90,67,86,30,37), +(10,6,47,92,68,88,31,38), +(10,6,48,94,69,90,31,38), +(10,6,49,96,69,92,31,39), +(10,6,50,98,70,93,31,40), +(10,6,51,100,71,95,32,40), +(10,6,52,102,72,96,32,41), +(10,6,53,103,73,97,32,41), +(10,6,54,104,74,98,32,41), +(10,6,55,105,75,97,33,41), +(10,6,56,108,77,100,33,42), +(10,6,57,113,78,102,33,42), +(10,6,58,115,79,104,34,43), +(10,6,59,117,81,106,34,43), +(10,6,60,118,82,108,34,44), +(10,6,61,119,83,110,34,45), +(10,6,62,121,85,112,34,45), +(10,6,63,124,86,115,35,46), +(10,6,64,127,88,117,35,46), +(10,6,65,133,89,119,35,47), +(10,6,66,135,91,122,35,48), +(10,6,67,139,92,124,36,48), +(10,6,68,141,94,126,36,49), +(10,6,69,142,95,129,36,50), +(10,6,70,145,97,131,36,50), +(10,6,71,150,99,134,37,51), +(10,6,72,152,100,136,37,52), +(10,6,73,155,102,139,37,53), +(10,6,74,158,104,141,37,53), +(10,6,75,159,105,144,38,54), +(10,6,76,160,107,147,38,55), +(10,6,77,163,109,149,38,56), +(10,6,78,166,110,152,38,56), +(10,6,79,169,112,155,39,57), +(10,6,80,172,114,158,39,58), (10,8,1,17,22,19,27,21), (10,8,2,17,22,19,28,22), (10,8,3,17,22,20,30,24), @@ -7181,6 +8570,16 @@ INSERT INTO `player_levelstats` VALUES (10,8,68,29,40,49,150,139), (10,8,69,30,41,49,153,142), (10,8,70,30,41,50,155,144), +(10,8,71,30,41,50,158,147), +(10,8,72,30,42,51,161,150), +(10,8,73,30,42,52,164,153), +(10,8,74,31,43,52,167,155), +(10,8,75,31,43,53,170,158), +(10,8,76,31,43,54,173,161), +(10,8,77,32,44,55,176,164), +(10,8,78,32,44,55,179,167), +(10,8,79,32,45,56,182,170), +(10,8,80,33,45,57,185,173), (10,9,1,17,22,20,26,21), (10,9,2,17,22,21,27,22), (10,9,3,18,23,21,28,23), @@ -7251,6 +8650,16 @@ INSERT INTO `player_levelstats` VALUES (10,9,68,47,58,73,133,126), (10,9,69,47,59,74,135,128), (10,9,70,48,60,75,137,130), +(10,9,71,49,61,83,139,141), +(10,9,72,50,61,84,142,143), +(10,9,73,51,62,84,144,146), +(10,9,74,51,63,86,147,149), +(10,9,75,52,64,89,149,151), +(10,9,76,53,65,90,155,154), +(10,9,77,54,66,91,155,157), +(10,9,78,54,67,93,157,160), +(10,9,79,55,68,94,160,163), +(10,9,80,56,69,95,163,165), (11,1,1,24,17,21,21,22), (11,1,2,25,18,22,21,22), (11,1,3,27,19,23,21,23), @@ -7321,6 +8730,16 @@ INSERT INTO `player_levelstats` VALUES (11,1,68,141,90,128,33,52), (11,1,69,144,92,130,34,52), (11,1,70,146,93,132,34,53), +(11,1,71,149,94,134,34,54), +(11,1,72,151,96,137,34,55), +(11,1,73,154,98,139,34,56), +(11,1,74,157,99,142,35,56), +(11,1,75,166,101,149,35,57), +(11,1,76,172,103,155,35,58), +(11,1,77,175,105,159,36,59), +(11,1,78,179,106,161,36,59), +(11,1,79,182,108,164,36,60), +(11,1,80,185,110,167,37,61), (11,2,1,23,17,21,21,23), (11,2,2,24,18,22,22,24), (11,2,3,25,18,23,22,24), @@ -7391,6 +8810,16 @@ INSERT INTO `player_levelstats` VALUES (11,2,68,123,72,115,82,88), (11,2,69,125,73,117,83,90), (11,2,70,127,74,119,84,91), +(11,2,71,130,75,121,87,92), +(11,2,72,132,76,124,90,94), +(11,2,73,134,77,126,93,96), +(11,2,74,137,79,128,97,97), +(11,2,75,139,80,130,101,99), +(11,2,76,142,81,133,106,100), +(11,2,77,144,83,135,108,102), +(11,2,78,147,84,137,110,104), +(11,2,79,149,85,140,111,105), +(11,2,80,152,87,142,113,107), (11,3,1,21,20,20,21,23), (11,3,2,21,21,21,22,24), (11,3,3,22,23,22,22,24), @@ -7461,6 +8890,16 @@ INSERT INTO `player_levelstats` VALUES (11,3,68,63,143,104,76,83), (11,3,69,64,146,105,77,84), (11,3,70,65,148,107,78,85), +(11,3,71,66,151,109,79,86), +(11,3,72,67,154,111,80,87), +(11,3,73,68,157,113,81,89), +(11,3,74,69,160,115,83,90), +(11,3,75,70,163,117,84,92), +(11,3,76,71,166,119,85,93), +(11,3,77,72,169,121,87,95), +(11,3,78,73,172,123,88,96), +(11,3,79,74,175,125,89,98), +(11,3,80,75,178,127,91,99), (11,5,1,21,17,19,23,25), (11,5,2,21,17,19,24,26), (11,5,3,21,17,20,26,28), @@ -7531,6 +8970,96 @@ INSERT INTO `player_levelstats` VALUES (11,5,68,39,41,56,141,148), (11,5,69,40,41,56,144,151), (11,5,70,40,42,57,146,153), +(11,5,71,40,43,58,149,156), +(11,5,72,41,43,58,155,159), +(11,5,73,41,44,59,157,160), +(11,5,74,42,44,61,160,163), +(11,5,75,42,45,62,164,166), +(11,5,76,42,46,62,167,169), +(11,5,77,43,46,63,168,172), +(11,5,78,43,47,64,169,177), +(11,5,79,44,47,65,172,180), +(11,5,80,44,48,66,175,183), +(11,6,1,24,17,21,21,22), +(11,6,2,25,18,22,21,22), +(11,6,3,27,19,23,21,23), +(11,6,4,28,19,25,21,23), +(11,6,5,29,20,26,21,23), +(11,6,6,31,21,27,21,23), +(11,6,7,32,22,28,21,24), +(11,6,8,33,23,29,22,24), +(11,6,9,35,24,31,22,24), +(11,6,10,36,24,32,22,25), +(11,6,11,37,25,33,22,25), +(11,6,12,39,26,34,22,25), +(11,6,13,40,27,36,22,26), +(11,6,14,42,28,37,22,26), +(11,6,15,43,29,38,22,26), +(11,6,16,45,30,40,22,27), +(11,6,17,46,31,41,23,27), +(11,6,18,48,32,43,23,27), +(11,6,19,49,33,44,23,28), +(11,6,20,51,34,45,23,28), +(11,6,21,52,34,47,23,28), +(11,6,22,54,35,48,23,29), +(11,6,23,55,36,50,23,29), +(11,6,24,57,37,51,24,30), +(11,6,25,59,38,52,24,30), +(11,6,26,60,39,54,24,30), +(11,6,27,62,40,55,24,31), +(11,6,28,63,41,57,24,31), +(11,6,29,65,43,58,24,32), +(11,6,30,67,44,60,24,32), +(11,6,31,69,45,62,25,32), +(11,6,32,70,46,63,25,33), +(11,6,33,72,47,65,25,33), +(11,6,34,74,48,66,25,34), +(11,6,35,75,49,68,25,34), +(11,6,36,77,50,69,26,35), +(11,6,37,79,51,71,26,35), +(11,6,38,81,52,73,26,35), +(11,6,39,83,53,74,26,36), +(11,6,40,84,55,76,26,36), +(11,6,41,86,56,78,27,37), +(11,6,42,88,57,79,27,37), +(11,6,43,90,58,81,27,38), +(11,6,44,92,59,83,27,38), +(11,6,45,94,60,85,27,39), +(11,6,46,96,62,86,28,39), +(11,6,47,98,63,88,28,40), +(11,6,48,100,64,90,28,40), +(11,6,49,102,65,92,28,41), +(11,6,50,103,65,93,29,41), +(11,6,51,105,66,94,29,42), +(11,6,52,106,67,95,29,42), +(11,6,53,107,68,96,29,43), +(11,6,54,108,69,97,30,44), +(11,6,55,109,70,98,30,44), +(11,6,56,112,72,101,30,45), +(11,6,57,114,73,103,30,45), +(11,6,58,117,74,105,31,46), +(11,6,59,119,76,107,31,46), +(11,6,60,121,77,109,31,47), +(11,6,61,123,78,111,31,48), +(11,6,62,126,80,113,31,48), +(11,6,63,128,81,116,32,49), +(11,6,64,131,83,118,32,49), +(11,6,65,136,84,120,32,50), +(11,6,66,140,86,123,32,51), +(11,6,67,141,87,125,33,51), +(11,6,68,141,89,127,33,52), +(11,6,69,144,90,130,33,53), +(11,6,70,147,92,132,33,53), +(11,6,71,150,94,135,34,54), +(11,6,72,152,95,137,34,55), +(11,6,73,155,97,140,34,56), +(11,6,74,162,99,142,34,56), +(11,6,75,165,100,145,35,57), +(11,6,76,167,102,146,35,58), +(11,6,77,169,104,150,35,59), +(11,6,78,170,105,152,35,59), +(11,6,79,173,107,156,36,60), +(11,6,80,176,109,159,36,61), (11,7,1,22,17,20,22,24), (11,7,2,23,17,21,23,25), (11,7,3,24,18,22,24,26), @@ -7601,6 +9130,16 @@ INSERT INTO `player_levelstats` VALUES (11,7,68,100,59,110,106,118), (11,7,69,101,60,111,107,120), (11,7,70,103,61,113,109,122), +(11,7,71,104,62,115,122,124), +(11,7,72,106,63,117,124,127), +(11,7,73,108,64,119,126,129), +(11,7,74,110,65,122,128,131), +(11,7,75,112,66,124,130,133), +(11,7,76,114,67,126,133,136), +(11,7,77,115,68,128,135,138), +(11,7,78,117,69,130,137,140), +(11,7,79,119,70,133,139,143), +(11,7,80,121,71,135,141,145), (11,8,1,21,17,19,24,24), (11,8,2,21,17,19,25,25), (11,8,3,21,17,20,27,27), @@ -7670,7 +9209,17 @@ INSERT INTO `player_levelstats` VALUES (11,8,67,33,35,48,145,140), (11,8,68,33,35,49,147,142), (11,8,69,34,36,49,150,145), -(11,8,70,34,36,50,152,147); +(11,8,70,34,36,50,152,147), +(11,8,71,34,36,51,155,150), +(11,8,72,34,37,52,161,153), +(11,8,73,34,37,53,161,156), +(11,8,74,35,38,53,164,158), +(11,8,75,35,38,54,167,161), +(11,8,76,35,38,55,170,164), +(11,8,77,36,39,56,173,167), +(11,8,78,36,39,56,176,170), +(11,8,79,36,40,57,179,173), +(11,8,80,37,40,58,182,176); /*!40000 ALTER TABLE `player_levelstats` ENABLE KEYS */; UNLOCK TABLES; @@ -7701,11 +9250,13 @@ INSERT INTO `playercreateinfo` VALUES (1,2,0,12,-8949,-132,84), (1,4,0,12,-8949,-132,84), (1,5,0,12,-8949,-132,84), +(1,6,609,4298,2355.84,-5664.77,426.028), (1,8,0,12,-8949,-132,84), (1,9,0,12,-8949,-132,84), (2,1,1,14,-618,-4251,39), (2,3,1,14,-618,-4251,39), (2,4,1,14,-618,-4251,39), +(2,6,609,4298,2358.44,-5666.9,426.023), (2,7,1,14,-618,-4251,39), (2,9,1,14,-618,-4251,39), (3,1,0,1,-6240,331,383), @@ -7713,40 +9264,48 @@ INSERT INTO `playercreateinfo` VALUES (3,3,0,1,-6240,331,383), (3,4,0,1,-6240,331,383), (3,5,0,1,-6240,331,383), +(3,6,609,4298,2358.44,-5666.9,426.023), (4,1,1,141,10311,832,1327), (4,3,1,141,10311,832,1327), (4,4,1,141,10311,832,1327), (4,5,1,141,10311,832,1327), +(4,6,609,4298,2356.21,-5662.21,426.026), (4,11,1,141,10311,832,1327), (5,1,0,85,1676,1677,122), (5,4,0,85,1676,1677,122), (5,5,0,85,1676,1677,122), (5,8,0,85,1676,1677,122), (5,9,0,85,1676,1677,122), +(5,6,609,4298,2356.21,-5662.21,426.026), (6,1,1,215,-2917,-257,53), (6,3,1,215,-2917,-257,53), +(6,6,609,4298,2358.17,-5663.21,426.027), (6,7,1,215,-2917,-257,53), (6,11,1,215,-2917,-257,53), (7,1,0,1,-6240,331,383), (7,4,0,1,-6340,331,383), +(7,6,609,4298,2355.05,-5661.7, 426.026), (7,8,0,1,-6340,331,383), (7,9,0,1,-6340,331,383), (8,1,1,14,-618,-4251,39), (8,3,1,14,-618,-4251,39), (8,4,1,14,-618,-4251,39), (8,5,1,14,-618,-4251,39), +(8,6,609,4298,2355.05,-5661.7, 426.026), (8,7,1,14,-618,-4251,39), (8,8,1,14,-618,-4251,39), (10,2,530,3431,10349.6,-6357.29,33.4026), (10,3,530,3431,10349.6,-6357.29,33.4026), (10,4,530,3431,10349.6,-6357.29,33.4026), (10,5,530,3431,10349.6,-6357.29,33.4026), +(10,6,609,4298,2355.84,-5664.77,426.028), (10,8,530,3431,10349.6,-6357.29,33.4026), (10,9,530,3431,10349.6,-6357.29,33.4026), (11,1,530,3526,-3961.64,-13931.2,100.615), (11,2,530,3526,-3961.64,-13931.2,100.615), (11,3,530,3526,-3961.64,-13931.2,100.615), (11,5,530,3526,-3961.64,-13931.2,100.615), +(11,6,609,4298,2358.17,-5663.21,426.027), (11,7,530,3526,-3961.64,-13931.2,100.615), (11,8,530,3526,-3961.64,-13931.2,100.615); /*!40000 ALTER TABLE `playercreateinfo` ENABLE KEYS */; @@ -7792,6 +9351,13 @@ INSERT INTO `playercreateinfo_action` VALUES (1,5,0,6603,0,0), (1,5,10,159,128,0), (1,5,11,2070,128,0), +(1,6,0,6603,0,0), +(1,6,1,49576,0,0), +(1,6,2,45477,0,0), +(1,6,3,45462,0,0), +(1,6,4,45902,0,0), +(1,6,5,47541,0,0), +(1,6,11,59752,0,0), (1,8,1,133,0,0), (1,8,2,168,0,0), (1,8,0,6603,0,0), @@ -7815,6 +9381,13 @@ INSERT INTO `playercreateinfo_action` VALUES (2,4,2,2098,0,0), (2,4,0,6603,0,0), (2,4,11,117,128,0), +(2,6,0,6603,0,0), +(2,6,1,49576,0,0), +(2,6,2,45477,0,0), +(2,6,3,45462,0,0), +(2,6,4,45902,0,0), +(2,6,5,47541,0,0), +(2,6,10,20572,0,0), (2,7,2,331,0,0), (2,7,1,403,0,0), (2,7,0,6603,0,0), @@ -7848,6 +9421,13 @@ INSERT INTO `playercreateinfo_action` VALUES (3,5,0,6603,0,0), (3,5,10,159,128,0), (3,5,11,4540,128,0), +(3,6,0,6603,0,0), +(3,6,1,49576,0,0), +(3,6,2,45477,0,0), +(3,6,3,45462,0,0), +(3,6,4,45902,0,0), +(3,6,5,47541,0,0), +(3,6,10,2481,0,0), (4,1,1,78,0,0), (4,1,0,6603,0,0), (4,1,11,117,128,0), @@ -7866,6 +9446,14 @@ INSERT INTO `playercreateinfo_action` VALUES (4,5,0,6603,0,0), (4,5,10,159,128,0), (4,5,11,2070,128,0), +(4,6,0,6603,0,0), +(4,6,1,49576,0,0), +(4,6,2,45477,0,0), +(4,6,3,45462,0,0), +(4,6,4,45902,0,0), +(4,6,5,47541,0,0), +(4,6,10,58984,0,0), +(4,6,83,58984,0,0), (4,11,1,5176,0,0), (4,11,2,5185,0,0), (4,11,0,6603,0,0), @@ -7884,6 +9472,13 @@ INSERT INTO `playercreateinfo_action` VALUES (5,5,1,585,0,0), (5,5,11,4604,128,0), (5,5,0,6603,0,0), +(5,6,0,6603,0,0), +(5,6,1,49576,0,0), +(5,6,2,45477,0,0), +(5,6,3,45462,0,0), +(5,6,4,45902,0,0), +(5,6,5,47541,0,0), +(5,6,10,20577,0,0), (5,8,11,4604,128,0), (5,8,10,159,128,0), (5,8,2,168,0,0), @@ -7904,6 +9499,14 @@ INSERT INTO `playercreateinfo_action` VALUES (6,3,3,20549,0,0), (6,3,11,117,128,0), (6,3,0,6603,0,0), +(6,6,0,6603,0,0), +(6,6,1,49576,0,0), +(6,6,2,45477,0,0), +(6,6,3,45462,0,0), +(6,6,4,45902,0,0), +(6,6,5,47541,0,0), +(6,6,10,20549,0,0), +(6,6,75,20549,0,0), (6,7,1,403,0,0), (6,7,10,159,128,0), (6,7,2,331,0,0), @@ -7924,6 +9527,18 @@ INSERT INTO `playercreateinfo_action` VALUES (7,4,1,1752,0,0), (7,4,2,2098,0,0), (7,4,0,6603,0,0), +(7,6,0,6603,0,0), +(7,6,1,49576,0,0), +(7,6,2,45477,0,0), +(7,6,3,45462,0,0), +(7,6,4,45902,0,0), +(7,6,5,47541,0,0), +(7,6,10,20589,0,0), +(7,6,72,6603,0,0), +(7,6,83,117,128,0), +(7,6,84,6603,0,0), +(7,6,96,6603,0,0), +(7,6,108,6603,0,0), (7,8,11,4536,128,0), (7,8,1,133,0,0), (7,8,2,168,0,0), @@ -7953,6 +9568,13 @@ INSERT INTO `playercreateinfo_action` VALUES (8,5,2,2050,0,0), (8,5,11,4540,128,0), (8,5,0,6603,0,0), +(8,6,0,6603,0,0), +(8,6,1,49576,0,0), +(8,6,2,45477,0,0), +(8,6,3,45462,0,0), +(8,6,4,45902,0,0), +(8,6,5,47541,0,0), +(8,6,10,50621,0,0), (8,7,1,403,0,0), (8,7,10,159,128,0), (8,7,2,331,0,0), @@ -7991,6 +9613,13 @@ INSERT INTO `playercreateinfo_action` VALUES (10,5,4,28730,0,0), (10,5,10,159,128,0), (10,5,11,20857,128,0), +(10,6,0,6603,0,0), +(10,6,1,49576,0,0), +(10,6,2,45477,0,0), +(10,6,3,45462,0,0), +(10,6,4,45902,0,0), +(10,6,5,47541,0,0), +(10,6,6,50613,0,0), (10,8,0,6603,0,0), (10,8,1,133,0,0), (10,8,2,168,0,0), @@ -8038,6 +9667,12 @@ INSERT INTO `playercreateinfo_action` VALUES (11,5,10,159,128,0), (11,5,11,4540,128,0), (11,5,83,4540,128,0), +(11,6,0,6603,0,0), +(11,6,1,49576,0,0), +(11,6,2,45477,0,0), +(11,6,3,45462,0,0), +(11,6,4,45902,0,0), +(11,6,5,47541,0,0), (11,7,0,6603,0,0), (11,7,1,403,0,0), (11,7,2,331,0,0), @@ -8253,6 +9888,75 @@ INSERT INTO `playercreateinfo_spell` VALUES (1,5,21652,'Closing',1), (1,5,22027,'Remove Insignia',1), (1,5,22810,'Opening - No Text',1), +(1,6,81,'Dodge',1), +(1,6,196,'One-Handed Axes',1), +(1,6,197,'Two-Handed Axes',1), +(1,6,200,'Polearms',1), +(1,6,201,'One-Handed Swords',1), +(1,6,202,'Two-Handed Swords',1), +(1,6,203,'Unarmed',1), +(1,6,204,'Defense',1), +(1,6,522,'SPELLDEFENSE (DND)',1), +(1,6,668,'Language Common',1), +(1,6,674,'Dual Wield',1), +(1,6,750,'Plate Mail',1), +(1,6,1843,'Disarm',1), +(1,6,2382,'Generic',1), +(1,6,2479,'Honorless Target',1), +(1,6,3050,'Detect',1), +(1,6,3127,'Parry',1), +(1,6,3275,'Linen Bandage',1), +(1,6,3276,'Heavy Linen Bandage',1), +(1,6,3277,'Wool Bandage',1), +(1,6,3278,'Heavy Wool Bandage',1), +(1,6,3365,'Opening',1), +(1,6,6233,'Closing',1), +(1,6,6246,'Closing',1), +(1,6,6247,'Opening',1), +(1,6,6477,'Opening',1), +(1,6,6478,'Opening',1), +(1,6,6603,'Attack',1), +(1,6,7266,'Duel',1), +(1,6,7267,'Grovel',1), +(1,6,7355,'Stuck',1), +(1,6,7928,'Silk Bandage',1), +(1,6,7929,'Heavy Silk Bandage',1), +(1,6,7934,'Anti-Venom',1), +(1,6,8386,'Attacking',1), +(1,6,8737,'Mail',1), +(1,6,9077,'Leather',1), +(1,6,9078,'Cloth',1), +(1,6,9125,'Generic',1), +(1,6,10840,'Mageweave Bandage',1), +(1,6,10841,'Heavy Mageweave Bandage',1), +(1,6,10846,'First Aid',1), +(1,6,18629,'Runecloth Bandage',1), +(1,6,18630,'Heavy Runecloth Bandage',1), +(1,6,20597,'Sword Specialization',1), +(1,6,20598,'The Human Spirit',1), +(1,6,20599,'Diplomacy',1), +(1,6,20864,'Mace Specialization',1), +(1,6,21651,'Opening',1), +(1,6,21652,'Closing',1), +(1,6,22027,'Remove Insignia',1), +(1,6,22810,'Opening - No Text',1), +(1,6,33391,'Journeyman Riding',1), +(1,6,45462,'Plague Strike',1), +(1,6,45477,'Icy Touch',1), +(1,6,45902,'Blood Strike',1), +(1,6,45903,'Offensive State (DND)',1), +(1,6,45927,'Summon Friend',1), +(1,6,47541,'Death Coil',1), +(1,6,48266,'Blood Presence',1), +(1,6,49410,'Forceful Deflection',1), +(1,6,49576,'Death Grip',1), +(1,6,52665,'Sigil',1), +(1,6,58985,'Perception',1), +(1,6,59752,'Every Man for Himself',1), +(1,6,59879,'Blood Plague',1), +(1,6,59921,'Frost Fever',1), +(1,6,61437,'Opening',1), +(1,6,61455,'Runic Focus',1), (1,8,81,'Dodge',1), (1,8,133,'Fireball',1), (1,8,168,'Frost Armor',1), @@ -8440,6 +10144,73 @@ INSERT INTO `playercreateinfo_spell` VALUES (2,4,21652,'Closing',1), (2,4,22027,'Remove Insignia',1), (2,4,22810,'Opening - No Text',1), +(2,6,81,'Dodge',1), +(2,6,196,'One-Handed Axes',1), +(2,6,197,'Two-Handed Axes',1), +(2,6,200,'Polearms',1), +(2,6,201,'One-Handed Swords',1), +(2,6,202,'Two-Handed Swords',1), +(2,6,203,'Unarmed',1), +(2,6,204,'Defense',1), +(2,6,522,'SPELLDEFENSE (DND)',1), +(2,6,669,'Language Orcish',1), +(2,6,674,'Dual Wield',1), +(2,6,750,'Plate Mail',1), +(2,6,1843,'Disarm',1), +(2,6,2382,'Generic',1), +(2,6,2479,'Honorless Target',1), +(2,6,3050,'Detect',1), +(2,6,3127,'Parry',1), +(2,6,3275,'Linen Bandage',1), +(2,6,3276,'Heavy Linen Bandage',1), +(2,6,3277,'Wool Bandage',1), +(2,6,3278,'Heavy Wool Bandage',1), +(2,6,3365,'Opening',1), +(2,6,6233,'Closing',1), +(2,6,6246,'Closing',1), +(2,6,6247,'Opening',1), +(2,6,6477,'Opening',1), +(2,6,6478,'Opening',1), +(2,6,6603,'Attack',1), +(2,6,7266,'Duel',1), +(2,6,7267,'Grovel',1), +(2,6,7355,'Stuck',1), +(2,6,7928,'Silk Bandage',1), +(2,6,7929,'Heavy Silk Bandage',1), +(2,6,7934,'Anti-Venom',1), +(2,6,8386,'Attacking',1), +(2,6,8737,'Mail',1), +(2,6,9077,'Leather',1), +(2,6,9078,'Cloth',1), +(2,6,9125,'Generic',1), +(2,6,10840,'Mageweave Bandage',1), +(2,6,10841,'Heavy Mageweave Bandage',1), +(2,6,10846,'First Aid',1), +(2,6,18629,'Runecloth Bandage',1), +(2,6,18630,'Heavy Runecloth Bandage',1), +(2,6,20572,'Blood Fury',1), +(2,6,20573,'Hardiness',1), +(2,6,20574,'Axe Specialization',1), +(2,6,21651,'Opening',1), +(2,6,21652,'Closing',1), +(2,6,22027,'Remove Insignia',1), +(2,6,22810,'Opening - No Text',1), +(2,6,33391,'Journeyman Riding',1), +(2,6,45462,'Plague Strike',1), +(2,6,45477,'Icy Touch',1), +(2,6,45902,'Blood Strike',1), +(2,6,45903,'Offensive State (DND)',1), +(2,6,45927,'Summon Friend',1), +(2,6,47541,'Death Coil',1), +(2,6,48266,'Blood Presence',1), +(2,6,49410,'Forceful Deflection',1), +(2,6,49576,'Death Grip',1), +(2,6,52665,'Sigil',1), +(2,6,54562,'Command',1), +(2,6,59879,'Blood Plague',1), +(2,6,59921,'Frost Fever',1), +(2,6,61437,'Opening',1), +(2,6,61455,'Runic Focus',1), (2,7,81,'Dodge',1), (2,7,107,'Block',1), (2,7,198,'One-Handed Maces',1), @@ -8705,6 +10476,75 @@ INSERT INTO `playercreateinfo_spell` VALUES (3,5,21652,'Closing',1), (3,5,22027,'Remove Insignia',1), (3,5,22810,'Opening - No Text',1), +(3,6,81,'Dodge',1), +(3,6,196,'One-Handed Axes',1), +(3,6,197,'Two-Handed Axes',1), +(3,6,200,'Polearms',1), +(3,6,201,'One-Handed Swords',1), +(3,6,202,'Two-Handed Swords',1), +(3,6,203,'Unarmed',1), +(3,6,204,'Defense',1), +(3,6,522,'SPELLDEFENSE (DND)',1), +(3,6,668,'Language Common',1), +(3,6,672,'Language Dwarven',1), +(3,6,674,'Dual Wield',1), +(3,6,750,'Plate Mail',1), +(3,6,1843,'Disarm',1), +(3,6,2382,'Generic',1), +(3,6,2479,'Honorless Target',1), +(3,6,2481,'Find Treasure',1), +(3,6,3050,'Detect',1), +(3,6,3127,'Parry',1), +(3,6,3275,'Linen Bandage',1), +(3,6,3276,'Heavy Linen Bandage',1), +(3,6,3277,'Wool Bandage',1), +(3,6,3278,'Heavy Wool Bandage',1), +(3,6,3365,'Opening',1), +(3,6,6233,'Closing',1), +(3,6,6246,'Closing',1), +(3,6,6247,'Opening',1), +(3,6,6477,'Opening',1), +(3,6,6478,'Opening',1), +(3,6,6603,'Attack',1), +(3,6,7266,'Duel',1), +(3,6,7267,'Grovel',1), +(3,6,7355,'Stuck',1), +(3,6,7928,'Silk Bandage',1), +(3,6,7929,'Heavy Silk Bandage',1), +(3,6,7934,'Anti-Venom',1), +(3,6,8386,'Attacking',1), +(3,6,8737,'Mail',1), +(3,6,9077,'Leather',1), +(3,6,9078,'Cloth',1), +(3,6,9125,'Generic',1), +(3,6,10840,'Mageweave Bandage',1), +(3,6,10841,'Heavy Mageweave Bandage',1), +(3,6,10846,'First Aid',1), +(3,6,18629,'Runecloth Bandage',1), +(3,6,18630,'Heavy Runecloth Bandage',1), +(3,6,20594,'Stoneform',1), +(3,6,20595,'Gun Specialization',1), +(3,6,20596,'Frost Resistance',1), +(3,6,21651,'Opening',1), +(3,6,21652,'Closing',1), +(3,6,22027,'Remove Insignia',1), +(3,6,22810,'Opening - No Text',1), +(3,6,33391,'Journeyman Riding',1), +(3,6,45462,'Plague Strike',1), +(3,6,45477,'Icy Touch',1), +(3,6,45902,'Blood Strike',1), +(3,6,45903,'Offensive State (DND)',1), +(3,6,45927,'Summon Friend',1), +(3,6,47541,'Death Coil',1), +(3,6,48266,'Blood Presence',1), +(3,6,49410,'Forceful Deflection',1), +(3,6,49576,'Death Grip',1), +(3,6,52665,'Sigil',1), +(3,6,59224,'Mace Specialization',1), +(3,6,59879,'Blood Plague',1), +(3,6,59921,'Frost Fever',1), +(3,6,61437,'Opening',1), +(3,6,61455,'Runic Focus',1), (4,1,78,'Heroic Strike',1), (4,1,81,'Dodge',1), (4,1,107,'Block',1), @@ -8864,6 +10704,74 @@ INSERT INTO `playercreateinfo_spell` VALUES (4,5,21652,'Closing',1), (4,5,22027,'Remove Insignia',1), (4,5,22810,'Opening - No Text',1), +(4,6,81,'Dodge',1), +(4,6,196,'One-Handed Axes',1), +(4,6,197,'Two-Handed Axes',1), +(4,6,200,'Polearms',1), +(4,6,201,'One-Handed Swords',1), +(4,6,202,'Two-Handed Swords',1), +(4,6,203,'Unarmed',1), +(4,6,204,'Defense',1), +(4,6,522,'SPELLDEFENSE (DND)',1), +(4,6,668,'Language Common',1), +(4,6,671,'Language Darnassian',1), +(4,6,674,'Dual Wield',1), +(4,6,750,'Plate Mail',1), +(4,6,1843,'Disarm',1), +(4,6,2382,'Generic',1), +(4,6,2479,'Honorless Target',1), +(4,6,3050,'Detect',1), +(4,6,3127,'Parry',1), +(4,6,3275,'Linen Bandage',1), +(4,6,3276,'Heavy Linen Bandage',1), +(4,6,3277,'Wool Bandage',1), +(4,6,3278,'Heavy Wool Bandage',1), +(4,6,3365,'Opening',1), +(4,6,6233,'Closing',1), +(4,6,6246,'Closing',1), +(4,6,6247,'Opening',1), +(4,6,6477,'Opening',1), +(4,6,6478,'Opening',1), +(4,6,6603,'Attack',1), +(4,6,7266,'Duel',1), +(4,6,7267,'Grovel',1), +(4,6,7355,'Stuck',1), +(4,6,7928,'Silk Bandage',1), +(4,6,7929,'Heavy Silk Bandage',1), +(4,6,7934,'Anti-Venom',1), +(4,6,8386,'Attacking',1), +(4,6,8737,'Mail',1), +(4,6,9077,'Leather',1), +(4,6,9078,'Cloth',1), +(4,6,9125,'Generic',1), +(4,6,10840,'Mageweave Bandage',1), +(4,6,10841,'Heavy Mageweave Bandage',1), +(4,6,10846,'First Aid',1), +(4,6,18629,'Runecloth Bandage',1), +(4,6,18630,'Heavy Runecloth Bandage',1), +(4,6,20582,'Quickness',1), +(4,6,20583,'Nature Resistance',1), +(4,6,20585,'Wisp Spirit',1), +(4,6,21651,'Opening',1), +(4,6,21652,'Closing',1), +(4,6,22027,'Remove Insignia',1), +(4,6,22810,'Opening - No Text',1), +(4,6,33391,'Journeyman Riding',1), +(4,6,45462,'Plague Strike',1), +(4,6,45477,'Icy Touch',1), +(4,6,45902,'Blood Strike',1), +(4,6,45903,'Offensive State (DND)',1), +(4,6,45927,'Summon Friend',1), +(4,6,47541,'Death Coil',1), +(4,6,48266,'Blood Presence',1), +(4,6,49410,'Forceful Deflection',1), +(4,6,49576,'Death Grip',1), +(4,6,52665,'Sigil',1), +(4,6,58984,'Shadowmeld',1), +(4,6,59879,'Blood Plague',1), +(4,6,59921,'Frost Fever',1), +(4,6,61437,'Opening',1), +(4,6,61455,'Runic Focus',1), (4,11,81,'Dodge',1), (4,11,203,'Unarmed',1), (4,11,204,'Defense',1), @@ -9029,6 +10937,74 @@ INSERT INTO `playercreateinfo_spell` VALUES (5,5,21652,'Closing',1), (5,5,22027,'Remove Insignia',1), (5,5,22810,'Opening - No Text',1), +(5,6,81,'Dodge',1), +(5,6,196,'One-Handed Axes',1), +(5,6,197,'Two-Handed Axes',1), +(5,6,200,'Polearms',1), +(5,6,201,'One-Handed Swords',1), +(5,6,202,'Two-Handed Swords',1), +(5,6,203,'Unarmed',1), +(5,6,204,'Defense',1), +(5,6,522,'SPELLDEFENSE (DND)',1), +(5,6,669,'Language Orcish',1), +(5,6,674,'Dual Wield',1), +(5,6,750,'Plate Mail',1), +(5,6,1843,'Disarm',1), +(5,6,2382,'Generic',1), +(5,6,2479,'Honorless Target',1), +(5,6,3050,'Detect',1), +(5,6,3127,'Parry',1), +(5,6,3275,'Linen Bandage',1), +(5,6,3276,'Heavy Linen Bandage',1), +(5,6,3277,'Wool Bandage',1), +(5,6,3278,'Heavy Wool Bandage',1), +(5,6,3365,'Opening',1), +(5,6,5227,'Underwater Breathing',1), +(5,6,6233,'Closing',1), +(5,6,6246,'Closing',1), +(5,6,6247,'Opening',1), +(5,6,6477,'Opening',1), +(5,6,6478,'Opening',1), +(5,6,6603,'Attack',1), +(5,6,7266,'Duel',1), +(5,6,7267,'Grovel',1), +(5,6,7355,'Stuck',1), +(5,6,7744,'Will of the Forsaken',1), +(5,6,7928,'Silk Bandage',1), +(5,6,7929,'Heavy Silk Bandage',1), +(5,6,7934,'Anti-Venom',1), +(5,6,8386,'Attacking',1), +(5,6,8737,'Mail',1), +(5,6,9077,'Leather',1), +(5,6,9078,'Cloth',1), +(5,6,9125,'Generic',1), +(5,6,10840,'Mageweave Bandage',1), +(5,6,10841,'Heavy Mageweave Bandage',1), +(5,6,10846,'First Aid',1), +(5,6,17737,'Language Gutterspeak',1), +(5,6,18629,'Runecloth Bandage',1), +(5,6,18630,'Heavy Runecloth Bandage',1), +(5,6,20577,'Cannibalize',1), +(5,6,20579,'Shadow Resistance',1), +(5,6,21651,'Opening',1), +(5,6,21652,'Closing',1), +(5,6,22027,'Remove Insignia',1), +(5,6,22810,'Opening - No Text',1), +(5,6,33391,'Journeyman Riding',1), +(5,6,45462,'Plague Strike',1), +(5,6,45477,'Icy Touch',1), +(5,6,45902,'Blood Strike',1), +(5,6,45903,'Offensive State (DND)',1), +(5,6,45927,'Summon Friend',1), +(5,6,47541,'Death Coil',1), +(5,6,48266,'Blood Presence',1), +(5,6,49410,'Forceful Deflection',1), +(5,6,49576,'Death Grip',1), +(5,6,52665,'Sigil',1), +(5,6,59879,'Blood Plague',1), +(5,6,59921,'Frost Fever',1), +(5,6,61437,'Opening',1), +(5,6,61455,'Runic Focus',1), (5,8,81,'Dodge',1), (5,8,133,'Fireball',1), (5,8,168,'Frost Armor',1), @@ -9181,6 +11157,74 @@ INSERT INTO `playercreateinfo_spell` VALUES (6,3,22810,'Opening - No Text',1), (6,3,24949,'Defensive State 2(DND)',1), (6,3,34082,'Advantaged State(DND)',1), +(6,6,81,'Dodge',1), +(6,6,196,'One-Handed Axes',1), +(6,6,197,'Two-Handed Axes',1), +(6,6,200,'Polearms',1), +(6,6,201,'One-Handed Swords',1), +(6,6,202,'Two-Handed Swords',1), +(6,6,203,'Unarmed',1), +(6,6,204,'Defense',1), +(6,6,522,'SPELLDEFENSE (DND)',1), +(6,6,669,'Language Orcish',1), +(6,6,670,'Language Taurahe',1), +(6,6,674,'Dual Wield',1), +(6,6,750,'Plate Mail',1), +(6,6,1843,'Disarm',1), +(6,6,2382,'Generic',1), +(6,6,2479,'Honorless Target',1), +(6,6,3050,'Detect',1), +(6,6,3127,'Parry',1), +(6,6,3275,'Linen Bandage',1), +(6,6,3276,'Heavy Linen Bandage',1), +(6,6,3277,'Wool Bandage',1), +(6,6,3278,'Heavy Wool Bandage',1), +(6,6,3365,'Opening',1), +(6,6,6233,'Closing',1), +(6,6,6246,'Closing',1), +(6,6,6247,'Opening',1), +(6,6,6477,'Opening',1), +(6,6,6478,'Opening',1), +(6,6,6603,'Attack',1), +(6,6,7266,'Duel',1), +(6,6,7267,'Grovel',1), +(6,6,7355,'Stuck',1), +(6,6,7928,'Silk Bandage',1), +(6,6,7929,'Heavy Silk Bandage',1), +(6,6,7934,'Anti-Venom',1), +(6,6,8386,'Attacking',1), +(6,6,8737,'Mail',1), +(6,6,9077,'Leather',1), +(6,6,9078,'Cloth',1), +(6,6,9125,'Generic',1), +(6,6,10840,'Mageweave Bandage',1), +(6,6,10841,'Heavy Mageweave Bandage',1), +(6,6,10846,'First Aid',1), +(6,6,18629,'Runecloth Bandage',1), +(6,6,18630,'Heavy Runecloth Bandage',1), +(6,6,20549,'War Stomp',1), +(6,6,20550,'Endurance',1), +(6,6,20551,'Nature Resistance',1), +(6,6,20552,'Cultivation',1), +(6,6,21651,'Opening',1), +(6,6,21652,'Closing',1), +(6,6,22027,'Remove Insignia',1), +(6,6,22810,'Opening - No Text',1), +(6,6,33391,'Journeyman Riding',1), +(6,6,45462,'Plague Strike',1), +(6,6,45477,'Icy Touch',1), +(6,6,45902,'Blood Strike',1), +(6,6,45903,'Offensive State (DND)',1), +(6,6,45927,'Summon Friend',1), +(6,6,47541,'Death Coil',1), +(6,6,48266,'Blood Presence',1), +(6,6,49410,'Forceful Deflection',1), +(6,6,49576,'Death Grip',1), +(6,6,52665,'Sigil',1), +(6,6,59879,'Blood Plague',1), +(6,6,59921,'Frost Fever',1), +(6,6,61437,'Opening',1), +(6,6,61455,'Runic Focus',1), (6,7,81,'Dodge',1), (6,7,107,'Block',1), (6,7,198,'One-Handed Maces',1), @@ -9348,6 +11392,74 @@ INSERT INTO `playercreateinfo_spell` VALUES (7,4,21652,'Closing',1), (7,4,22027,'Remove Insignia',1), (7,4,22810,'Opening - No Text',1), +(7,6,81,'Dodge',1), +(7,6,196,'One-Handed Axes',1), +(7,6,197,'Two-Handed Axes',1), +(7,6,200,'Polearms',1), +(7,6,201,'One-Handed Swords',1), +(7,6,202,'Two-Handed Swords',1), +(7,6,203,'Unarmed',1), +(7,6,204,'Defense',1), +(7,6,522,'SPELLDEFENSE (DND)',1), +(7,6,668,'Language Common',1), +(7,6,674,'Dual Wield',1), +(7,6,750,'Plate Mail',1), +(7,6,1843,'Disarm',1), +(7,6,2382,'Generic',1), +(7,6,2479,'Honorless Target',1), +(7,6,3050,'Detect',1), +(7,6,3127,'Parry',1), +(7,6,3275,'Linen Bandage',1), +(7,6,3276,'Heavy Linen Bandage',1), +(7,6,3277,'Wool Bandage',1), +(7,6,3278,'Heavy Wool Bandage',1), +(7,6,3365,'Opening',1), +(7,6,6233,'Closing',1), +(7,6,6246,'Closing',1), +(7,6,6247,'Opening',1), +(7,6,6477,'Opening',1), +(7,6,6478,'Opening',1), +(7,6,6603,'Attack',1), +(7,6,7266,'Duel',1), +(7,6,7267,'Grovel',1), +(7,6,7340,'Language Gnomish',1), +(7,6,7355,'Stuck',1), +(7,6,7928,'Silk Bandage',1), +(7,6,7929,'Heavy Silk Bandage',1), +(7,6,7934,'Anti-Venom',1), +(7,6,8386,'Attacking',1), +(7,6,8737,'Mail',1), +(7,6,9077,'Leather',1), +(7,6,9078,'Cloth',1), +(7,6,9125,'Generic',1), +(7,6,10840,'Mageweave Bandage',1), +(7,6,10841,'Heavy Mageweave Bandage',1), +(7,6,10846,'First Aid',1), +(7,6,18629,'Runecloth Bandage',1), +(7,6,18630,'Heavy Runecloth Bandage',1), +(7,6,20589,'Escape Artist',1), +(7,6,20591,'Expansive Mind',1), +(7,6,20592,'Arcane Resistance',1), +(7,6,20593,'Engineering Specialization',1), +(7,6,21651,'Opening',1), +(7,6,21652,'Closing',1), +(7,6,22027,'Remove Insignia',1), +(7,6,22810,'Opening - No Text',1), +(7,6,33391,'Journeyman Riding',1), +(7,6,45462,'Plague Strike',1), +(7,6,45477,'Icy Touch',1), +(7,6,45902,'Blood Strike',1), +(7,6,45903,'Offensive State (DND)',1), +(7,6,45927,'Summon Friend',1), +(7,6,47541,'Death Coil',1), +(7,6,48266,'Blood Presence',1), +(7,6,49410,'Forceful Deflection',1), +(7,6,49576,'Death Grip',1), +(7,6,52665,'Sigil',1), +(7,6,59879,'Blood Plague',1), +(7,6,59921,'Frost Fever',1), +(7,6,61437,'Opening',1), +(7,6,61455,'Runic Focus',1), (7,8,81,'Dodge',1), (7,8,133,'Fireball',1), (7,8,168,'Frost Armor',1), @@ -9578,6 +11690,76 @@ INSERT INTO `playercreateinfo_spell` VALUES (8,5,22027,'Remove Insignia',1), (8,5,22810,'Opening - No Text',1), (8,5,26290,'Bow Specialization',1), +(8,6,81,'Dodge',1), +(8,6,196,'One-Handed Axes',1), +(8,6,197,'Two-Handed Axes',1), +(8,6,200,'Polearms',1), +(8,6,201,'One-Handed Swords',1), +(8,6,202,'Two-Handed Swords',1), +(8,6,203,'Unarmed',1), +(8,6,204,'Defense',1), +(8,6,522,'SPELLDEFENSE (DND)',1), +(8,6,669,'Language Orcish',1), +(8,6,674,'Dual Wield',1), +(8,6,750,'Plate Mail',1), +(8,6,1843,'Disarm',1), +(8,6,2382,'Generic',1), +(8,6,2479,'Honorless Target',1), +(8,6,3050,'Detect',1), +(8,6,3127,'Parry',1), +(8,6,3275,'Linen Bandage',1), +(8,6,3276,'Heavy Linen Bandage',1), +(8,6,3277,'Wool Bandage',1), +(8,6,3278,'Heavy Wool Bandage',1), +(8,6,3365,'Opening',1), +(8,6,6233,'Closing',1), +(8,6,6246,'Closing',1), +(8,6,6247,'Opening',1), +(8,6,6477,'Opening',1), +(8,6,6478,'Opening',1), +(8,6,6603,'Attack',1), +(8,6,7266,'Duel',1), +(8,6,7267,'Grovel',1), +(8,6,7341,'Language Troll',1), +(8,6,7355,'Stuck',1), +(8,6,7928,'Silk Bandage',1), +(8,6,7929,'Heavy Silk Bandage',1), +(8,6,7934,'Anti-Venom',1), +(8,6,8386,'Attacking',1), +(8,6,8737,'Mail',1), +(8,6,9077,'Leather',1), +(8,6,9078,'Cloth',1), +(8,6,9125,'Generic',1), +(8,6,10840,'Mageweave Bandage',1), +(8,6,10841,'Heavy Mageweave Bandage',1), +(8,6,10846,'First Aid',1), +(8,6,18629,'Runecloth Bandage',1), +(8,6,18630,'Heavy Runecloth Bandage',1), +(8,6,20555,'Regeneration',1), +(8,6,20557,'Beast Slaying',1), +(8,6,20558,'Throwing Specialization',1), +(8,6,21651,'Opening',1), +(8,6,21652,'Closing',1), +(8,6,22027,'Remove Insignia',1), +(8,6,22810,'Opening - No Text',1), +(8,6,26290,'Bow Specialization',1), +(8,6,33391,'Journeyman Riding',1), +(8,6,45462,'Plague Strike',1), +(8,6,45477,'Icy Touch',1), +(8,6,45902,'Blood Strike',1), +(8,6,45903,'Offensive State (DND)',1), +(8,6,45927,'Summon Friend',1), +(8,6,47541,'Death Coil',1), +(8,6,48266,'Blood Presence',1), +(8,6,49410,'Forceful Deflection',1), +(8,6,49576,'Death Grip',1), +(8,6,50621,'Berserking',1), +(8,6,52665,'Sigil',1), +(8,6,58943,'Da Voodoo Shuffle',1), +(8,6,59879,'Blood Plague',1), +(8,6,59921,'Frost Fever',1), +(8,6,61437,'Opening',1), +(8,6,61455,'Runic Focus',1), (8,7,81,'Dodge',1), (8,7,107,'Block',1), (8,7,198,'One-Handed Maces',1), @@ -9803,6 +11985,73 @@ INSERT INTO `playercreateinfo_spell` VALUES (10,5,28730,'Arcane Torrent',1), (10,5,28734,'Mana Tap',1), (10,5,28877,'Arcane Affinity',1), +(10,6,81,'Dodge',1), +(10,6,196,'One-Handed Axes',1), +(10,6,197,'Two-Handed Axes',1), +(10,6,200,'Polearms',1), +(10,6,201,'One-Handed Swords',1), +(10,6,202,'Two-Handed Swords',1), +(10,6,203,'Unarmed',1), +(10,6,204,'Defense',1), +(10,6,522,'SPELLDEFENSE (DND)',1), +(10,6,669,'Language Orcish',1), +(10,6,674,'Dual Wield',1), +(10,6,750,'Plate Mail',1), +(10,6,813,'Language Thalassian',1), +(10,6,822,'Magic Resistance',1), +(10,6,1843,'Disarm',1), +(10,6,2382,'Generic',1), +(10,6,2479,'Honorless Target',1), +(10,6,3050,'Detect',1), +(10,6,3127,'Parry',1), +(10,6,3275,'Linen Bandage',1), +(10,6,3276,'Heavy Linen Bandage',1), +(10,6,3277,'Wool Bandage',1), +(10,6,3278,'Heavy Wool Bandage',1), +(10,6,3365,'Opening',1), +(10,6,6233,'Closing',1), +(10,6,6246,'Closing',1), +(10,6,6247,'Opening',1), +(10,6,6477,'Opening',1), +(10,6,6478,'Opening',1), +(10,6,6603,'Attack',1), +(10,6,7266,'Duel',1), +(10,6,7267,'Grovel',1), +(10,6,7355,'Stuck',1), +(10,6,7928,'Silk Bandage',1), +(10,6,7929,'Heavy Silk Bandage',1), +(10,6,7934,'Anti-Venom',1), +(10,6,8386,'Attacking',1), +(10,6,8737,'Mail',1), +(10,6,9077,'Leather',1), +(10,6,9078,'Cloth',1), +(10,6,9125,'Generic',1), +(10,6,10840,'Mageweave Bandage',1), +(10,6,10841,'Heavy Mageweave Bandage',1), +(10,6,10846,'First Aid',1), +(10,6,18629,'Runecloth Bandage',1), +(10,6,18630,'Heavy Runecloth Bandage',1), +(10,6,21651,'Opening',1), +(10,6,21652,'Closing',1), +(10,6,22027,'Remove Insignia',1), +(10,6,22810,'Opening - No Text',1), +(10,6,28877,'Arcane Affinity',1), +(10,6,33391,'Journeyman Riding',1), +(10,6,45462,'Plague Strike',1), +(10,6,45477,'Icy Touch',1), +(10,6,45902,'Blood Strike',1), +(10,6,45903,'Offensive State (DND)',1), +(10,6,45927,'Summon Friend',1), +(10,6,47541,'Death Coil',1), +(10,6,48266,'Blood Presence',1), +(10,6,49410,'Forceful Deflection',1), +(10,6,49576,'Death Grip',1), +(10,6,50613,'Arcane Torrent',1), +(10,6,52665,'Sigil',1), +(10,6,59879,'Blood Plague',1), +(10,6,59921,'Frost Fever',1), +(10,6,61437,'Opening',1), +(10,6,61455,'Runic Focus',1), (10,8,81,'Dodge',1), (10,8,133,'Fireball',1), (10,8,168,'Frost Armor',1), @@ -10029,6 +12278,74 @@ INSERT INTO `playercreateinfo_spell` VALUES (11,5,28878,'Inspiring Presence',1), (11,5,28880,'Gift of the Naaru',1), (11,5,29932,'Language Draenei',1), +(11,6,81,'Dodge',1), +(11,6,196,'One-Handed Axes',1), +(11,6,197,'Two-Handed Axes',1), +(11,6,200,'Polearms',1), +(11,6,201,'One-Handed Swords',1), +(11,6,202,'Two-Handed Swords',1), +(11,6,203,'Unarmed',1), +(11,6,204,'Defense',1), +(11,6,522,'SPELLDEFENSE (DND)',1), +(11,6,668,'Language Common',1), +(11,6,674,'Dual Wield',1), +(11,6,750,'Plate Mail',1), +(11,6,1843,'Disarm',1), +(11,6,2382,'Generic',1), +(11,6,2479,'Honorless Target',1), +(11,6,3050,'Detect',1), +(11,6,3127,'Parry',1), +(11,6,3275,'Linen Bandage',1), +(11,6,3276,'Heavy Linen Bandage',1), +(11,6,3277,'Wool Bandage',1), +(11,6,3278,'Heavy Wool Bandage',1), +(11,6,3365,'Opening',1), +(11,6,6233,'Closing',1), +(11,6,6246,'Closing',1), +(11,6,6247,'Opening',1), +(11,6,6477,'Opening',1), +(11,6,6478,'Opening',1), +(11,6,6562,'Heroic Presence',1), +(11,6,6603,'Attack',1), +(11,6,7266,'Duel',1), +(11,6,7267,'Grovel',1), +(11,6,7355,'Stuck',1), +(11,6,7928,'Silk Bandage',1), +(11,6,7929,'Heavy Silk Bandage',1), +(11,6,7934,'Anti-Venom',1), +(11,6,8386,'Attacking',1), +(11,6,8737,'Mail',1), +(11,6,9077,'Leather',1), +(11,6,9078,'Cloth',1), +(11,6,9125,'Generic',1), +(11,6,10840,'Mageweave Bandage',1), +(11,6,10841,'Heavy Mageweave Bandage',1), +(11,6,10846,'First Aid',1), +(11,6,18629,'Runecloth Bandage',1), +(11,6,18630,'Heavy Runecloth Bandage',1), +(11,6,21651,'Opening',1), +(11,6,21652,'Closing',1), +(11,6,22027,'Remove Insignia',1), +(11,6,22810,'Opening - No Text',1), +(11,6,28875,'Gemcutting',1), +(11,6,29932,'Language Draenei',1), +(11,6,33391,'Journeyman Riding',1), +(11,6,45462,'Plague Strike',1), +(11,6,45477,'Icy Touch',1), +(11,6,45902,'Blood Strike',1), +(11,6,45903,'Offensive State (DND)',1), +(11,6,45927,'Summon Friend',1), +(11,6,47541,'Death Coil',1), +(11,6,48266,'Blood Presence',1), +(11,6,49410,'Forceful Deflection',1), +(11,6,49576,'Death Grip',1), +(11,6,52665,'Sigil',1), +(11,6,59539,'Shadow Resistance',1), +(11,6,59545,'Gift of the Naaru',1), +(11,6,59879,'Blood Plague',1), +(11,6,59921,'Frost Fever',1), +(11,6,61437,'Opening',1), +(11,6,61455,'Runic Focus',1), (11,7,81,'Dodge',1), (11,7,107,'Block',1), (11,7,198,'One-Handed Maces',1), @@ -10239,6 +12556,8 @@ CREATE TABLE `quest_template` ( `QuestFlags` smallint(5) unsigned NOT NULL default '0', `SpecialFlags` tinyint(3) unsigned NOT NULL default '0', `CharTitleId` tinyint(3) unsigned NOT NULL default '0', + `PlayersSlain` tinyint(3) unsigned NOT NULL default '0', + `BonusTalents` tinyint(3) unsigned NOT NULL default '0', `PrevQuestId` mediumint(9) NOT NULL default '0', `NextQuestId` mediumint(9) NOT NULL default '0', `ExclusiveGroup` mediumint(9) NOT NULL default '0', @@ -10496,7 +12815,9 @@ DROP TABLE IF EXISTS `spell_affect`; CREATE TABLE `spell_affect` ( `entry` smallint(5) unsigned NOT NULL default '0', `effectId` tinyint(3) unsigned NOT NULL default '0', - `SpellFamilyMask` bigint(20) unsigned NOT NULL default '0', + `SpellClassMask0` int(5) unsigned NOT NULL default '0', + `SpellClassMask1` int(5) unsigned NOT NULL default '0', + `SpellClassMask2` int(5) unsigned NOT NULL default '0', PRIMARY KEY (`entry`,`effectId`) ) ENGINE=MyISAM DEFAULT CHARSET=utf8; @@ -10506,1198 +12827,6 @@ CREATE TABLE `spell_affect` ( LOCK TABLES `spell_affect` WRITE; /*!40000 ALTER TABLE `spell_affect` DISABLE KEYS */; -INSERT INTO `spell_affect` VALUES -(5420,2,0x00001012100000D0), -(8875,1,0x0000040000000000), -(11069,0,0x0000000000000001), -(11070,0,0x0000000000000020), -(11071,0,0x0000000000100000), -(11083,0,0x0000000000C20017), -(11124,0,0x0000000008C20017), -(11151,0,0x00000000000202E0), -(11160,0,0x00000001020203E0), -(11175,1,0x0000000000100000), -(11207,0,0x00000000000202E0), -(11222,0,0x0000000020001800), -(11242,0,0x0000000020001000), -(11247,0,0x0000000000002000), -(12042,0,0x0000000020E01AF7), -(12042,1,0x0000000020E01AF7), -(12042,2,0x0000000020E01AF7), -(12043,0,0x0000000021400035), -(12285,0,0x0000000000000001), -(12286,0,0x0000000000000020), -(12287,1,0x0000000000000080), -(12295,1,0x0000000002000000), -(12295,2,0x0000040000000000), -(12301,0,0x0000000000000100), -(12303,1,0x0000100000000000), -(12308,0,0x0000000000004000), -(12318,0,0x0000008000010000), -(12321,0,0x0000008000030000), -(12321,1,0x0000008000030000), -(12330,0,0x0000000000200000), -(12338,0,0x0000000000000001), -(12339,0,0x0000000000000001), -(12340,0,0x0000000000000001), -(12341,0,0x0000000000000001), -(12351,0,0x0000000000C20017), -(12378,0,0x0000000008C20017), -(12398,0,0x0000000008C20017), -(12399,0,0x0000000008C20017), -(12400,0,0x0000000008C20017), -(12467,0,0x0000000020001000), -(12469,0,0x0000000020001000), -(12472,1,0x00000000E44008A5), -(12473,0,0x0000000000000020), -(12496,0,0x0000000000100000), -(12497,0,0x0000000000100000), -(12518,0,0x00000001020203E0), -(12519,0,0x00000001020203E0), -(12536,0,0x0000000020C01AF7), -(12569,1,0x0000000000100000), -(12571,1,0x0000000000100000), -(12658,0,0x0000000000000020), -(12659,0,0x0000000000000020), -(12665,1,0x0000000000000080), -(12666,1,0x0000000000000080), -(12672,0,0x00000000000202E0), -(12676,1,0x0000000002000000), -(12676,2,0x0000040000000000), -(12677,1,0x0000000002000000), -(12677,2,0x0000040000000000), -(12697,0,0x0000000000000001), -(12788,1,0x0000100000000000), -(12789,1,0x0000100000000000), -(12810,0,0x0000000000004000), -(12811,0,0x0000000000004000), -(12818,0,0x0000000000000100), -(12835,0,0x0000008000030000), -(12835,1,0x0000008000030000), -(12836,0,0x0000008000030000), -(12836,1,0x0000008000030000), -(12837,0,0x0000008000030000), -(12837,1,0x0000008000030000), -(12838,0,0x0000008000030000), -(12838,1,0x0000008000030000), -(12839,0,0x0000000020001800), -(12840,0,0x0000000020001800), -(12841,0,0x0000000020001800), -(12842,0,0x0000000020001800), -(12857,0,0x0000008000010000), -(12858,0,0x0000008000010000), -(12860,0,0x0000008000010000), -(12861,0,0x0000008000010000), -(12862,0,0x0000000000200000), -(12945,1,0x0000000000001000), -(12952,0,0x00000000000202E0), -(12953,0,0x00000000000202E0), -(12954,0,0x00000000000202E0), -(12957,0,0x00000000000202E0), -(13733,0,0x0000000000000004), -(13733,1,0x0000000400000000), -(13742,0,0x0000000000000060), -(13743,0,0x0000000000000040), -(13865,0,0x0000000000000004), -(13865,1,0x0000000400000000), -(13866,0,0x0000000000000004), -(13866,1,0x0000000400000000), -(13872,0,0x0000000000000060), -(13875,0,0x0000000000000040), -(13975,0,0x0000000000400000), -(13975,1,0x0000000000400000), -(13976,0,0x0000000000000700), -(13979,0,0x0000000000000700), -(13980,0,0x0000000000000700), -(13981,0,0x0000000001000000), -(13981,1,0x0000000000000800), -(14057,0,0x0000000600000304), -(14062,0,0x0000000000400000), -(14062,1,0x0000000000400000), -(14063,0,0x0000000000400000), -(14063,1,0x0000000000400000), -(14064,0,0x0000000000400000), -(14064,1,0x0000000000400000), -(14065,0,0x0000000000400000), -(14065,1,0x0000000000400000), -(14066,0,0x0000000001000000), -(14066,1,0x0000000000000800), -(14072,0,0x0000000600000304), -(14073,0,0x0000000600000304), -(14074,0,0x0000000600000304), -(14075,0,0x0000000600000304), -(14076,0,0x0000000001000080), -(14076,1,0x0000000001000080), -(14082,0,0x0000000000000500), -(14083,0,0x0000000000000500), -(14094,0,0x0000000001000080), -(14094,1,0x0000000001000080), -(14113,0,0x000000000001E000), -(14114,0,0x000000000001E000), -(14115,0,0x000000000001E000), -(14116,0,0x000000000001E000), -(14117,0,0x000000000001E000), -(14128,0,0x000000062600000E), -(14132,0,0x000000062600000E), -(14135,0,0x000000062600000E), -(14136,0,0x000000062600000E), -(14137,0,0x000000062600000E), -(14143,0,0x0000000004000206), -(14149,0,0x0000000004000206), -(14162,0,0x0000000000020000), -(14163,0,0x0000000000020000), -(14164,0,0x0000000000020000), -(14168,0,0x0000000000080000), -(14169,0,0x0000000000080000), -(14174,0,0x0000000000200000), -(14175,0,0x0000000000200000), -(14176,0,0x0000000000200000), -(14177,0,0x0000000C6012031E), -(14179,0,0x00000009003E0000), -(14520,0,0x00000963BF61C16F), -(14523,1,0x000000208030016B), -(14523,2,0x000000208030016B), -(14743,0,0x0000049440963E90), -(14747,0,0x0000000000000002), -(14750,0,0x0000000000000010), -(14751,0,0xFFFFFFFFFFFFFFFF), -(14751,1,0xFFFFFFFFFFFFFFFF), -(14770,0,0x0000000000000002), -(14771,0,0x0000000000000002), -(14772,0,0x0000000000000010), -(14780,0,0x00000963BF61C16F), -(14781,0,0x00000963BF61C16F), -(14782,0,0x00000963BF61C16F), -(14783,0,0x00000963BF61C16F), -(14784,1,0x000000208030016B), -(14784,2,0x000000208030016B), -(14785,1,0x000000208030016B), -(14785,2,0x000000208030016B), -(14786,1,0x000000208030016B), -(14786,2,0x000000208030016B), -(14787,1,0x000000208030016B), -(14787,2,0x000000208030016B), -(14908,0,0x0000000000000040), -(14909,1,0x0000000000100080), -(14911,0,0x0000002000000200), -(14912,0,0x0000000000041400), -(14913,0,0x0000000400041E00), -(15012,0,0x0000000400041E00), -(15013,0,0x0000000000041400), -(15014,0,0x0000000000041400), -(15017,1,0x0000000000100080), -(15018,0,0x0000002000000200), -(15020,0,0x0000000000000040), -(15047,0,0x00000000000202E0), -(15052,0,0x00000000000202E0), -(15053,0,0x00000000000202E0), -(15257,0,0x000004020288A010), -(15259,0,0x0000000202002000), -(15259,1,0x0000040000808000), -(15260,0,0x00000442068BA000), -(15272,0,0x00000D4A068BE104), -(15307,0,0x0000000202002000), -(15307,1,0x0000040000808000), -(15308,0,0x0000000202002000), -(15308,1,0x0000040000808000), -(15309,0,0x0000000202002000), -(15309,1,0x0000040000808000), -(15310,0,0x0000000202002000), -(15310,1,0x0000040000808000), -(15318,0,0x00000D4A068BE104), -(15320,0,0x00000D4A068BE104), -(15327,0,0x00000442068BA000), -(15328,0,0x00000442068BA000), -(15329,0,0x00000442068BA000), -(15330,0,0x00000442068BA000), -(15331,0,0x000004020288A010), -(15332,0,0x000004020288A010), -(15333,0,0x000004020288A010), -(15334,0,0x000004020288A010), -(16035,0,0x0000000090100003), -(16038,0,0x0000000040000000), -(16039,0,0x0000000090100003), -(16041,0,0x0000000000000003), -(16043,0,0x0000000000000008), -(16043,1,0x0000000100000000), -(16086,0,0x0000000000000020), -(16086,1,0x0000000000000020), -(16086,2,0x0000000000000004), -(16089,0,0x00000004D3300407), -(16105,0,0x0000000090100003), -(16106,0,0x0000000090100003), -(16106,1,0x0000000090100003), -(16107,0,0x0000000090100003), -(16108,0,0x0000000090100003), -(16109,0,0x0000000090100003), -(16110,0,0x0000000090100003), -(16111,0,0x0000000090100003), -(16112,0,0x0000000090100003), -(16117,0,0x0000000000000003), -(16118,0,0x0000000000000003), -(16119,0,0x0000000000000003), -(16120,0,0x0000000000000003), -(16130,0,0x0000000000000008), -(16130,1,0x0000000100000000), -(16160,0,0x0000000040000000), -(16161,0,0x0000000040000000), -(16166,0,0x0000000090100003), -(16166,1,0x0000000090100003), -(16173,0,0x0000000020081018), -(16179,0,0x00000000000000C0), -(16181,0,0x00000000000001C0), -(16184,0,0x0000000000000200), -(16184,1,0x0000000000000200), -(16187,0,0x0000000000006000), -(16187,1,0x0000000000006000), -(16188,0,0x00000000000009C3), -(16189,0,0x000001000403E000), -(16205,0,0x0000000000006000), -(16205,1,0x0000000000006000), -(16206,0,0x0000000000006000), -(16206,1,0x0000000000006000), -(16207,0,0x0000000000006000), -(16207,1,0x0000000000006000), -(16208,0,0x0000000000006000), -(16208,1,0x0000000000006000), -(16209,1,0x0000000000000200), -(16214,0,0x00000000000000C0), -(16215,0,0x00000000000000C0), -(16216,0,0x00000000000000C0), -(16217,0,0x00000000000000C0), -(16222,0,0x0000000020081018), -(16223,0,0x0000000020081018), -(16224,0,0x0000000020081018), -(16225,0,0x0000000020081018), -(16230,0,0x00000000000001C0), -(16232,0,0x00000000000001C0), -(16233,0,0x00000000000001C0), -(16234,0,0x00000000000001C0), -(16246,0,0x0000000090100003), -(16258,0,0x0000000000008000), -(16258,1,0x0000000000040000), -(16259,0,0x0000000000010000), -(16259,1,0x0000000000020000), -(16261,0,0x0000000000000400), -(16266,0,0x0000000000400000), -(16266,1,0x0000000001000000), -(16266,2,0x0000000000800000), -(16290,0,0x0000000000000400), -(16291,0,0x0000000000000400), -(16293,0,0x0000000000008000), -(16293,1,0x0000000000040000), -(16295,0,0x0000000000010000), -(16295,1,0x0000000000020000), -(16493,0,0x0000014D2A600CEF), -(16494,0,0x0000014D2A600CEF), -(16513,0,0x000000080001E000), -(16513,1,0x000000000001E000), -(16513,2,0x000000000001E000), -(16514,0,0x000000080001E000), -(16514,1,0x000000000001E000), -(16514,2,0x000000000001E000), -(16515,0,0x000000080001E000), -(16515,1,0x000000000001E000), -(16515,2,0x000000000001E000), -(16544,2,0x0000000000000004), -(16578,0,0x0000000000000003), -(16579,0,0x0000000000000003), -(16580,0,0x0000000000000003), -(16581,0,0x0000000000000003), -(16582,0,0x0000000000000003), -(16719,0,0x000000080001E000), -(16719,1,0x000000000001E000), -(16719,2,0x000000000001E000), -(16720,0,0x000000080001E000), -(16720,1,0x000000000001E000), -(16720,2,0x000000000001E000), -(16757,0,0x00000000000200A0), -(16757,1,0x0000000000000240), -(16758,0,0x00000000000200A0), -(16758,1,0x0000000000000240), -(16763,0,0x0000000000000020), -(16765,0,0x0000000000000020), -(16766,0,0x0000000000000020), -(16814,0,0x0000000000000005), -(16815,0,0x0000000000000005), -(16816,0,0x0000000000000005), -(16817,0,0x0000000000000005), -(16818,0,0x0000000000000005), -(16819,0,0x0002122000600707), -(16820,0,0x0002122000600707), -(16821,0,0x0000000000000002), -(16821,1,0x0000000000000002), -(16821,2,0x0000000000000002), -(16822,0,0x0000000000000002), -(16822,1,0x0000000000000002), -(16822,2,0x0000000000000002), -(16833,0,0x0000E000E2000000), -(16834,0,0x0000E000E2000000), -(16835,0,0x0000E000E2000000), -(16836,1,0x0000000000000300), -(16839,1,0x0000000000000300), -(16840,1,0x0000000000000300), -(16850,1,0x0000000000000001), -(16870,0,0x001007F100E3FEFF), -(16886,0,0x0000000001000265), -(16896,0,0x0000000000000007), -(16896,1,0x0000000000000007), -(16897,0,0x0000000000000007), -(16897,1,0x0000000000000007), -(16899,0,0x0000000000000007), -(16899,1,0x0000000000000007), -(16900,0,0x0000000000000007), -(16900,1,0x0000000000000007), -(16901,0,0x0000000000000007), -(16901,1,0x0000000000000007), -(16918,0,0x0000002000000200), -(16919,0,0x0000002000000200), -(16920,0,0x0000002000000200), -(16923,1,0x0000000000000001), -(16924,1,0x0000000000000001), -(16934,0,0x0010004000000800), -(16934,1,0x0000040000001000), -(16935,0,0x0010004000000800), -(16935,1,0x0000040000001000), -(16936,0,0x0010004000000800), -(16936,1,0x0000040000001000), -(16937,0,0x0010004000000800), -(16937,1,0x0000040000001000), -(16938,0,0x0010004000000800), -(16938,1,0x0000040000001000), -(16947,1,0x0000000002000000), -(16948,1,0x0000000002000000), -(16949,1,0x0000000002000000), -(16966,0,0x0000000000008000), -(16966,1,0x0000010000000000), -(16968,0,0x0000000000008000), -(16968,1,0x0000010000000000), -(16998,0,0x0000000000001000), -(16998,2,0x0000000000001000), -(16999,0,0x0000000000001000), -(16999,2,0x0000000000001000), -(17104,0,0x00000010000000F0), -(17104,1,0x00000010000000F0), -(17111,0,0x0000000000000010), -(17112,0,0x0000000000000010), -(17113,0,0x0000000000000010), -(17114,0,0x0000000000000010), -(17115,0,0x0000000000000010), -(17116,0,0x0002002010000261), -(17118,0,0x001005D000E193F7), -(17118,1,0x0004103000340750), -(17119,0,0x001005D000E193F7), -(17119,1,0x0004103000340750), -(17120,0,0x001005D000E193F7), -(17120,1,0x0004103000340750), -(17121,0,0x001005D000E193F7), -(17121,1,0x0004103000340750), -(17122,0,0x001005D000E193F7), -(17122,1,0x0004103000340750), -(17123,0,0x0000000000000080), -(17124,0,0x0000000000000080), -(17191,0,0x0000000000000040), -(17322,0,0x00000542068AA004), -(17323,0,0x00000542068AA004), -(17768,0,0x0000000040000000), -(17768,1,0x0000000080000000), -(17778,0,0x000010C0000003E5), -(17779,0,0x000010C0000003E5), -(17780,0,0x000010C0000003E5), -(17781,0,0x000010C0000003E5), -(17782,0,0x000010C0000003E5), -(17788,1,0x0000008000000000), -(17789,1,0x0000008000000000), -(17790,1,0x0000008000000000), -(17791,1,0x0000008000000000), -(17792,1,0x0000008000000000), -(17904,0,0x0000000000000000), -(17912,0,0x0000000000000000), -(17913,0,0x0000000000000000), -(17914,0,0x0000000000000000), -(17915,0,0x0000000000000000), -(17916,0,0x0000000000000000), -(17917,0,0x000010C0000003A5), -(17917,1,0x000010C0000003E5), -(17918,0,0x000010C0000003A5), -(17918,1,0x000010C0000003E5), -(17927,0,0x0000000000000100), -(17929,0,0x0000000000000100), -(17930,0,0x0000000000000100), -(17941,0,0x0000000000000001), -(17954,0,0x000000C000001364), -(17954,1,0x000000C000001364), -(17954,2,0x0000004000000000), -(17955,0,0x000000C000001364), -(17955,1,0x000000C000001364), -(17955,2,0x0000004000000000), -(17956,0,0x000000C000001364), -(17956,1,0x000000C000001364), -(17956,2,0x0000004000000000), -(17957,0,0x000000C000001364), -(17957,1,0x000000C000001364), -(17957,2,0x0000004000000000), -(17958,0,0x000000C000001364), -(17958,1,0x000000C000001364), -(17958,2,0x0000004000000000), -(17959,0,0x000010C0000003E5), -(18126,0,0x0000000000001000), -(18127,0,0x0000000000001000), -(18130,0,0x000010C0000003E5), -(18131,0,0x000010C0000003E5), -(18132,0,0x000010C0000003E5), -(18133,0,0x000010C0000003E5), -(18134,0,0x000010C0000003E5), -(18135,0,0x000010C0000003E5), -(18136,0,0x000010C0000003E5), -(18174,0,0x0000071B804CC41A), -(18175,0,0x0000071B804CC41A), -(18176,0,0x0000071B804CC41A), -(18177,0,0x0000071B804CC41A), -(18178,0,0x0000071B804CC41A), -(18179,0,0x0000000000008000), -(18180,0,0x0000000000008000), -(18213,0,0x0000000000004000), -(18213,1,0x0000871B804CC41A), -(18218,0,0x000007138048C41A), -(18219,0,0x000007138048C41A), -(18271,0,0x000011130008A48B), -(18271,1,0x000011130008A48B), -(18272,0,0x000011130008A48B), -(18272,1,0x000011130008A48B), -(18273,0,0x000011130008A48B), -(18273,1,0x000011130008A48B), -(18274,0,0x000011130008A48B), -(18274,1,0x000011130008A48B), -(18275,0,0x000011130008A48B), -(18275,1,0x000011130008A48B), -(18288,0,0x0000000200000400), -(18288,1,0x0000000000400000), -(18372,1,0x0000871B804CC41A), -(18427,0,0x0000000000020006), -(18428,0,0x0000000000020006), -(18429,0,0x0000000000020006), -(18544,0,0x0000041202F8A090), -(18544,1,0x0000001202582090), -(18544,2,0x0000040000A08000), -(18547,0,0x0000041202F8A090), -(18547,1,0x0000001202582090), -(18547,2,0x0000040000A08000), -(18548,0,0x0000041202F8A090), -(18548,1,0x0000001202582090), -(18548,2,0x0000040000A08000), -(18549,0,0x0000041202F8A090), -(18549,1,0x0000001202582090), -(18549,2,0x0000040000A08000), -(18550,0,0x0000041202F8A090), -(18550,1,0x0000001202582090), -(18550,2,0x0000040000A08000), -(18703,1,0x0000000001000000), -(18704,1,0x0000000001000000), -(18731,0,0x0000000010000000), -(18743,0,0x0000000010000000), -(18744,0,0x0000000010000000), -(18748,0,0x0000000008000000), -(18749,0,0x0000000008000000), -(18750,0,0x0000000008000000), -(18767,1,0x0000000000020000), -(18768,1,0x0000000000020000), -(18821,0,0x0000000000000800), -(18821,1,0x0000000000000800), -(18821,2,0x0000000000000800), -(18822,0,0x0000000000000800), -(18822,1,0x0000000000000800), -(18822,2,0x0000000000000800), -(18827,0,0x0000000000000400), -(18829,0,0x0000000000000400), -(19239,0,0x0000000000000018), -(19239,1,0x0000000000000004), -(19245,0,0x0000000000000018), -(19245,1,0x0000200000000004), -(19416,0,0x000210810007FA00), -(19417,0,0x000210810007FA00), -(19418,0,0x000210810007FA00), -(19419,0,0x000210810007FA00), -(19420,0,0x000210810007FA00), -(19461,0,0x0000000000003000), -(19461,1,0x0000000000003000), -(19462,0,0x0000000000003000), -(19462,1,0x0000000000003000), -(19464,0,0x0000010000004000), -(19464,1,0x0000008000000000), -(19464,2,0x000011800000C000), -(19465,0,0x0000010000004000), -(19465,1,0x0000008000000000), -(19465,2,0x000011800000C000), -(19466,0,0x0000010000004000), -(19466,1,0x0000008000000000), -(19466,2,0x000011800000C000), -(19467,0,0x0000010000004000), -(19467,1,0x0000008000000000), -(19467,2,0x000011800000C000), -(19468,0,0x0000010000004000), -(19468,1,0x0000008000000000), -(19468,2,0x000011800000C000), -(19485,0,0x0000000100061801), -(19487,0,0x0000000100061801), -(19488,0,0x0000000100061801), -(19489,0,0x0000000100061801), -(19490,0,0x0000000100061801), -(19498,0,0x000210810007FA01), -(19499,0,0x000210810007FA01), -(19500,0,0x000210810007FA01), -(19549,0,0x0000000000080000), -(19550,0,0x0000000000080000), -(19551,0,0x0000000000080000), -(19552,0,0x0000000000100000), -(19552,1,0x0000020000000000), -(19553,0,0x0000000000100000), -(19553,1,0x0000020000000000), -(19554,0,0x0000000000100000), -(19554,1,0x0000020000000000), -(19555,0,0x0000000000100000), -(19555,1,0x0000020000000000), -(19556,0,0x0000000000100000), -(19556,1,0x0000020000000000), -(19559,0,0x0000000000200000), -(19560,0,0x0000000000200000), -(19572,1,0x0000000000800000), -(19573,1,0x0000000000800000), -(19583,0,0x0000000008000000), -(19584,0,0x0000000008000000), -(19585,0,0x0000000008000000), -(19586,0,0x0000000008000000), -(19587,0,0x0000000008000000), -(19590,0,0x0000000020000000), -(19592,0,0x0000000020000000), -(19598,0,0x0000000040000000), -(19599,0,0x0000000040000000), -(19600,0,0x0000000040000000), -(19601,0,0x0000000040000000), -(19602,0,0x0000000040000000), -(19609,0,0x0000000004000000), -(19610,0,0x0000000004000000), -(19612,0,0x0000000004000000), -(20101,0,0x000004000A000200), -(20102,0,0x000004000A000200), -(20103,0,0x000004000A000200), -(20104,0,0x000004000A000200), -(20105,0,0x000004000A000200), -(20138,0,0x0000000000000040), -(20139,0,0x0000000000000040), -(20140,0,0x0000000000000040), -(20141,0,0x0000000000000040), -(20142,0,0x0000000000000040), -(20174,0,0x0000000000000080), -(20174,1,0x0000000000000010), -(20175,0,0x0000000000000080), -(20175,1,0x0000000000000010), -(20216,0,0x00010000C0200000), -(20224,0,0x0000000008000400), -(20225,0,0x0000000008000400), -(20237,0,0x00000000C0000000), -(20238,0,0x00000000C0000000), -(20239,0,0x00000000C0000000), -(20249,0,0x0000000040000000), -(20250,0,0x0000000040000000), -(20251,0,0x0000000040000000), -(20254,0,0x0000000000020000), -(20254,1,0x0000000000020000), -(20254,2,0x0000000000020000), -(20255,0,0x0000000000020000), -(20255,1,0x0000000000020000), -(20255,2,0x0000000000020000), -(20256,0,0x0000000000020000), -(20256,1,0x0000000000020000), -(20256,2,0x0000000000020000), -(20330,0,0x0000000008000400), -(20331,0,0x0000000008000400), -(20332,0,0x0000000008000400), -(20335,0,0x0000000020000000), -(20336,0,0x0000000020000000), -(20337,0,0x0000000020000000), -(20359,0,0x0000000080000000), -(20360,0,0x0000000080000000), -(20361,0,0x0000000080000000), -(20468,1,0x0000000000000001), -(20469,1,0x0000000000000001), -(20470,1,0x0000000000000001), -(20575,0,0x0000000004000000), -(20575,1,0x0000000004000000), -(20576,0,0x0000000002000000), -(21873,0,0x0000E000E2000000), -(21881,0,0x000000000001E000), -(21887,0,0x0000036C2A764EEF), -(21895,0,0x000000000403E000), -(21899,0,0x0000000000000100), -(21942,1,0x0000000008000000), -(22008,0,0x0000000021400035), -(23025,0,0x0000000000010000), -(23047,0,0x0000040000000000), -(23047,1,0x0000040000000000), -(23158,0,0x0000000000000200), -(23300,0,0x0000000020000000), -(23555,0,0x000010C0000003E5), -(23561,0,0x0000000000004000), -(23566,0,0x0000000000001000), -(23724,0,0x0000E000E2000000), -(23726,0,0x0000000000002000), -(23726,1,0x0000000000010000), -(24348,0,0x0000000000200000), -(24429,0,0x0000000000004000), -(24431,0,0x0000000400000000), -(24460,0,0x0000000010000180), -(24469,0,0x0000000001000000), -(24499,0,0x0000000000000400), -(24542,1,0x00000000000000F0), -(24546,1,0x0000000400041E00), -(24691,0,0x0000000000003000), -(24691,1,0x0000000000003000), -(24943,0,0x00000010000000F0), -(24943,1,0x00000010000000F0), -(24944,0,0x00000010000000F0), -(24944,1,0x00000010000000F0), -(24945,0,0x00000010000000F0), -(24945,1,0x00000010000000F0), -(24946,0,0x00000010000000F0), -(24946,1,0x00000010000000F0), -(26106,0,0x0000000010000000), -(26109,0,0x00000080000F0000), -(26112,0,0x0000000000000020), -(26118,0,0x0000000004000000), -(26118,1,0x0000000004000000), -(26174,0,0x0000000000000020), -(27789,1,0x0000000010400200), -(27790,1,0x0000000010400200), -(27828,0,0x0000049440963E90), -(27846,0,0x0000000000000020), -(27850,0,0x0000000000000040), -(27851,0,0x0000000000001000), -(28088,0,0x000000000001E000), -(28107,0,0x0000000000040000), -(28539,0,0x0000000000001000), -(28682,0,0x0000004008C20017), -(28743,0,0x00000000000000F0), -(28746,1,0x0000000100000406), -(28751,0,0x0000000000021000), -(28755,0,0x0000000000000020), -(28763,0,0x0000000004000000), -(28774,0,0x0000000000008000), -(28775,0,0x0000000100000000), -(28787,0,0x0000000000001000), -(28807,0,0x0000000000000040), -(28808,0,0x0000000411041E40), -(28811,0,0x0000000002020006), -(28814,0,0x0000000000020000), -(28815,0,0x0000000002000006), -(28818,0,0x0000000020081018), -(28821,0,0x0000000000000400), -(28829,0,0x0000000000000002), -(28831,0,0x0000000000000001), -(28842,0,0x0000000100004440), -(28843,0,0x0000000000088000), -(28844,0,0x0000000000000400), -(28852,0,0x0000000000000200), -(28852,1,0x0000000020000000), -(28855,0,0x0000000000000800), -(28855,1,0x0010000000000000), -(28999,0,0x0000000000000003), -(29000,0,0x0000000000000003), -(29005,0,0x0000000090100003), -(29063,0,0x00000000000009C3), -(29079,0,0x0000000000400000), -(29079,1,0x0000000001000000), -(29079,2,0x0000000000800000), -(29080,0,0x0000000000400000), -(29080,1,0x0000000001000000), -(29080,2,0x0000000000800000), -(29171,0,0x0000000000004000), -(29187,0,0x00000000000001C0), -(29187,1,0x0004103000340750), -(29189,0,0x00000000000001C0), -(29189,1,0x0004103000340750), -(29191,0,0x00000000000001C0), -(29191,1,0x0004103000340750), -(29202,0,0x0000000000000040), -(29205,0,0x0000000000000040), -(29206,0,0x0000000000000040), -(29438,0,0x0000000000D000D7), -(29439,0,0x0000000000D000D7), -(29440,0,0x0000000000D000D7), -(29721,0,0x0000000400000000), -(29723,0,0x0000000800002010), -(29723,1,0x0000000800002010), -(29724,0,0x0000000800002010), -(29724,1,0x0000000800002010), -(29725,0,0x0000000800002010), -(29725,1,0x0000000800002010), -(29759,1,0x0000075D6E6ECEEF), -(29760,1,0x0000075D6E6ECEEF), -(29761,1,0x0000075D6E6ECEEF), -(29762,1,0x0000075D6E6ECEEF), -(29763,1,0x0000075D6E6ECEEF), -(29776,0,0x0000000400000000), -(29787,0,0x0000036C2A764EEF), -(29790,0,0x0000036C2A764EEF), -(29792,0,0x0000036C2A764EEF), -(29836,0,0x0000001000000020), -(29859,0,0x0000001000000020), -(29888,0,0x0000000040000000), -(29889,0,0x0000000040000000), -(29976,0,0x0000000021400035), -(30049,0,0x0000000000080000), -(30051,0,0x0000000000080000), -(30052,0,0x0000000000080000), -(30054,0,0x0000000800000000), -(30057,0,0x0000000800000000), -(30060,0,0x0000001000000402), -(30060,1,0x0000001000000402), -(30060,2,0x0000871B804CC41A), -(30061,0,0x0000001000000402), -(30061,1,0x0000001000000402), -(30061,2,0x0000871B804CC41A), -(30062,0,0x0000001000000402), -(30062,1,0x0000001000000402), -(30062,2,0x0000871B804CC41A), -(30063,0,0x0000001000000402), -(30063,1,0x0000001000000402), -(30063,2,0x0000871B804CC41A), -(30064,0,0x0000001000000402), -(30064,1,0x0000001000000402), -(30064,2,0x0000871B804CC41A), -(30085,0,0x0000071B804CC41A), -(30085,1,0x0000000000000400), -(30085,2,0x0000000000000002), -(30086,0,0x0000071B804CC41A), -(30086,1,0x0000000000000400), -(30086,2,0x0000000000000002), -(30017,0,0x0000000000000000), -(30143,0,0x0000002000000000), -(30144,0,0x0000002000000000), -(30145,0,0x0000002000000000), -(30242,0,0x0000200000000000), -(30245,0,0x0000200000000000), -(30246,0,0x0000200000000000), -(30247,0,0x0000200000000000), -(30248,0,0x0000200000000000), -(30251,0,0x000010C000000125), -(30256,0,0x000010C000000125), -(30280,0,0x0000000000000000), -(30288,0,0x0000004000000001), -(30289,0,0x0000004000000001), -(30290,0,0x0000004000000001), -(30291,0,0x0000004000000001), -(30292,0,0x0000004000000001), -(30319,1,0x0000400000000000), -(30320,1,0x0000400000000000), -(30321,1,0x0000400000000000), -(30326,0,0x0000000000040010), -(30327,0,0x0000000000040010), -(30328,0,0x0000000000040010), -(30812,0,0x00000C78B018141B), -(30813,0,0x00000C78B018141B), -(30814,0,0x00000C78B018141B), -(30872,0,0x0000000000000100), -(30873,0,0x0000000000000100), -(30892,0,0x0000000008000000), -(30893,0,0x0000000008000000), -(31216,1,0x0000000002000004), -(31217,1,0x0000000002000004), -(31218,1,0x0000000002000004), -(31219,1,0x0000000002000004), -(31220,1,0x0000000002000004), -(31226,0,0x000000000001E000), -(31227,0,0x000000000001E000), -(31234,0,0x000001002612030F), -(31234,1,0x0000000000100100), -(31235,0,0x000001002612030F), -(31235,1,0x0000000000100100), -(31236,0,0x000001002612030F), -(31236,1,0x0000000000100100), -(31237,0,0x000001002612030F), -(31237,1,0x0000000000100100), -(31238,0,0x000001002612030F), -(31238,1,0x0000000000100100), -(31571,0,0x0000000200000000), -(31572,0,0x0000000200000000), -(31573,0,0x0000000200000000), -(31579,0,0x0000000000200000), -(31579,1,0x0000000000000800), -(31582,0,0x0000000000200000), -(31582,1,0x0000000000000800), -(31583,0,0x0000000000200000), -(31583,1,0x0000000000000800), -(31656,0,0x0000000000000001), -(31657,0,0x0000000000000001), -(31658,0,0x0000000000000001), -(31659,0,0x0000000000000001), -(31660,0,0x0000000000000001), -(31670,0,0x0000000500000200), -(31672,0,0x0000000500000200), -(31682,0,0x0000000000000020), -(31682,1,0x0000000000000020), -(31683,0,0x0000000000000020), -(31683,1,0x0000000000000020), -(31684,0,0x0000000000000020), -(31684,1,0x0000000000000020), -(31685,0,0x0000000000000020), -(31685,1,0x0000000000000020), -(31686,0,0x0000000000000020), -(31686,1,0x0000000000000020), -(31821,0,0x0000000004020048), -(31825,0,0x0000000000001020), -(31825,1,0x0000000200000000), -(31826,0,0x0000000000001020), -(31826,1,0x0000000200000000), -(31834,0,0x0000000080000000), -(31844,1,0x000005401A00038C), -(31845,1,0x000005401A00038C), -(31848,0,0x0000000000400000), -(31848,1,0x0000000000400000), -(31849,0,0x0000000000400000), -(31849,1,0x0000000000400000), -(31869,0,0x0000002000000000), -(31870,0,0x0000002000000000), -(31879,0,0x0000000800000400), -(31880,0,0x0000000800000400), -(31881,0,0x0000000800000400), -(31882,0,0x0000000800000400), -(31883,0,0x0000000800000400), -(32043,1,0x000004000A000000), -(32203,1,0x0001100001C22000), -(32381,0,0x0000000000000002), -(32382,0,0x0000000000000002), -(32383,0,0x0000000000000002), -(32412,0,0x0000000000000400), -(32477,0,0x0000020000000000), -(32483,0,0x0000020000000000), -(32484,0,0x0000020000000000), -(32601,1,0x0000000020800008), -(32743,0,0x0000000000000800), -(32973,0,0x0000000090100000), -(33018,0,0x0000001000000000), -(33020,0,0x0000000000000400), -(33063,0,0x0000040000000000), -(33066,0,0x0000000000000002), -(33151,0,0x0000000000000080), -(33151,1,0x0000000000000080), -(33151,2,0x0000000000000080), -(33158,0,0x0000000000001000), -(33158,1,0x0000000000000800), -(33159,0,0x0000000000001000), -(33159,1,0x0000000000000800), -(33160,0,0x0000000000001000), -(33160,1,0x0000000000000800), -(33161,0,0x0000000000001000), -(33161,1,0x0000000000000800), -(33162,0,0x0000000000001000), -(33162,1,0x0000000000000800), -(33167,0,0x0000008100000000), -(33171,0,0x0000008100000000), -(33172,0,0x0000008100000000), -(33174,0,0x0000000000000020), -(33174,1,0x0000000000000020), -(33182,0,0x0000000000000020), -(33182,1,0x0000000000000020), -(33186,0,0x0000008000000000), -(33186,1,0x0000008000002080), -(33190,0,0x0000008000000000), -(33190,1,0x0000008000002080), -(33213,0,0x0000000000822000), -(33214,0,0x0000000000822000), -(33215,0,0x0000000000822000), -(33221,0,0x0000000200002000), -(33222,0,0x0000000200002000), -(33223,0,0x0000000200002000), -(33224,0,0x0000000200002000), -(33225,0,0x0000000200002000), -(33333,0,0x0000000020000000), -(33421,0,0x0000000200000000), -(33557,0,0x0000000000000200), -(33557,1,0x0000000020000000), -(33565,0,0x0000000000001000), -(33600,0,0x0000000000000400), -(33600,1,0x0000000000000400), -(33601,0,0x0000000000000400), -(33601,1,0x0000000000000400), -(33602,0,0x0000000000000400), -(33602,1,0x0000000000000400), -(33603,0,0x0000000000000004), -(33603,1,0x0000000000000001), -(33604,0,0x0000000000000004), -(33604,1,0x0000000000000001), -(33605,0,0x0000000000000004), -(33605,1,0x0000000000000001), -(33606,0,0x0000000000000004), -(33606,1,0x0000000000000001), -(33607,0,0x0000000000000004), -(33607,1,0x0000000000000001), -(33693,0,0x0000000000008000), -(33696,0,0x0000000000000001), -(33713,0,0x0000000200000000), -(33714,0,0x0000000200000000), -(33830,0,0x0000002000000000), -(33830,1,0x0000002000000000), -(33877,0,0x0000000000000002), -(33879,0,0x0000000000000020), -(33880,0,0x0000000000000020), -(33886,0,0x00000010000000D0), -(33887,0,0x00000010000000D0), -(33888,0,0x00000010000000D0), -(33889,0,0x00000010000000D0), -(33890,0,0x00000010000000D0), -(34128,0,0x0000001000000000), -(34129,0,0x0000000040000000), -(34129,1,0x0000000040000000), -(34131,0,0x0000000000000080), -(34131,1,0x0000000000000080), -(34253,0,0x0000010000000000), -(34297,0,0x0000080000000000), -(34300,0,0x0000080000000000), -(34318,0,0x0000000000000400), -(34318,1,0x0000002000000000), -(34323,0,0x0000008000800000), -(34453,1,0x0000000400000000), -(34454,1,0x0000000400000000), -(34455,0,0x0000002000000000), -(34455,1,0x0000004000000000), -(34459,0,0x0000002000000000), -(34459,1,0x0000004000000000), -(34460,0,0x0000002000000000), -(34460,1,0x0000004000000000), -(34462,1,0x0000000800000000), -(34464,1,0x0000000800000000), -(34465,1,0x0000000800000000), -(34466,1,0x0000001000000000), -(34467,1,0x0000001000000000), -(34468,1,0x0000001000000000), -(34469,1,0x0000001000000000), -(34470,1,0x0000001000000000), -(34491,0,0x00004000000000C2), -(34491,1,0x0000000000000080), -(34492,0,0x00004000000000C2), -(34492,1,0x0000000000000080), -(34493,0,0x00004000000000C2), -(34493,1,0x0000000000000080), -(34520,1,0x0000000000000000), -(34754,0,0x0000000400001800), -(34936,0,0x0000004000000001), -(34948,1,0x0000000000000020), -(34949,1,0x0000000000000020), -(35029,1,0x0000080000000000), -(35030,1,0x0000080000000000), -(35098,0,0x0000000000020801), -(35099,0,0x0000000000020801), -(35104,0,0x0000000000001000), -(35104,1,0x0000000000002000), -(35110,0,0x0000000000001000), -(35110,1,0x0000000000002000), -(35111,0,0x0000000000001000), -(35111,1,0x0000000000002000), -(35363,0,0x0000000000000005), -(35364,0,0x0000000000000005), -(35396,1,0x000004000A000000), -(35397,1,0x000004000A000000), -(35446,0,0x0000000002000000), -(35446,1,0x0000000002000000), -(35448,0,0x0000000002000000), -(35448,1,0x0000000002000000), -(35449,0,0x0000000002000000), -(35449,1,0x0000000002000000), -(35450,0,0x0000000002000000), -(35450,1,0x0000000002000000), -(35451,0,0x0000000002000000), -(35451,1,0x0000000002000000), -(35578,0,0x0000000028E212F7), -(35581,0,0x0000000028E212F7), -(36032,0,0x0000000020000000), -(36032,1,0x0000000020000000), -(36413,0,0x0000000000000001), -(36563,1,0x0000000000000204), -(36563,2,0x0000000000000100), -(37166,0,0x0000000000800000), -(37167,0,0x0000000000040000), -(37171,0,0x00000009003E0000), -(37180,0,0x0000000000000020), -(37181,0,0x0000000400000000), -(37183,0,0x0000010000000000), -(37184,0,0x0000040008000000), -(37184,1,0x0000040008000000), -(37185,0,0x0000004000000000), -(37186,0,0x0000000020000000), -(37187,0,0x0000020000000000), -(37190,0,0x0000000000000008), -(37191,0,0x0000004000000000), -(37194,0,0x0000000000800000), -(37207,0,0x0000000000000002), -(37209,0,0x0000000000000400), -(37209,1,0x0000002000000000), -(37210,0,0x0000000000004000), -(37211,0,0x0000008000000000), -(37212,0,0x0000010000000000), -(37223,0,0x0000000000010000), -(37224,0,0x0000001000000000), -(37225,0,0x0000000000000080), -(37234,0,0x0000000000000080), -(37240,0,0x0000000000000080), -(37241,0,0x0000020000000000), -(37286,0,0x0000000000000010), -(37287,0,0x0000E000E2000000), -(37292,0,0x0008000000000000), -(37297,0,0x0000100000000000), -(37313,0,0x0000000000000040), -(37314,0,0x0000001000000000), -(37316,0,0x0000000000000040), -(37325,0,0x0000000000000040), -(37333,0,0x0000000000008000), -(37333,1,0x0000010000000000), -(37376,0,0x0000001000000000), -(37380,0,0x0000000000000006), -(37423,0,0x0000000000000004), -(37424,0,0x0000000000008000), -(37438,0,0x0000000000000021), -(37439,0,0x0000002000000000), -(37439,1,0x0000004000000000), -(37439,2,0x0000008000000000), -(37441,0,0x0000000020000000), -(37441,1,0x0000000020000000), -(37447,0,0x0000010000000000), -(37481,0,0x0000000000000080), -(37484,0,0x0000000000000100), -(37485,0,0x0000000000001000), -(37505,0,0x0000000100000000), -(37507,0,0x0000000000000800), -(37508,0,0x0000000100061800), -(37508,1,0x0000000000000000), -(37512,0,0x00000080000F0000), -(37513,0,0x0000000000000001), -(37517,0,0x0000014D2A600CEF), -(37518,0,0x0000000400000000), -(37522,0,0x0000000000001000), -(37535,0,0x0000000002000000), -(37536,0,0x0000000000010000), -(37556,0,0x0000000400000000), -(37564,0,0x0000000000000200), -(37565,0,0x0000000000001000), -(37570,1,0x0000010000000000), -(37571,0,0x0000000000000080), -(37571,1,0x0000000000800000), -(37593,0,0x0000000000000040), -(37706,0,0x0000000411041E40), -(37721,0,0x00000010000000F0), -(37722,0,0x00000000000001C0), -(37723,0,0x00000000C0000000), -(37736,0,0x0000040000000000), -(37736,1,0x0000004000000000), -(37737,0,0x0000000000000040), -(37738,0,0x0000000000000040), -(37739,0,0x0000000080000000), -(37740,0,0x0000000000000001), -(37742,0,0x0000004000000000), -(37760,0,0x0000000000000001), -(37762,0,0x0000001000000000), -(37763,0,0x0000800000000000), -(37878,0,0x00000010000000F0), -(37879,0,0x00000000C0000000), -(37880,0,0x0000000411041E40), -(37881,0,0x00000000000001C0), -(38314,0,0x0000E000E2000000), -(38321,0,0x0000000000000020), -(38322,0,0x0000000000000100), -(38388,0,0x0000000000040000), -(38389,0,0x0000000E00000006), -(38392,0,0x0000000100000000), -(38393,0,0x0000000000000001), -(38396,0,0x0000000004000000), -(38397,0,0x0000000000000821), -(38398,0,0x0000000020000000), -(38399,0,0x0000000002000000), -(38407,0,0x0000000100000000), -(38408,0,0x0000008000000000), -(38410,0,0x0000000000000200), -(38411,0,0x0000000000001000), -(38412,0,0x0000000000002000), -(38413,0,0x0000000000008000), -(38414,0,0x0000000000000002), -(38415,0,0x0000000000000004), -(38416,0,0x0010000000800000), -(38416,1,0x0010000000800000), -(38417,0,0x0000000200000000), -(38420,0,0x0000000000000020), -(38421,0,0x0000100000000000), -(38422,0,0x0000000000000020), -(38424,0,0x0000008000000000), -(38425,0,0x0000000040000000), -(38426,0,0x0000000080000000), -(38429,0,0x0000000090100000), -(38434,0,0x0000000000000100), -(38435,0,0x0000000000000080), -(38436,0,0x0000000000000001), -(38447,0,0x0000040000000000), -(38447,1,0x0000004000000000), -(38466,0,0x0008000000000000), -(38499,0,0x0000008000000000), -(38501,0,0x0000000000000080), -(38522,0,0x0000000040000000), -(39805,0,0x0000000000000003), -(39805,1,0x0000000000000003), -(39926,1,0x0000080000000000), -(39926,2,0x0000200000000000), -(39950,0,0x0000000000000040), -(40389,0,0x0000800000000000), -(40460,0,0x00000009003E0000), -(41021,0,0x0000004000000000), -(41021,1,0x0000004000000000), -(41026,0,0x0000004000000000), -(41026,1,0x0000004000000000), -(41037,0,0x0000044000000000), -(41042,0,0x0000000000800000), -(42367,0,0x0000001000000000), -(43339,0,0x0000000090100000), -(43725,0,0x0000001000000000), -(43736,0,0x0000000000000010), -(43743,1,0x0000000008000400), -(43752,0,0x0000000000000100), -(43837,0,0x0000000080000000), -(43840,0,0x0000044000000000), -(43841,0,0x0000000000000002), -(43842,0,0x0000044000000000), -(43843,0,0x0000044000000000), -(43844,0,0x0000000000000002), -(43845,0,0x0000000000000002), -(43850,0,0x0000000000800000), -(43851,0,0x0000000000800000), -(43852,0,0x0000000000800000), -(43854,0,0x0000004000000000), -(43855,0,0x0000004000000000), -(43856,0,0x0000004000000000), -(43857,0,0x0000001000000000), -(43858,0,0x0000001000000000), -(43859,0,0x0000001000000000), -(43860,0,0x0000000090100000), -(43861,0,0x0000000090100000), -(43862,0,0x0000000090100000), -(44292,0,0x0000000000001000), -(44293,0,0x0000000000000200), -(44295,0,0x0000000090100000), -(44296,0,0x0000000000000001), -(44297,0,0x0000000000010000), -(44299,0,0x0000000000040000), -(44300,0,0x0000800000000000), -(44301,0,0x0000000001000000), -(44302,0,0x0000000001000000), -(44373,0,0x0000000000000000), -(46088,0,0x0000044000000000), -(46090,0,0x0000000000000002), -(46091,0,0x0000000000800000), -(46095,0,0x0000004000000000), -(46096,0,0x0000001000000000), -(46097,0,0x0000000090100000), -(46100,0,0x0000001000000000), -(46833,0,0x0000000000000004), -(46834,0,0x0000000000000040), -(46851,0,0x0001000000000000); - /*!40000 ALTER TABLE `spell_affect` ENABLE KEYS */; UNLOCK TABLES; diff --git a/sql/updates/06360_characters_characters.sql b/sql/updates/0.12/06360_characters_characters.sql similarity index 100% rename from sql/updates/06360_characters_characters.sql rename to sql/updates/0.12/06360_characters_characters.sql diff --git a/sql/updates/06360_characters_corpse.sql b/sql/updates/0.12/06360_characters_corpse.sql similarity index 100% rename from sql/updates/06360_characters_corpse.sql rename to sql/updates/0.12/06360_characters_corpse.sql diff --git a/sql/updates/06362_characters.sql b/sql/updates/0.12/06362_characters.sql similarity index 100% rename from sql/updates/06362_characters.sql rename to sql/updates/0.12/06362_characters.sql diff --git a/sql/updates/06362_mangos_instance_template.sql b/sql/updates/0.12/06362_mangos_instance_template.sql similarity index 100% rename from sql/updates/06362_mangos_instance_template.sql rename to sql/updates/0.12/06362_mangos_instance_template.sql diff --git a/sql/updates/06367_mangos_spell_proc_event.sql b/sql/updates/0.12/06367_mangos_spell_proc_event.sql similarity index 100% rename from sql/updates/06367_mangos_spell_proc_event.sql rename to sql/updates/0.12/06367_mangos_spell_proc_event.sql diff --git a/sql/updates/06369_mangos_spell_affect.sql b/sql/updates/0.12/06369_mangos_spell_affect.sql similarity index 100% rename from sql/updates/06369_mangos_spell_affect.sql rename to sql/updates/0.12/06369_mangos_spell_affect.sql diff --git a/sql/updates/06370_mangos_spell_affect.sql b/sql/updates/0.12/06370_mangos_spell_affect.sql similarity index 100% rename from sql/updates/06370_mangos_spell_affect.sql rename to sql/updates/0.12/06370_mangos_spell_affect.sql diff --git a/sql/updates/06381_mangos_command.sql b/sql/updates/0.12/06381_mangos_command.sql similarity index 100% rename from sql/updates/06381_mangos_command.sql rename to sql/updates/0.12/06381_mangos_command.sql diff --git a/sql/updates/06387_characters_character_ticket.sql b/sql/updates/0.12/06387_characters_character_ticket.sql similarity index 100% rename from sql/updates/06387_characters_character_ticket.sql rename to sql/updates/0.12/06387_characters_character_ticket.sql diff --git a/sql/updates/06387_mangos_mangos_string.sql b/sql/updates/0.12/06387_mangos_mangos_string.sql similarity index 100% rename from sql/updates/06387_mangos_mangos_string.sql rename to sql/updates/0.12/06387_mangos_mangos_string.sql diff --git a/sql/updates/06397_mangos_creature_template.sql b/sql/updates/0.12/06397_mangos_creature_template.sql similarity index 100% rename from sql/updates/06397_mangos_creature_template.sql rename to sql/updates/0.12/06397_mangos_creature_template.sql diff --git a/sql/updates/06398_mangos_creature_template.sql b/sql/updates/0.12/06398_mangos_creature_template.sql similarity index 100% rename from sql/updates/06398_mangos_creature_template.sql rename to sql/updates/0.12/06398_mangos_creature_template.sql diff --git a/sql/updates/06412_characters_declinedname.sql b/sql/updates/0.12/06412_characters_declinedname.sql similarity index 100% rename from sql/updates/06412_characters_declinedname.sql rename to sql/updates/0.12/06412_characters_declinedname.sql diff --git a/sql/updates/06426_mangos_locales.sql b/sql/updates/0.12/06426_mangos_locales.sql similarity index 100% rename from sql/updates/06426_mangos_locales.sql rename to sql/updates/0.12/06426_mangos_locales.sql diff --git a/sql/updates/06426_realmd_localization.sql b/sql/updates/0.12/06426_realmd_localization.sql similarity index 100% rename from sql/updates/06426_realmd_localization.sql rename to sql/updates/0.12/06426_realmd_localization.sql diff --git a/sql/updates/06431_mangos_mangos_string.sql b/sql/updates/0.12/06431_mangos_mangos_string.sql similarity index 100% rename from sql/updates/06431_mangos_mangos_string.sql rename to sql/updates/0.12/06431_mangos_mangos_string.sql diff --git a/sql/updates/06439_mangos_command.sql b/sql/updates/0.12/06439_mangos_command.sql similarity index 100% rename from sql/updates/06439_mangos_command.sql rename to sql/updates/0.12/06439_mangos_command.sql diff --git a/sql/updates/06456_mangos_command.sql b/sql/updates/0.12/06456_mangos_command.sql similarity index 100% rename from sql/updates/06456_mangos_command.sql rename to sql/updates/0.12/06456_mangos_command.sql diff --git a/sql/updates/06472_realmd_account.sql b/sql/updates/0.12/06472_realmd_account.sql similarity index 100% rename from sql/updates/06472_realmd_account.sql rename to sql/updates/0.12/06472_realmd_account.sql diff --git a/sql/updates/06492_mangos_spell_chain.sql b/sql/updates/0.12/06492_mangos_spell_chain.sql similarity index 100% rename from sql/updates/06492_mangos_spell_chain.sql rename to sql/updates/0.12/06492_mangos_spell_chain.sql diff --git a/sql/updates/06496_mangos_spell_pet_auras.sql b/sql/updates/0.12/06496_mangos_spell_pet_auras.sql similarity index 100% rename from sql/updates/06496_mangos_spell_pet_auras.sql rename to sql/updates/0.12/06496_mangos_spell_pet_auras.sql diff --git a/sql/updates/06506_mangos_spell_proc_event.sql b/sql/updates/0.12/06506_mangos_spell_proc_event.sql similarity index 100% rename from sql/updates/06506_mangos_spell_proc_event.sql rename to sql/updates/0.12/06506_mangos_spell_proc_event.sql diff --git a/sql/updates/06509_mangos_command.sql b/sql/updates/0.12/06509_mangos_command.sql similarity index 100% rename from sql/updates/06509_mangos_command.sql rename to sql/updates/0.12/06509_mangos_command.sql diff --git a/sql/updates/06509_mangos_mangos_string.sql b/sql/updates/0.12/06509_mangos_mangos_string.sql similarity index 100% rename from sql/updates/06509_mangos_mangos_string.sql rename to sql/updates/0.12/06509_mangos_mangos_string.sql diff --git a/sql/updates/06513_mangos_command.sql b/sql/updates/0.12/06513_mangos_command.sql similarity index 100% rename from sql/updates/06513_mangos_command.sql rename to sql/updates/0.12/06513_mangos_command.sql diff --git a/sql/updates/06515_mangos_spell_proc_event.sql b/sql/updates/0.12/06515_mangos_spell_proc_event.sql similarity index 100% rename from sql/updates/06515_mangos_spell_proc_event.sql rename to sql/updates/0.12/06515_mangos_spell_proc_event.sql diff --git a/sql/updates/06521_mangos_spell_proc_event.sql b/sql/updates/0.12/06521_mangos_spell_proc_event.sql similarity index 100% rename from sql/updates/06521_mangos_spell_proc_event.sql rename to sql/updates/0.12/06521_mangos_spell_proc_event.sql diff --git a/sql/updates/06523_mangos_spell_proc_event.sql b/sql/updates/0.12/06523_mangos_spell_proc_event.sql similarity index 100% rename from sql/updates/06523_mangos_spell_proc_event.sql rename to sql/updates/0.12/06523_mangos_spell_proc_event.sql diff --git a/sql/updates/06528_mangos_spell_affect.sql b/sql/updates/0.12/06528_mangos_spell_affect.sql similarity index 100% rename from sql/updates/06528_mangos_spell_affect.sql rename to sql/updates/0.12/06528_mangos_spell_affect.sql diff --git a/sql/updates/06528_mangos_spell_proc_event.sql b/sql/updates/0.12/06528_mangos_spell_proc_event.sql similarity index 100% rename from sql/updates/06528_mangos_spell_proc_event.sql rename to sql/updates/0.12/06528_mangos_spell_proc_event.sql diff --git a/sql/updates/06538_mangos_spell_proc_event.sql b/sql/updates/0.12/06538_mangos_spell_proc_event.sql similarity index 100% rename from sql/updates/06538_mangos_spell_proc_event.sql rename to sql/updates/0.12/06538_mangos_spell_proc_event.sql diff --git a/sql/updates/06540_mangos_spell_proc_event.sql b/sql/updates/0.12/06540_mangos_spell_proc_event.sql similarity index 100% rename from sql/updates/06540_mangos_spell_proc_event.sql rename to sql/updates/0.12/06540_mangos_spell_proc_event.sql diff --git a/sql/updates/06544_mangos_spell_proc_event.sql b/sql/updates/0.12/06544_mangos_spell_proc_event.sql similarity index 100% rename from sql/updates/06544_mangos_spell_proc_event.sql rename to sql/updates/0.12/06544_mangos_spell_proc_event.sql diff --git a/sql/updates/06545_mangos_command.sql b/sql/updates/0.12/06545_mangos_command.sql similarity index 100% rename from sql/updates/06545_mangos_command.sql rename to sql/updates/0.12/06545_mangos_command.sql diff --git a/sql/updates/06557_mangos_command.sql b/sql/updates/0.12/06557_mangos_command.sql similarity index 100% rename from sql/updates/06557_mangos_command.sql rename to sql/updates/0.12/06557_mangos_command.sql diff --git a/sql/updates/06574_mangos_spell_proc_event.sql b/sql/updates/0.12/06574_mangos_spell_proc_event.sql similarity index 100% rename from sql/updates/06574_mangos_spell_proc_event.sql rename to sql/updates/0.12/06574_mangos_spell_proc_event.sql diff --git a/sql/updates/06585_mangos_command.sql b/sql/updates/0.12/06585_mangos_command.sql similarity index 100% rename from sql/updates/06585_mangos_command.sql rename to sql/updates/0.12/06585_mangos_command.sql diff --git a/sql/updates/06588_mangos_spell_proc_event.sql b/sql/updates/0.12/06588_mangos_spell_proc_event.sql similarity index 100% rename from sql/updates/06588_mangos_spell_proc_event.sql rename to sql/updates/0.12/06588_mangos_spell_proc_event.sql diff --git a/sql/updates/06596_characters_arena_team.sql b/sql/updates/0.12/06596_characters_arena_team.sql similarity index 100% rename from sql/updates/06596_characters_arena_team.sql rename to sql/updates/0.12/06596_characters_arena_team.sql diff --git a/sql/updates/06598_character_spell.sql b/sql/updates/0.12/06598_character_spell.sql similarity index 100% rename from sql/updates/06598_character_spell.sql rename to sql/updates/0.12/06598_character_spell.sql diff --git a/sql/updates/06609_mangos_mangos_string.sql b/sql/updates/0.12/06609_mangos_mangos_string.sql similarity index 100% rename from sql/updates/06609_mangos_mangos_string.sql rename to sql/updates/0.12/06609_mangos_mangos_string.sql diff --git a/sql/updates/06613_mangos_mangos_string.sql b/sql/updates/0.12/06613_mangos_mangos_string.sql similarity index 100% rename from sql/updates/06613_mangos_mangos_string.sql rename to sql/updates/0.12/06613_mangos_mangos_string.sql diff --git a/sql/updates/06627_mangos_creature_movement.sql b/sql/updates/0.12/06627_mangos_creature_movement.sql similarity index 100% rename from sql/updates/06627_mangos_creature_movement.sql rename to sql/updates/0.12/06627_mangos_creature_movement.sql diff --git a/sql/updates/06640_mangos_reference_loot_template.sql b/sql/updates/0.12/06640_mangos_reference_loot_template.sql similarity index 100% rename from sql/updates/06640_mangos_reference_loot_template.sql rename to sql/updates/0.12/06640_mangos_reference_loot_template.sql diff --git a/sql/updates/06642_characters_declinedname.sql b/sql/updates/0.12/06642_characters_declinedname.sql similarity index 100% rename from sql/updates/06642_characters_declinedname.sql rename to sql/updates/0.12/06642_characters_declinedname.sql diff --git a/sql/updates/06668_mangos_spell_proc_event.sql b/sql/updates/0.12/06668_mangos_spell_proc_event.sql similarity index 100% rename from sql/updates/06668_mangos_spell_proc_event.sql rename to sql/updates/0.12/06668_mangos_spell_proc_event.sql diff --git a/sql/updates/06673_mangos_areatrigger_scripts.sql b/sql/updates/0.12/06673_mangos_areatrigger_scripts.sql similarity index 100% rename from sql/updates/06673_mangos_areatrigger_scripts.sql rename to sql/updates/0.12/06673_mangos_areatrigger_scripts.sql diff --git a/sql/updates/06676_mangos_spell_proc_event.sql b/sql/updates/0.12/06676_mangos_spell_proc_event.sql similarity index 100% rename from sql/updates/06676_mangos_spell_proc_event.sql rename to sql/updates/0.12/06676_mangos_spell_proc_event.sql diff --git a/sql/updates/06681_mangos_mangos_string.sql b/sql/updates/0.12/06681_mangos_mangos_string.sql similarity index 100% rename from sql/updates/06681_mangos_mangos_string.sql rename to sql/updates/0.12/06681_mangos_mangos_string.sql diff --git a/sql/updates/06691_mangos_spell_proc_event.sql b/sql/updates/0.12/06691_mangos_spell_proc_event.sql similarity index 100% rename from sql/updates/06691_mangos_spell_proc_event.sql rename to sql/updates/0.12/06691_mangos_spell_proc_event.sql diff --git a/sql/updates/06693_mangos_spell_affect.sql b/sql/updates/0.12/06693_mangos_spell_affect.sql similarity index 100% rename from sql/updates/06693_mangos_spell_affect.sql rename to sql/updates/0.12/06693_mangos_spell_affect.sql diff --git a/sql/updates/06693_mangos_spell_proc_event.sql b/sql/updates/0.12/06693_mangos_spell_proc_event.sql similarity index 100% rename from sql/updates/06693_mangos_spell_proc_event.sql rename to sql/updates/0.12/06693_mangos_spell_proc_event.sql diff --git a/sql/updates/06698_characters_character_tutorial.sql b/sql/updates/0.12/06698_characters_character_tutorial.sql similarity index 100% rename from sql/updates/06698_characters_character_tutorial.sql rename to sql/updates/0.12/06698_characters_character_tutorial.sql diff --git a/sql/updates/06701_mangos_command.sql b/sql/updates/0.12/06701_mangos_command.sql similarity index 100% rename from sql/updates/06701_mangos_command.sql rename to sql/updates/0.12/06701_mangos_command.sql diff --git a/sql/updates/06701_mangos_mangos_string.sql b/sql/updates/0.12/06701_mangos_mangos_string.sql similarity index 100% rename from sql/updates/06701_mangos_mangos_string.sql rename to sql/updates/0.12/06701_mangos_mangos_string.sql diff --git a/sql/updates/06708_mangos_mangos_string.sql b/sql/updates/0.12/06708_mangos_mangos_string.sql similarity index 100% rename from sql/updates/06708_mangos_mangos_string.sql rename to sql/updates/0.12/06708_mangos_mangos_string.sql diff --git a/sql/updates/06715_mangos_spell_affect.sql b/sql/updates/0.12/06715_mangos_spell_affect.sql similarity index 100% rename from sql/updates/06715_mangos_spell_affect.sql rename to sql/updates/0.12/06715_mangos_spell_affect.sql diff --git a/sql/updates/06728_mangos_quest_template.sql b/sql/updates/0.12/06728_mangos_quest_template.sql similarity index 100% rename from sql/updates/06728_mangos_quest_template.sql rename to sql/updates/0.12/06728_mangos_quest_template.sql diff --git a/sql/updates/06730_mangos_mangos_string.sql b/sql/updates/0.12/06730_mangos_mangos_string.sql similarity index 100% rename from sql/updates/06730_mangos_mangos_string.sql rename to sql/updates/0.12/06730_mangos_mangos_string.sql diff --git a/sql/updates/06740_characters_characters.sql b/sql/updates/0.12/06740_characters_characters.sql similarity index 100% rename from sql/updates/06740_characters_characters.sql rename to sql/updates/0.12/06740_characters_characters.sql diff --git a/sql/updates/06740_mangos_command.sql b/sql/updates/0.12/06740_mangos_command.sql similarity index 100% rename from sql/updates/06740_mangos_command.sql rename to sql/updates/0.12/06740_mangos_command.sql diff --git a/sql/updates/06740_mangos_mangos_string.sql b/sql/updates/0.12/06740_mangos_mangos_string.sql similarity index 100% rename from sql/updates/06740_mangos_mangos_string.sql rename to sql/updates/0.12/06740_mangos_mangos_string.sql diff --git a/sql/updates/06742_mangos_command.sql b/sql/updates/0.12/06742_mangos_command.sql similarity index 100% rename from sql/updates/06742_mangos_command.sql rename to sql/updates/0.12/06742_mangos_command.sql diff --git a/sql/updates/06742_mangos_mangos_string.sql b/sql/updates/0.12/06742_mangos_mangos_string.sql similarity index 100% rename from sql/updates/06742_mangos_mangos_string.sql rename to sql/updates/0.12/06742_mangos_mangos_string.sql diff --git a/sql/updates/06748_mangos_mangos_string.sql b/sql/updates/0.12/06748_mangos_mangos_string.sql similarity index 100% rename from sql/updates/06748_mangos_mangos_string.sql rename to sql/updates/0.12/06748_mangos_mangos_string.sql diff --git a/sql/updates/06750_mangos_command.sql b/sql/updates/0.12/06750_mangos_command.sql similarity index 100% rename from sql/updates/06750_mangos_command.sql rename to sql/updates/0.12/06750_mangos_command.sql diff --git a/sql/updates/06751_realmd_account.sql b/sql/updates/0.12/06751_realmd_account.sql similarity index 100% rename from sql/updates/06751_realmd_account.sql rename to sql/updates/0.12/06751_realmd_account.sql diff --git a/sql/updates/06760_mangos_creature_template.sql b/sql/updates/0.12/06760_mangos_creature_template.sql similarity index 100% rename from sql/updates/06760_mangos_creature_template.sql rename to sql/updates/0.12/06760_mangos_creature_template.sql diff --git a/sql/updates/2008_11_11_02_mangos_scripts.sql b/sql/updates/2008_11_11_02_mangos_scripts.sql index a9fbd1036..b2d9fb147 100644 --- a/sql/updates/2008_11_11_02_mangos_scripts.sql +++ b/sql/updates/2008_11_11_02_mangos_scripts.sql @@ -2,20 +2,20 @@ ALTER TABLE db_version CHANGE COLUMN required_2008_11_11_01_mangos_db_script_str ALTER TABLE event_scripts DROP datatext, - ADD COLUMN dataint int(11) NOT NULL default '0'; + ADD COLUMN dataint int(11) NOT NULL default '0'; ALTER TABLE gameobject_scripts DROP datatext, - ADD COLUMN dataint int(11) NOT NULL default '0'; + ADD COLUMN dataint int(11) NOT NULL default '0'; ALTER TABLE quest_end_scripts DROP datatext, - ADD COLUMN dataint int(11) NOT NULL default '0'; + ADD COLUMN dataint int(11) NOT NULL default '0'; ALTER TABLE quest_start_scripts DROP datatext, - ADD COLUMN dataint int(11) NOT NULL default '0'; + ADD COLUMN dataint int(11) NOT NULL default '0'; ALTER TABLE spell_scripts DROP datatext, - ADD COLUMN dataint int(11) NOT NULL default '0'; + ADD COLUMN dataint int(11) NOT NULL default '0'; diff --git a/sql/updates/2008_11_14_01_mangos_scripts.sql b/sql/updates/2008_11_14_01_mangos_scripts.sql index ab51cf3d8..a2176b612 100644 --- a/sql/updates/2008_11_14_01_mangos_scripts.sql +++ b/sql/updates/2008_11_14_01_mangos_scripts.sql @@ -1,16 +1,16 @@ ALTER TABLE db_version CHANGE COLUMN required_2008_11_11_02_mangos_scripts required_2008_11_14_01_mangos_scripts bit; ALTER TABLE event_scripts - CHANGE COLUMN dataint dataint int(11) NOT NULL default '0' AFTER datalong2; + CHANGE COLUMN dataint dataint int(11) NOT NULL default '0' AFTER datalong2; ALTER TABLE gameobject_scripts - CHANGE COLUMN dataint dataint int(11) NOT NULL default '0' AFTER datalong2; + CHANGE COLUMN dataint dataint int(11) NOT NULL default '0' AFTER datalong2; ALTER TABLE quest_end_scripts - CHANGE COLUMN dataint dataint int(11) NOT NULL default '0' AFTER datalong2; + CHANGE COLUMN dataint dataint int(11) NOT NULL default '0' AFTER datalong2; ALTER TABLE quest_start_scripts - CHANGE COLUMN dataint dataint int(11) NOT NULL default '0' AFTER datalong2; + CHANGE COLUMN dataint dataint int(11) NOT NULL default '0' AFTER datalong2; ALTER TABLE spell_scripts - CHANGE COLUMN dataint dataint int(11) NOT NULL default '0' AFTER datalong2; + CHANGE COLUMN dataint dataint int(11) NOT NULL default '0' AFTER datalong2; diff --git a/sql/updates/2008_12_15_01_character_arenas.sql b/sql/updates/2008_12_15_01_character_arenas.sql new file mode 100644 index 000000000..5fdf0870f --- /dev/null +++ b/sql/updates/2008_12_15_01_character_arenas.sql @@ -0,0 +1,8 @@ +ALTER TABLE character_db_version CHANGE COLUMN required_2008_12_03_01_character_guild_member required_2008_12_15_01_character_arenas bit; + +CREATE TABLE `saved_variables` ( + `NextArenaPointDistributionTime` bigint(40) UNSIGNED NOT NULL DEFAULT '0' +) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=FIXED COMMENT='Variable Saves'; + +ALTER TABLE `arena_team_member` ADD COLUMN `personal_rating` int(10) UNSIGNED NOT NULL DEFAULT '0'; +ALTER TABLE `characters` ADD COLUMN `arena_pending_points` int(10) UNSIGNED NOT NULL default '0'; diff --git a/sql/updates/2008_12_15_01_mangos_arenas.sql b/sql/updates/2008_12_15_01_mangos_arenas.sql new file mode 100644 index 000000000..c8208b844 --- /dev/null +++ b/sql/updates/2008_12_15_01_mangos_arenas.sql @@ -0,0 +1,28 @@ +ALTER TABLE db_version CHANGE COLUMN required_2008_11_29_02_mangos_spell_elixir required_2008_12_15_01_mangos_arenas bit; + +DELETE FROM `command` WHERE `name` = "flusharenapoints"; +INSERT INTO `command` (`name`, `security`, `help`) VALUES +('flusharenapoints','3','Syntax: .flusharenapoints\r\n\r\nUse it to distribute arena points based on arena team ratings, and start a new week.'); + +DELETE FROM mangos_string WHERE entry BETWEEN 1122 AND 1138; + +INSERT INTO mangos_string (entry, content_default) VALUES + (1122,'Your group is too large for this battleground. Please regroup to join.'), + (1123,'Your group is too large for this arena. Please regroup to join.'), + (1124,'Your group has members not in your arena team. Please regroup to join.'), + (1125,'Your group does not have enough players to join this match.'), + (1126,'The Gold Team wins!'), + (1127,'The Green Team wins!'), + (1128, 'There aren\'t enough players in this battleground. It will end soon unless some more players join to balance the fight.'), + (1129, 'Your group has an offline member. Please remove him before joining.'), + (1130, 'Your group has players from the opposing faction. You can\'t join the battleground as a group.'), + (1131, 'Your group has players from different battleground brakets. You can\'t join as group.'), + (1132, 'Someone in your party is already in this battleground queue. (S)he must leave it before joining as group.'), + (1133, 'Someone in your party is Deserter. You can\'t join as group.'), + (1134, 'Someone in your party is already in three battleground queues. You cannot join as group.'), + (1135, 'You cannot teleport to a battleground or arena map.'), + (1136, 'You cannot summon players to a battleground or arena map.'), + (1137, 'You must be in GM mode to teleport to a player in a battleground.'), + (1138, 'You cannot teleport to a battleground from another battleground. Please leave the current battleground first.'); + +DELETE FROM mangos_string WHERE entry = 714 OR entry = 716; diff --git a/sql/updates/2008_12_22_01_mangos_creature_equip_template.sql b/sql/updates/2008_12_22_01_mangos_creature_equip_template.sql new file mode 100644 index 000000000..6efaae7ae --- /dev/null +++ b/sql/updates/2008_12_22_01_mangos_creature_equip_template.sql @@ -0,0 +1,14 @@ +ALTER TABLE db_version CHANGE COLUMN required_2008_12_15_01_mangos_arenas required_2008_12_22_01_mangos_creature_equip_template bit; + +TRUNCATE creature_equip_template; + +alter table `creature_equip_template` + drop column `equipinfo1`, + drop column `equipinfo2`, + drop column `equipinfo3`, + drop column `equipslot1`, + drop column `equipslot2`, + drop column `equipslot3`, + change `equipmodel1` `equipentry1` mediumint(8) UNSIGNED default '0' NOT NULL, + change `equipmodel2` `equipentry2` mediumint(8) UNSIGNED default '0' NOT NULL, + change `equipmodel3` `equipentry3` mediumint(8) UNSIGNED default '0' NOT NULL; diff --git a/sql/updates/2008_12_22_02_characters_character_pet.sql b/sql/updates/2008_12_22_02_characters_character_pet.sql new file mode 100644 index 000000000..b083232ae --- /dev/null +++ b/sql/updates/2008_12_22_02_characters_character_pet.sql @@ -0,0 +1,7 @@ +ALTER TABLE character_db_version CHANGE COLUMN required_2008_12_15_01_character_arenas required_2008_12_22_02_characters_character_pet bit; + +alter table `character_pet` + drop column `trainpoint`, + drop column `loyaltypoints`, + drop column `loyalty`, + add `talentpoints` int(11) UNSIGNED default '0' NOT NULL after `Reactstate`; diff --git a/sql/updates/2008_12_22_03_mangos_item_template.sql b/sql/updates/2008_12_22_03_mangos_item_template.sql new file mode 100644 index 000000000..3d27b3f3d --- /dev/null +++ b/sql/updates/2008_12_22_03_mangos_item_template.sql @@ -0,0 +1,7 @@ +ALTER TABLE db_version CHANGE COLUMN required_2008_12_22_01_mangos_creature_equip_template required_2008_12_22_03_mangos_item_template bit; + +alter table `item_template` + add column `ScalingStatDistribution` smallint(6) DEFAULT '0' NOT NULL after `stat_value10`, + add column `ScalingStatValue` smallint(6) DEFAULT '0' NOT NULL after `ScalingStatDistribution`, + add column `ItemLimitCategory` smallint(6) DEFAULT '0' NOT NULL after `ArmorDamageModifier`, + change `Duration` `Duration` int(11) NOT NULL default '0' COMMENT 'Duration in seconds. Negative value means realtime, postive value ingame time' after ArmorDamageModifier; diff --git a/sql/updates/2008_12_22_04_mangos_item_template.sql b/sql/updates/2008_12_22_04_mangos_item_template.sql new file mode 100644 index 000000000..685c44a4e --- /dev/null +++ b/sql/updates/2008_12_22_04_mangos_item_template.sql @@ -0,0 +1,4 @@ +ALTER TABLE db_version CHANGE COLUMN required_2008_12_22_03_mangos_item_template required_2008_12_22_04_mangos_item_template bit; + +alter table `item_template` + add column `StatsCount` tinyint(3) UNSIGNED DEFAULT '0' NOT NULL after `ContainerSlots`; diff --git a/sql/updates/2008_12_22_05_characters_account_data.sql b/sql/updates/2008_12_22_05_characters_account_data.sql new file mode 100644 index 000000000..5923bfe96 --- /dev/null +++ b/sql/updates/2008_12_22_05_characters_account_data.sql @@ -0,0 +1,9 @@ +ALTER TABLE character_db_version CHANGE COLUMN required_2008_12_22_02_characters_character_pet required_2008_12_22_05_characters_account_data bit; + +CREATE TABLE `account_data` ( + `account` int(11) unsigned NOT NULL default '0', + `type` int(11) unsigned NOT NULL default '0', + `time` bigint(11) unsigned NOT NULL default '0', + `data` longtext NOT NULL, + PRIMARY KEY (`account`,`type`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; diff --git a/sql/updates/2008_12_22_06_characters_character_achievement.sql b/sql/updates/2008_12_22_06_characters_character_achievement.sql new file mode 100644 index 000000000..ca5c240b6 --- /dev/null +++ b/sql/updates/2008_12_22_06_characters_character_achievement.sql @@ -0,0 +1,18 @@ +ALTER TABLE character_db_version CHANGE COLUMN required_2008_12_22_05_characters_account_data required_2008_12_22_06_characters_character_achievement bit; + +DROP TABLE IF EXISTS `character_achievement`; +CREATE TABLE `character_achievement` ( + `guid` int(11) NOT NULL, + `achievement` int(11) NOT NULL, + `date` int(11) NOT NULL, + PRIMARY KEY (`guid`,`achievement`) + ) ENGINE=MyISAM DEFAULT CHARSET=utf8; + +DROP TABLE IF EXISTS `character_achievement_progress`; +CREATE TABLE `character_achievement_progress` ( + `guid` int(11) NOT NULL, + `criteria` int(11) NOT NULL, + `counter` int(11) NOT NULL, + `date` int(11) NOT NULL, + PRIMARY KEY (`guid`,`criteria`) + ) ENGINE=MyISAM DEFAULT CHARSET=utf8; diff --git a/sql/updates/2008_12_22_07_mangos_quest_template.sql b/sql/updates/2008_12_22_07_mangos_quest_template.sql new file mode 100644 index 000000000..a3795504b --- /dev/null +++ b/sql/updates/2008_12_22_07_mangos_quest_template.sql @@ -0,0 +1,5 @@ +ALTER TABLE db_version CHANGE COLUMN required_2008_12_22_04_mangos_item_template required_2008_12_22_07_mangos_quest_template bit; + +alter table `quest_template` + add column `PlayersSlain` tinyint(3) UNSIGNED DEFAULT '0' NOT NULL after `CharTitleId`, + add column `BonusTalents` tinyint(3) UNSIGNED DEFAULT '0' NOT NULL after `PlayersSlain`; diff --git a/sql/updates/2008_12_22_08_mangos_milling_loot_template.sql b/sql/updates/2008_12_22_08_mangos_milling_loot_template.sql new file mode 100644 index 000000000..18500508c --- /dev/null +++ b/sql/updates/2008_12_22_08_mangos_milling_loot_template.sql @@ -0,0 +1,15 @@ +ALTER TABLE db_version CHANGE COLUMN required_2008_12_22_07_mangos_quest_template required_2008_12_22_08_mangos_milling_loot_template bit; + +DROP TABLE IF EXISTS `milling_loot_template`; +CREATE TABLE `milling_loot_template` ( + `entry` mediumint(8) unsigned NOT NULL default '0', + `item` mediumint(8) unsigned NOT NULL default '0', + `ChanceOrQuestChance` float NOT NULL default '100', + `groupid` tinyint(3) unsigned NOT NULL default '0', + `mincountOrRef` mediumint(9) NOT NULL default '1', + `maxcount` tinyint(3) unsigned NOT NULL default '1', + `lootcondition` tinyint(3) unsigned NOT NULL default '0', + `condition_value1` mediumint(8) unsigned NOT NULL default '0', + `condition_value2` mediumint(8) unsigned NOT NULL default '0', + PRIMARY KEY (`entry`,`item`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=FIXED COMMENT='Loot System'; diff --git a/sql/updates/2008_12_22_09_mangos_spell_affect.sql b/sql/updates/2008_12_22_09_mangos_spell_affect.sql new file mode 100644 index 000000000..6d5635ece --- /dev/null +++ b/sql/updates/2008_12_22_09_mangos_spell_affect.sql @@ -0,0 +1,14 @@ +ALTER TABLE db_version CHANGE COLUMN required_2008_12_22_08_mangos_milling_loot_template required_2008_12_22_09_mangos_spell_affect bit; + +-- +-- Table structure for table `spell_affect` +-- +DROP TABLE IF EXISTS `spell_affect`; +CREATE TABLE `spell_affect` ( + `entry` smallint(5) unsigned NOT NULL default '0', + `effectId` tinyint(3) unsigned NOT NULL default '0', + `SpellClassMask0` int(5) unsigned NOT NULL default '0', + `SpellClassMask1` int(5) unsigned NOT NULL default '0', + `SpellClassMask2` int(5) unsigned NOT NULL default '0', + PRIMARY KEY (`entry`,`effectId`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; \ No newline at end of file diff --git a/sql/updates/2008_12_22_10_mangos_string.sql b/sql/updates/2008_12_22_10_mangos_string.sql new file mode 100644 index 000000000..16c9f0dda --- /dev/null +++ b/sql/updates/2008_12_22_10_mangos_string.sql @@ -0,0 +1,5 @@ +ALTER TABLE db_version CHANGE COLUMN required_2008_12_22_09_mangos_spell_affect required_2008_12_22_10_mangos_string bit; + +INSERT INTO `mangos_string` VALUES +(345,'Forced customize for player %s will be requested at next login.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(346,'Forced customize for player %s (GUID #%u) will be requested at next login.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL); diff --git a/sql/updates/2008_12_22_11_mangos_player_classlevelstats.sql b/sql/updates/2008_12_22_11_mangos_player_classlevelstats.sql new file mode 100644 index 000000000..70c947f97 --- /dev/null +++ b/sql/updates/2008_12_22_11_mangos_player_classlevelstats.sql @@ -0,0 +1,183 @@ +ALTER TABLE db_version CHANGE COLUMN required_2008_12_22_10_mangos_string required_2008_12_22_11_mangos_player_classlevelstats bit; + +DELETE FROM `player_classlevelstats` WHERE class = 6 OR level > 70; +INSERT INTO `player_classlevelstats` VALUES +(1,71,4720,0), +(1,72,5013,0), +(1,73,5325,0), +(1,74,5656,0), +(1,75,6008,0), +(1,76,6381,0), +(1,77,6778,0), +(1,78,7198,0), +(1,79,7646,0), +(1,80,8121,0), + +(2,71,3629,3097), +(2,72,3900,3241), +(2,73,4191,3385), +(2,74,4503,3529), +(2,75,4839,3673), +(2,76,5200,3817), +(2,77,5588,3962), +(2,78,6005,4106), +(2,79,6453,4250), +(2,80,6934,4394), + +(3,71,3834,3549), +(3,72,4120,3716), +(3,73,4427,3882), +(3,74,4757,4048), +(3,75,5112,4215), +(3,76,5493,4381), +(3,77,5903,4547), +(3,78,6343,4713), +(3,79,6816,4880), +(3,80,7324,5046), + +(4,71,3980,0), +(4,72,4277,0), +(4,73,4596,0), +(4,74,4939,0), +(4,75,5307,0), +(4,76,5703,0), +(4,77,6128,0), +(4,78,6585,0), +(4,79,7076,0), +(4,80,7604,0), + +(5,71,3644,2744), +(5,72,3916,2868), +(5,73,4208,2993), +(5,74,4522,3117), +(5,75,4859,3242), +(5,76,5221,3366), +(5,77,5610,3490), +(5,78,6028,3615), +(5,79,6477,3739), +(5,80,6960,3863), + +(6,1,22,0), +(6,2,27,0), +(6,3,32,0), +(6,4,37,0), +(6,5,42,0), +(6,6,47,0), +(6,7,52,0), +(6,8,58,0), +(6,9,64,0), +(6,10,70,0), +(6,11,77,0), +(6,12,84,0), +(6,13,92,0), +(6,14,100,0), +(6,15,117,0), +(6,16,127,0), +(6,17,138,0), +(6,18,150,0), +(6,19,163,0), +(6,20,177,0), +(6,21,192,0), +(6,22,208,0), +(6,23,225,0), +(6,24,239,0), +(6,25,258,0), +(6,26,278,0), +(6,27,299,0), +(6,28,321,0), +(6,29,344,0), +(6,30,368,0), +(6,31,393,0), +(6,32,419,0), +(6,33,446,0), +(6,34,474,0), +(6,35,503,0), +(6,36,533,0), +(6,37,564,0), +(6,38,596,0), +(6,39,629,0), +(6,40,698,0), +(6,41,698,0), +(6,42,734,0), +(6,43,771,0), +(6,44,809,0), +(6,45,849,0), +(6,46,891,0), +(6,47,935,0), +(6,48,981,0), +(6,49,1029,0), +(6,50,1079,0), +(6,51,1131,0), +(6,52,1185,0), +(6,53,1241,0), +(6,54,1299,0), +(6,55,1359,0), +(6,56,1421,0), +(6,57,1485,0), +(6,58,1551,0), +(6,59,1619,0), +(6,60,1689,0), +(6,61,1902,0), +(6,62,2129,0), +(6,63,2357,0), +(6,64,2612,0), +(6,65,2883,0), +(6,66,3169,0), +(6,67,3455,0), +(6,68,3774,0), +(6,69,4109,0), +(6,70,4444,0), +(6,71,4720,0), +(6,72,5013,0), +(6,73,5325,0), +(6,74,5656,0), +(6,75,6008,0), +(6,76,6381,0), +(6,77,6778,0), +(6,78,7199,0), +(6,79,7646,0), +(6,80,8121,0), + +(7,71,3395,3102), +(7,72,3648,3246), +(7,73,3920,3389), +(7,74,4212,3533), +(7,75,4526,3677), +(7,76,4863,3821), +(7,77,5226,3965), +(7,78,5616,4108), +(7,79,6035,4252), +(7,80,6485,4396), + +(8,71,3646,2343), +(8,72,3918,2446), +(8,73,4210,2549), +(8,74,4524,2652), +(8,75,4861,2754), +(8,76,5223,2857), +(8,77,5612,2960), +(8,78,6030,3063), +(8,79,6480,3165), +(8,80,6963,3268), + +(9,71,3750,2739), +(9,72,4025,2863), +(9,73,4330,2987), +(9,74,4646,3111), +(9,75,4997,3235), +(9,76,5373,3360), +(9,77,5774,3483), +(9,78,6207,3608), +(9,79,6667,3732), +(9,80,7136,3856), + +(11,71,3883,2482), +(11,72,4172,2595), +(11,73,4483,2708), +(11,74,4817,2820), +(11,75,5176,2933), +(11,76,5562,3045), +(11,77,5977,3158), +(11,78,6423,3270), +(11,79,6902,3383), +(11,80,7417,3496); diff --git a/sql/updates/2008_12_22_12_mangos_player_levelstats.sql b/sql/updates/2008_12_22_12_mangos_player_levelstats.sql new file mode 100644 index 000000000..f74733407 --- /dev/null +++ b/sql/updates/2008_12_22_12_mangos_player_levelstats.sql @@ -0,0 +1,5025 @@ +ALTER TABLE db_version CHANGE COLUMN required_2008_12_22_11_mangos_player_classlevelstats required_2008_12_22_12_mangos_player_levelstats bit; + +DELETE FROM `player_levelstats`; +INSERT INTO `player_levelstats` VALUES +(1,1,1,23,20,22,20,20), +(1,1,2,24,21,23,20,20), +(1,1,3,26,22,24,20,21), +(1,1,4,27,22,26,20,21), +(1,1,5,28,23,27,20,21), +(1,1,6,30,24,28,20,21), +(1,1,7,31,25,29,21,22), +(1,1,8,32,26,30,21,22), +(1,1,9,34,26,32,21,22), +(1,1,10,35,27,33,21,23), +(1,1,11,36,28,34,21,23), +(1,1,12,38,29,35,21,23), +(1,1,13,39,30,37,21,24), +(1,1,14,41,31,38,21,24), +(1,1,15,42,32,39,21,24), +(1,1,16,44,33,41,21,25), +(1,1,17,45,34,42,22,25), +(1,1,18,47,34,43,22,25), +(1,1,19,48,35,45,22,26), +(1,1,20,50,36,46,22,26), +(1,1,21,51,37,48,22,26), +(1,1,22,53,38,49,22,27), +(1,1,23,54,39,51,22,27), +(1,1,24,56,40,52,23,28), +(1,1,25,58,41,53,23,28), +(1,1,26,59,42,55,23,28), +(1,1,27,61,43,56,23,29), +(1,1,28,63,44,58,23,29), +(1,1,29,64,45,59,23,30), +(1,1,30,66,46,61,24,30), +(1,1,31,68,47,62,24,30), +(1,1,32,69,48,64,24,31), +(1,1,33,71,50,66,24,31), +(1,1,34,73,51,67,24,32), +(1,1,35,74,52,69,24,32), +(1,1,36,76,53,70,25,33), +(1,1,37,78,54,72,25,33), +(1,1,38,80,55,74,25,34), +(1,1,39,82,56,75,25,34), +(1,1,40,83,57,77,25,35), +(1,1,41,85,58,79,26,35), +(1,1,42,87,60,80,26,35), +(1,1,43,89,61,82,26,36), +(1,1,44,91,62,84,26,36), +(1,1,45,93,63,85,26,37), +(1,1,46,95,64,87,27,37), +(1,1,47,97,66,89,27,38), +(1,1,48,99,67,91,27,38), +(1,1,49,101,68,93,27,39), +(1,1,50,103,69,94,28,40), +(1,1,51,105,71,96,28,40), +(1,1,52,107,72,98,28,41), +(1,1,53,109,73,100,28,41), +(1,1,54,111,74,102,29,42), +(1,1,55,113,76,103,29,42), +(1,1,56,115,77,105,29,43), +(1,1,57,117,78,107,29,43), +(1,1,58,119,79,109,30,44), +(1,1,59,121,81,111,30,44), +(1,1,60,123,82,113,30,45), +(1,1,61,125,83,115,30,46), +(1,1,62,127,85,117,31,46), +(1,1,63,129,86,119,31,47), +(1,1,64,132,88,121,31,47), +(1,1,65,134,89,123,32,48), +(1,1,66,136,90,125,32,49), +(1,1,67,138,92,127,32,49), +(1,1,68,140,93,129,32,50), +(1,1,69,143,95,131,33,50), +(1,1,70,145,96,133,33,51), +(1,1,71,148,97,140,33,53), +(1,1,72,156,99,143,33,54), +(1,1,73,162,101,148,33,55), +(1,1,74,162,102,148,34,55), +(1,1,75,165,104,150,34,56), +(1,1,76,171,106,156,34,57), +(1,1,77,171,108,157,35,58), +(1,1,78,174,109,159,35,58), +(1,1,79,181,111,165,35,59), +(1,1,80,184,113,168,36,60), + +(1,2,1,22,20,22,20,21), +(1,2,2,23,21,23,21,22), +(1,2,3,24,21,24,21,22), +(1,2,4,25,22,25,22,23), +(1,2,5,26,22,26,23,24), +(1,2,6,28,23,27,23,25), +(1,2,7,29,24,28,24,25), +(1,2,8,30,24,29,25,26), +(1,2,9,31,25,30,25,27), +(1,2,10,32,25,32,26,27), +(1,2,11,33,26,33,27,28), +(1,2,12,35,27,34,27,29), +(1,2,13,36,27,35,28,30), +(1,2,14,37,28,36,29,31), +(1,2,15,38,29,37,30,31), +(1,2,16,40,29,38,30,32), +(1,2,17,41,30,40,31,33), +(1,2,18,42,31,41,32,34), +(1,2,19,43,31,42,33,35), +(1,2,20,45,32,43,33,35), +(1,2,21,46,33,45,34,36), +(1,2,22,47,33,46,35,37), +(1,2,23,49,34,47,36,38), +(1,2,24,50,35,48,37,39), +(1,2,25,51,36,50,37,40), +(1,2,26,53,36,51,38,41), +(1,2,27,54,37,52,39,42), +(1,2,28,56,38,54,40,43), +(1,2,29,57,39,55,41,43), +(1,2,30,58,39,56,42,44), +(1,2,31,60,40,58,43,45), +(1,2,32,61,41,59,43,46), +(1,2,33,63,42,60,44,47), +(1,2,34,64,43,62,45,48), +(1,2,35,66,44,63,46,49), +(1,2,36,67,44,65,47,50), +(1,2,37,69,45,66,48,51), +(1,2,38,70,46,67,49,52), +(1,2,39,72,47,69,50,53), +(1,2,40,73,48,70,51,54), +(1,2,41,75,49,72,52,55), +(1,2,42,77,49,73,53,56), +(1,2,43,78,50,75,54,57), +(1,2,44,80,51,76,55,58), +(1,2,45,81,52,78,56,59), +(1,2,46,83,53,79,57,61), +(1,2,47,85,54,81,58,62), +(1,2,48,86,55,83,59,63), +(1,2,49,88,56,84,60,64), +(1,2,50,90,57,86,61,65), +(1,2,51,91,58,87,62,66), +(1,2,52,93,59,89,63,67), +(1,2,53,95,60,91,64,68), +(1,2,54,97,61,92,65,69), +(1,2,55,98,61,94,66,71), +(1,2,56,100,62,95,67,72), +(1,2,57,102,63,97,68,73), +(1,2,58,104,64,99,69,74), +(1,2,59,105,65,101,70,75), +(1,2,60,107,66,102,71,77), +(1,2,61,109,67,104,73,78), +(1,2,62,111,69,106,74,79), +(1,2,63,113,70,107,75,80), +(1,2,64,115,71,109,76,81), +(1,2,65,116,72,111,77,83), +(1,2,66,118,73,113,78,84), +(1,2,67,120,74,115,79,85), +(1,2,68,122,75,116,81,86), +(1,2,69,124,76,118,82,88), +(1,2,70,126,77,120,83,89), +(1,2,71,148,78,122,84,92), +(1,2,72,150,79,125,86,94), +(1,2,73,152,80,127,87,96), +(1,2,74,156,82,129,89,97), +(1,2,75,158,83,131,90,99), +(1,2,76,162,84,134,92,100), +(1,2,77,164,86,136,93,103), +(1,2,78,167,87,138,95,105), +(1,2,79,170,88,153,96,106), +(1,2,80,173,90,160,98,108), + +(1,4,1,21,23,21,20,20), +(1,4,2,22,24,22,20,20), +(1,4,3,23,26,22,20,21), +(1,4,4,23,27,23,20,21), +(1,4,5,24,29,24,21,21), +(1,4,6,25,30,25,21,22), +(1,4,7,26,32,25,21,22), +(1,4,8,26,33,26,21,23), +(1,4,9,27,35,27,21,23), +(1,4,10,28,36,27,21,23), +(1,4,11,29,38,28,22,24), +(1,4,12,30,39,29,22,24), +(1,4,13,31,41,30,22,25), +(1,4,14,31,43,31,22,25), +(1,4,15,32,44,31,22,25), +(1,4,16,33,46,32,23,26), +(1,4,17,34,48,33,23,26), +(1,4,18,35,49,34,23,27), +(1,4,19,36,51,35,23,27), +(1,4,20,37,53,35,23,28), +(1,4,21,38,54,36,24,28), +(1,4,22,39,56,37,24,29), +(1,4,23,40,58,38,24,29), +(1,4,24,41,60,39,24,30), +(1,4,25,42,61,40,25,30), +(1,4,26,43,63,41,25,31), +(1,4,27,44,65,42,25,31), +(1,4,28,45,67,43,25,32), +(1,4,29,46,69,43,25,32), +(1,4,30,47,71,44,26,33), +(1,4,31,48,72,45,26,33), +(1,4,32,49,74,46,26,34), +(1,4,33,50,76,47,27,34), +(1,4,34,51,78,48,27,35), +(1,4,35,52,80,49,27,35), +(1,4,36,53,82,50,27,36), +(1,4,37,54,84,51,28,36), +(1,4,38,55,86,52,28,37), +(1,4,39,56,88,53,28,38), +(1,4,40,57,90,54,28,38), +(1,4,41,58,92,55,29,39), +(1,4,42,60,94,56,29,39), +(1,4,43,61,96,57,29,40), +(1,4,44,62,98,58,30,40), +(1,4,45,63,100,59,30,41), +(1,4,46,64,103,61,30,42), +(1,4,47,65,105,62,31,42), +(1,4,48,66,107,63,31,43), +(1,4,49,68,109,64,31,44), +(1,4,50,69,111,65,32,44), +(1,4,51,70,113,66,32,45), +(1,4,52,71,116,67,32,45), +(1,4,53,73,118,68,33,46), +(1,4,54,74,120,69,33,47), +(1,4,55,75,122,71,33,47), +(1,4,56,76,125,72,34,48), +(1,4,57,78,127,73,34,49), +(1,4,58,79,129,74,34,49), +(1,4,59,80,131,75,35,50), +(1,4,60,81,134,77,35,51), +(1,4,61,83,136,78,35,51), +(1,4,62,84,138,79,36,52), +(1,4,63,85,141,80,36,53), +(1,4,64,87,143,81,37,54), +(1,4,65,88,146,83,37,54), +(1,4,66,89,148,84,37,55), +(1,4,67,91,151,85,38,56), +(1,4,68,92,153,86,38,57), +(1,4,69,94,156,88,39,57), +(1,4,70,95,158,89,39,58), +(1,4,71,97,161,90,39,60), +(1,4,72,99,164,92,40,60), +(1,4,73,100,167,94,40,61), +(1,4,74,102,170,95,41,62), +(1,4,75,104,173,97,41,63), +(1,4,76,105,176,98,41,64), +(1,4,77,107,179,100,42,65), +(1,4,78,109,183,106,42,66), +(1,4,79,111,186,107,43,67), +(1,4,80,113,189,109,43,69), + +(1,5,1,20,20,20,22,23), +(1,5,2,20,20,20,23,24), +(1,5,3,20,20,21,25,26), +(1,5,4,20,21,21,26,27), +(1,5,5,21,21,21,27,28), +(1,5,6,21,21,22,29,30), +(1,5,7,21,21,22,30,31), +(1,5,8,21,22,23,31,33), +(1,5,9,21,22,23,33,34), +(1,5,10,21,22,23,34,36), +(1,5,11,22,22,24,36,37), +(1,5,12,22,23,24,37,39), +(1,5,13,22,23,25,38,40), +(1,5,14,22,23,25,40,42), +(1,5,15,22,23,25,41,43), +(1,5,16,23,24,26,43,45), +(1,5,17,23,24,26,44,46), +(1,5,18,23,24,27,46,48), +(1,5,19,23,24,27,47,49), +(1,5,20,23,25,28,49,51), +(1,5,21,24,25,28,51,53), +(1,5,22,24,25,29,52,54), +(1,5,23,24,26,29,54,56), +(1,5,24,24,26,30,55,58), +(1,5,25,25,26,30,57,59), +(1,5,26,25,27,31,59,61), +(1,5,27,25,27,31,60,63), +(1,5,28,25,27,32,62,65), +(1,5,29,25,28,32,64,66), +(1,5,30,26,28,33,65,68), +(1,5,31,26,28,33,67,70), +(1,5,32,26,29,34,69,72), +(1,5,33,27,29,34,70,73), +(1,5,34,27,29,35,72,75), +(1,5,35,27,30,35,74,77), +(1,5,36,27,30,36,76,79), +(1,5,37,28,30,36,78,81), +(1,5,38,28,31,37,79,83), +(1,5,39,28,31,38,81,85), +(1,5,40,28,31,38,83,87), +(1,5,41,29,32,39,85,88), +(1,5,42,29,32,39,87,90), +(1,5,43,29,33,40,89,92), +(1,5,44,30,33,40,91,94), +(1,5,45,30,33,41,92,96), +(1,5,46,30,34,42,94,98), +(1,5,47,31,34,42,96,100), +(1,5,48,31,35,43,98,102), +(1,5,49,31,35,44,100,104), +(1,5,50,32,36,44,102,106), +(1,5,51,32,36,45,104,109), +(1,5,52,32,36,45,106,111), +(1,5,53,33,37,46,108,113), +(1,5,54,33,37,47,110,115), +(1,5,55,33,38,47,112,117), +(1,5,56,34,38,48,114,119), +(1,5,57,34,39,49,117,121), +(1,5,58,34,39,49,119,124), +(1,5,59,35,40,50,121,126), +(1,5,60,35,40,51,123,128), +(1,5,61,35,41,51,125,130), +(1,5,62,36,41,52,127,132), +(1,5,63,36,41,53,129,135), +(1,5,64,37,42,54,132,137), +(1,5,65,37,42,54,134,139), +(1,5,66,37,43,55,136,142), +(1,5,67,38,43,56,138,144), +(1,5,68,38,44,57,140,146), +(1,5,69,39,44,57,143,149), +(1,5,70,39,45,58,145,151), +(1,5,71,39,46,59,148,158), +(1,5,72,40,46,59,151,161), +(1,5,73,40,47,60,154,164), +(1,5,74,41,47,61,156,167), +(1,5,75,41,48,62,159,170), +(1,5,76,41,49,63,162,174), +(1,5,77,42,49,64,165,177), +(1,5,78,42,50,65,168,180), +(1,5,79,43,50,66,171,183), +(1,5,80,43,51,67,174,186), + +(1,6,1,23,20,22,20,20), +(1,6,2,24,21,23,20,20), +(1,6,3,26,22,24,20,21), +(1,6,4,27,22,26,20,21), +(1,6,5,28,23,27,20,21), +(1,6,6,30,24,28,20,21), +(1,6,7,31,25,29,21,22), +(1,6,8,32,26,30,21,22), +(1,6,9,34,26,32,21,22), +(1,6,10,35,27,33,21,23), +(1,6,11,36,28,34,21,23), +(1,6,12,38,29,35,21,23), +(1,6,13,39,30,37,21,24), +(1,6,14,41,31,38,21,24), +(1,6,15,42,32,39,21,24), +(1,6,16,44,33,41,21,25), +(1,6,17,45,34,42,22,25), +(1,6,18,47,34,43,22,25), +(1,6,19,48,35,45,22,26), +(1,6,20,50,36,46,22,26), +(1,6,21,51,37,48,22,26), +(1,6,22,53,38,49,22,27), +(1,6,23,54,39,51,22,27), +(1,6,24,56,40,52,23,28), +(1,6,25,58,41,53,23,28), +(1,6,26,59,42,55,23,28), +(1,6,27,61,43,56,23,29), +(1,6,28,63,44,58,23,29), +(1,6,29,64,45,59,23,30), +(1,6,30,66,46,61,24,30), +(1,6,31,68,47,62,24,30), +(1,6,32,69,48,64,24,31), +(1,6,33,71,50,66,24,31), +(1,6,34,73,51,67,24,32), +(1,6,35,74,52,69,24,32), +(1,6,36,76,53,70,25,33), +(1,6,37,78,54,72,25,33), +(1,6,38,80,55,74,25,34), +(1,6,39,82,56,75,25,34), +(1,6,40,83,57,77,25,35), +(1,6,41,85,58,79,26,35), +(1,6,42,87,60,80,26,35), +(1,6,43,89,61,82,26,36), +(1,6,44,91,62,84,26,36), +(1,6,45,93,63,85,26,37), +(1,6,46,95,64,87,27,37), +(1,6,47,97,66,89,27,38), +(1,6,48,99,67,91,27,38), +(1,6,49,101,68,93,27,39), +(1,6,50,103,69,94,28,40), +(1,6,51,105,71,96,28,40), +(1,6,52,106,72,97,28,41), +(1,6,53,107,72,98,28,41), +(1,6,54,107,73,98,29,42), +(1,6,55,108,73,99,29,43), +(1,6,56,111,75,102,29,44), +(1,6,57,113,76,104,29,44), +(1,6,58,118,77,106,30,45), +(1,6,59,118,79,108,30,45), +(1,6,60,123,80,110,30,46), +(1,6,61,125,81,112,30,47), +(1,6,62,128,83,114,30,47), +(1,6,63,130,84,117,31,48), +(1,6,64,130,86,119,31,48), +(1,6,65,140,87,128,31,49), +(1,6,66,143,89,131,31,50), +(1,6,67,146,90,133,32,50), +(1,6,68,148,92,135,32,51), +(1,6,69,151,93,138,32,52), +(1,6,70,154,95,140,32,52), +(1,6,71,162,97,144,33,53), +(1,6,72,164,98,146,33,54), +(1,6,73,165,100,148,33,55), +(1,6,74,166,102,151,33,55), +(1,6,75,169,103,154,34,56), +(1,6,76,172,105,157,34,57), +(1,6,77,175,107,157,34,58), +(1,6,78,176,108,157,34,58), +(1,6,79,177,110,157,35,59), +(1,6,80,180,112,160,35,60), + +(1,8,1,20,20,20,23,22), +(1,8,2,20,20,20,24,23), +(1,8,3,20,20,21,26,25), +(1,8,4,20,20,21,27,26), +(1,8,5,20,21,21,28,27), +(1,8,6,20,21,21,30,29), +(1,8,7,21,21,22,31,30), +(1,8,8,21,21,22,33,31), +(1,8,9,21,21,22,34,33), +(1,8,10,21,21,23,36,34), +(1,8,11,21,22,23,37,36), +(1,8,12,21,22,23,39,37), +(1,8,13,21,22,24,40,38), +(1,8,14,21,22,24,42,40), +(1,8,15,21,22,24,43,41), +(1,8,16,21,23,25,45,43), +(1,8,17,22,23,25,46,44), +(1,8,18,22,23,25,48,46), +(1,8,19,22,23,26,49,47), +(1,8,20,22,23,26,51,49), +(1,8,21,22,24,26,53,51), +(1,8,22,22,24,27,54,52), +(1,8,23,22,24,27,56,54), +(1,8,24,23,24,28,58,55), +(1,8,25,23,25,28,59,57), +(1,8,26,23,25,28,61,59), +(1,8,27,23,25,29,63,60), +(1,8,28,23,25,29,65,62), +(1,8,29,23,25,30,66,64), +(1,8,30,24,26,30,68,65), +(1,8,31,24,26,30,70,67), +(1,8,32,24,26,31,72,69), +(1,8,33,24,27,31,73,70), +(1,8,34,24,27,32,75,72), +(1,8,35,24,27,32,77,74), +(1,8,36,25,27,33,79,76), +(1,8,37,25,28,33,81,78), +(1,8,38,25,28,34,83,79), +(1,8,39,25,28,34,85,81), +(1,8,40,25,28,35,87,83), +(1,8,41,26,29,35,88,85), +(1,8,42,26,29,35,90,87), +(1,8,43,26,29,36,92,89), +(1,8,44,26,30,36,94,91), +(1,8,45,26,30,37,96,92), +(1,8,46,27,30,37,98,94), +(1,8,47,27,31,38,100,96), +(1,8,48,27,31,38,102,98), +(1,8,49,27,31,39,104,100), +(1,8,50,28,32,40,106,102), +(1,8,51,28,32,40,109,104), +(1,8,52,28,32,41,111,106), +(1,8,53,28,33,41,113,108), +(1,8,54,29,33,42,115,110), +(1,8,55,29,33,42,117,112), +(1,8,56,29,34,43,119,114), +(1,8,57,29,34,43,121,117), +(1,8,58,30,34,44,124,119), +(1,8,59,30,35,44,126,121), +(1,8,60,30,35,45,128,123), +(1,8,61,30,35,46,130,125), +(1,8,62,31,36,46,132,127), +(1,8,63,31,36,47,135,129), +(1,8,64,31,37,47,137,132), +(1,8,65,32,37,48,139,134), +(1,8,66,32,37,49,142,136), +(1,8,67,32,38,49,144,138), +(1,8,68,32,38,50,146,140), +(1,8,69,33,39,50,149,143), +(1,8,70,33,39,51,151,145), +(1,8,71,33,39,52,154,152), +(1,8,72,33,40,53,160,155), +(1,8,73,33,40,54,160,158), +(1,8,74,34,41,54,163,160), +(1,8,75,34,41,55,166,163), +(1,8,76,34,41,56,169,166), +(1,8,77,35,42,57,172,169), +(1,8,78,35,42,57,175,173), +(1,8,79,35,43,58,178,176), +(1,8,80,36,43,59,181,179), + +(1,9,1,20,20,21,22,22), +(1,9,2,20,20,22,23,23), +(1,9,3,21,21,22,24,24), +(1,9,4,21,21,23,26,25), +(1,9,5,21,21,23,27,27), +(1,9,6,21,22,24,28,28), +(1,9,7,22,22,24,29,29), +(1,9,8,22,23,25,30,30), +(1,9,9,22,23,26,32,31), +(1,9,10,23,23,26,33,33), +(1,9,11,23,24,27,34,34), +(1,9,12,23,24,27,35,35), +(1,9,13,24,25,28,37,36), +(1,9,14,24,25,29,38,38), +(1,9,15,24,25,29,39,39), +(1,9,16,25,26,30,41,40), +(1,9,17,25,26,31,42,42), +(1,9,18,25,27,31,43,43), +(1,9,19,26,27,32,45,44), +(1,9,20,26,28,33,46,46), +(1,9,21,26,28,33,48,47), +(1,9,22,27,29,34,49,49), +(1,9,23,27,29,35,51,50), +(1,9,24,28,30,35,52,51), +(1,9,25,28,30,36,53,53), +(1,9,26,28,31,37,55,54), +(1,9,27,29,31,37,56,56), +(1,9,28,29,32,38,58,57), +(1,9,29,30,32,39,59,59), +(1,9,30,30,33,40,61,60), +(1,9,31,30,33,40,62,62), +(1,9,32,31,34,41,64,63), +(1,9,33,31,34,42,66,65), +(1,9,34,32,35,43,67,66), +(1,9,35,32,35,44,69,68), +(1,9,36,33,36,44,70,69), +(1,9,37,33,36,45,72,71), +(1,9,38,34,37,46,74,73), +(1,9,39,34,38,47,75,74), +(1,9,40,35,38,48,77,76), +(1,9,41,35,39,48,79,78), +(1,9,42,35,39,49,80,79), +(1,9,43,36,40,50,82,81), +(1,9,44,36,40,51,84,83), +(1,9,45,37,41,52,85,84), +(1,9,46,37,42,53,87,86), +(1,9,47,38,42,54,89,88), +(1,9,48,38,43,55,91,89), +(1,9,49,39,44,55,93,91), +(1,9,50,40,44,56,94,93), +(1,9,51,40,45,57,96,95), +(1,9,52,41,45,58,98,97), +(1,9,53,41,46,59,100,98), +(1,9,54,42,47,60,102,100), +(1,9,55,42,47,61,103,102), +(1,9,56,43,48,62,105,104), +(1,9,57,43,49,63,107,106), +(1,9,58,44,49,64,109,108), +(1,9,59,44,50,65,111,109), +(1,9,60,45,51,66,113,111), +(1,9,61,46,51,67,115,113), +(1,9,62,46,52,68,117,115), +(1,9,63,47,53,69,119,117), +(1,9,64,47,54,70,121,119), +(1,9,65,48,54,71,123,121), +(1,9,66,49,55,72,125,123), +(1,9,67,49,56,73,127,125), +(1,9,68,50,57,74,129,127), +(1,9,69,50,57,75,131,129), +(1,9,70,51,58,76,133,131), +(1,9,71,52,59,78,135,146), +(1,9,72,53,59,79,138,148), +(1,9,73,54,60,80,140,151), +(1,9,74,54,61,89,143,154), +(1,9,75,55,62,91,145,156), +(1,9,76,56,63,92,148,159), +(1,9,77,57,64,93,151,162), +(1,9,78,57,65,95,153,165), +(1,9,79,58,66,96,156,168), +(1,9,80,59,67,97,159,170), + +(2,1,1,26,17,24,17,23), +(2,1,2,27,18,25,17,23), +(2,1,3,29,19,26,17,24), +(2,1,4,30,19,27,17,24), +(2,1,5,31,20,29,17,24), +(2,1,6,32,21,30,17,24), +(2,1,7,34,22,31,18,25), +(2,1,8,35,23,32,18,25), +(2,1,9,37,24,34,18,25), +(2,1,10,38,24,35,18,26), +(2,1,11,39,25,36,18,26), +(2,1,12,41,26,37,18,26), +(2,1,13,42,27,39,18,27), +(2,1,14,44,28,40,18,27), +(2,1,15,45,29,41,18,27), +(2,1,16,47,30,43,19,28), +(2,1,17,48,31,44,19,28), +(2,1,18,50,32,45,19,28), +(2,1,19,51,33,47,19,29), +(2,1,20,53,34,48,19,29), +(2,1,21,54,34,50,19,29), +(2,1,22,56,35,51,19,30), +(2,1,23,57,36,52,20,30), +(2,1,24,59,37,54,20,30), +(2,1,25,60,38,55,20,31), +(2,1,26,62,39,57,20,31), +(2,1,27,64,40,58,20,32), +(2,1,28,65,41,60,20,32), +(2,1,29,67,43,61,21,32), +(2,1,30,69,44,63,21,33), +(2,1,31,70,45,64,21,33), +(2,1,32,72,46,66,21,34), +(2,1,33,74,47,67,21,34), +(2,1,34,76,48,69,21,35), +(2,1,35,77,49,71,22,35), +(2,1,36,79,50,72,22,36), +(2,1,37,81,51,74,22,36), +(2,1,38,83,52,76,22,36), +(2,1,39,84,53,77,22,37), +(2,1,40,86,55,79,23,37), +(2,1,41,88,56,81,23,38), +(2,1,42,90,57,82,23,38), +(2,1,43,92,58,84,23,39), +(2,1,44,94,59,86,23,39), +(2,1,45,96,60,87,24,40), +(2,1,46,98,62,89,24,40), +(2,1,47,100,63,91,24,41), +(2,1,48,101,64,93,24,41), +(2,1,49,103,65,94,25,42), +(2,1,50,105,66,96,25,42), +(2,1,51,107,68,98,25,43), +(2,1,52,109,69,100,25,43), +(2,1,53,111,70,102,25,44), +(2,1,54,113,71,104,26,45), +(2,1,55,115,73,105,26,45), +(2,1,56,118,74,107,26,46), +(2,1,57,120,75,109,26,46), +(2,1,58,122,77,111,27,47), +(2,1,59,124,78,113,27,47), +(2,1,60,126,79,115,27,48), +(2,1,61,128,81,117,27,48), +(2,1,62,130,82,119,28,49), +(2,1,63,132,83,121,28,50), +(2,1,64,135,85,123,28,50), +(2,1,65,137,86,125,29,51), +(2,1,66,139,87,127,29,52), +(2,1,67,141,89,129,29,52), +(2,1,68,143,90,131,29,53), +(2,1,69,146,92,133,30,53), +(2,1,70,148,93,135,30,54), +(2,1,71,157,94,142,30,55), +(2,1,72,162,96,148,30,56), +(2,1,73,165,98,150,30,57), +(2,1,74,168,99,153,31,57), +(2,1,75,170,101,154,31,58), +(2,1,76,172,103,156,31,59), +(2,1,77,174,105,159,32,60), +(2,1,78,179,106,162,32,60), +(2,1,79,184,108,167,32,61), +(2,1,80,187,110,170,33,62), + +(2,3,1,23,20,23,17,24), +(2,3,2,23,21,24,18,25), +(2,3,3,24,23,25,18,25), +(2,3,4,24,24,26,19,26), +(2,3,5,25,25,27,19,26), +(2,3,6,25,27,28,20,27), +(2,3,7,26,28,28,21,28), +(2,3,8,26,30,29,21,28), +(2,3,9,26,31,30,22,29), +(2,3,10,27,33,31,22,30), +(2,3,11,27,34,32,23,30), +(2,3,12,28,36,33,24,31), +(2,3,13,28,37,34,24,32), +(2,3,14,29,39,35,25,33), +(2,3,15,29,40,36,26,33), +(2,3,16,30,42,37,26,34), +(2,3,17,30,43,39,27,35), +(2,3,18,31,45,40,28,35), +(2,3,19,31,47,41,28,36), +(2,3,20,32,48,42,29,37), +(2,3,21,32,50,43,30,38), +(2,3,22,33,51,44,31,39), +(2,3,23,34,53,45,31,39), +(2,3,24,34,55,46,32,40), +(2,3,25,35,57,47,33,41), +(2,3,26,35,58,48,34,42), +(2,3,27,36,60,50,34,43), +(2,3,28,36,62,51,35,43), +(2,3,29,37,63,52,36,44), +(2,3,30,38,65,53,37,45), +(2,3,31,38,67,54,37,46), +(2,3,32,39,69,56,38,47), +(2,3,33,39,71,57,39,48), +(2,3,34,40,72,58,40,49), +(2,3,35,41,74,59,41,49), +(2,3,36,41,76,61,42,50), +(2,3,37,42,78,62,42,51), +(2,3,38,43,80,63,43,52), +(2,3,39,43,82,64,44,53), +(2,3,40,44,84,66,45,54), +(2,3,41,45,86,67,46,55), +(2,3,42,45,88,68,47,56), +(2,3,43,46,90,70,47,57), +(2,3,44,47,91,71,48,58), +(2,3,45,47,93,72,49,59), +(2,3,46,48,95,74,50,60), +(2,3,47,49,98,75,51,61), +(2,3,48,50,100,77,52,62), +(2,3,49,50,102,78,53,63), +(2,3,50,51,104,79,54,64), +(2,3,51,52,106,81,55,65), +(2,3,52,52,108,82,56,66), +(2,3,53,53,110,84,57,67), +(2,3,54,54,112,85,58,68), +(2,3,55,55,114,87,59,69), +(2,3,56,55,116,88,60,70), +(2,3,57,56,118,90,61,71), +(2,3,58,57,121,91,62,72), +(2,3,59,58,123,93,63,73), +(2,3,60,59,125,94,64,74), +(2,3,61,59,127,96,65,76), +(2,3,62,60,130,97,66,77), +(2,3,63,61,132,99,67,78), +(2,3,64,62,134,100,68,79), +(2,3,65,63,136,102,69,80), +(2,3,66,64,139,104,70,81), +(2,3,67,64,141,105,71,82), +(2,3,68,65,143,107,72,84), +(2,3,69,66,146,108,73,85), +(2,3,70,67,148,110,74,86), +(2,3,71,68,151,112,75,87), +(2,3,72,69,154,114,76,88), +(2,3,73,70,157,116,77,90), +(2,3,74,71,160,118,79,91), +(2,3,75,72,163,120,80,93), +(2,3,76,73,166,122,81,94), +(2,3,77,74,169,124,83,96), +(2,3,78,75,172,126,84,97), +(2,3,79,76,175,128,85,99), +(2,3,80,77,178,130,87,100), + +(2,4,1,24,20,23,17,23), +(2,4,2,25,21,24,17,23), +(2,4,3,25,23,24,17,24), +(2,4,4,26,24,25,17,24), +(2,4,5,27,26,26,18,24), +(2,4,6,28,27,26,18,25), +(2,4,7,29,29,27,18,25), +(2,4,8,29,30,28,18,26), +(2,4,9,30,32,29,18,26), +(2,4,10,31,33,29,19,26), +(2,4,11,32,35,30,19,27), +(2,4,12,33,37,31,19,27), +(2,4,13,34,38,32,19,28), +(2,4,14,34,40,32,19,28), +(2,4,15,35,41,33,19,28), +(2,4,16,36,43,34,20,29), +(2,4,17,37,45,35,20,29), +(2,4,18,38,46,36,20,30), +(2,4,19,39,48,37,20,30), +(2,4,20,40,50,37,21,31), +(2,4,21,41,52,38,21,31), +(2,4,22,42,53,39,21,31), +(2,4,23,43,55,40,21,32), +(2,4,24,43,57,41,21,32), +(2,4,25,44,59,42,22,33), +(2,4,26,45,60,43,22,33), +(2,4,27,46,62,44,22,34), +(2,4,28,47,64,44,22,34), +(2,4,29,48,66,45,23,35), +(2,4,30,49,68,46,23,35), +(2,4,31,50,70,47,23,36), +(2,4,32,51,72,48,23,36), +(2,4,33,53,73,49,24,37), +(2,4,34,54,75,50,24,38), +(2,4,35,55,77,51,24,38), +(2,4,36,56,79,52,24,39), +(2,4,37,57,81,53,25,39), +(2,4,38,58,83,54,25,40), +(2,4,39,59,85,55,25,40), +(2,4,40,60,87,56,26,41), +(2,4,41,61,89,57,26,41), +(2,4,42,62,91,58,26,42), +(2,4,43,63,93,59,27,43), +(2,4,44,65,95,60,27,43), +(2,4,45,66,98,61,27,44), +(2,4,46,67,100,62,27,44), +(2,4,47,68,102,64,28,45), +(2,4,48,69,104,65,28,46), +(2,4,49,71,106,66,28,46), +(2,4,50,72,108,67,29,47), +(2,4,51,73,110,68,29,48), +(2,4,52,74,113,69,29,48), +(2,4,53,75,115,70,30,49), +(2,4,54,77,117,71,30,50), +(2,4,55,78,119,73,30,50), +(2,4,56,79,122,74,31,51), +(2,4,57,80,124,75,31,52), +(2,4,58,82,126,76,31,52), +(2,4,59,83,129,77,32,53), +(2,4,60,84,131,78,32,54), +(2,4,61,86,133,80,33,54), +(2,4,62,87,136,81,33,55), +(2,4,63,88,138,82,33,56), +(2,4,64,90,140,83,34,57), +(2,4,65,91,143,85,34,57), +(2,4,66,92,145,86,34,58), +(2,4,67,94,148,87,35,59), +(2,4,68,95,150,88,35,59), +(2,4,69,97,153,90,36,60), +(2,4,70,98,155,91,36,61), +(2,4,71,100,158,92,36,62), +(2,4,72,102,161,94,37,62), +(2,4,73,103,164,99,37,63), +(2,4,74,105,167,100,38,64), +(2,4,75,107,170,102,38,65), +(2,4,76,108,173,102,38,66), +(2,4,77,110,176,102,39,67), +(2,4,78,112,180,103,39,68), +(2,4,79,114,183,105,40,69), +(2,4,80,116,186,107,40,70), + +(2,6,1,26,17,24,17,23), +(2,6,2,27,18,25,17,23), +(2,6,3,29,19,26,17,24), +(2,6,4,30,19,27,17,24), +(2,6,5,31,20,29,17,24), +(2,6,6,32,21,30,17,24), +(2,6,7,34,22,31,18,25), +(2,6,8,35,23,32,18,25), +(2,6,9,37,24,34,18,25), +(2,6,10,38,24,35,18,26), +(2,6,11,39,25,36,18,26), +(2,6,12,41,26,37,18,26), +(2,6,13,42,27,39,18,27), +(2,6,14,44,28,40,18,27), +(2,6,15,45,29,41,18,27), +(2,6,16,47,30,43,19,28), +(2,6,17,48,31,44,19,28), +(2,6,18,50,32,45,19,28), +(2,6,19,51,33,47,19,29), +(2,6,20,53,34,48,19,29), +(2,6,21,54,34,50,19,29), +(2,6,22,56,35,51,19,30), +(2,6,23,57,36,52,20,30), +(2,6,24,59,37,54,20,30), +(2,6,25,60,38,55,20,31), +(2,6,26,62,39,57,20,31), +(2,6,27,64,40,58,20,32), +(2,6,28,65,41,60,20,32), +(2,6,29,67,43,61,21,32), +(2,6,30,69,44,63,21,33), +(2,6,31,70,45,64,21,33), +(2,6,32,72,46,66,21,34), +(2,6,33,74,47,67,21,34), +(2,6,34,76,48,69,21,35), +(2,6,35,77,49,71,22,35), +(2,6,36,79,50,72,22,36), +(2,6,37,81,51,74,22,36), +(2,6,38,83,52,76,22,36), +(2,6,39,84,53,77,22,37), +(2,6,40,86,55,79,23,37), +(2,6,41,88,56,81,23,38), +(2,6,42,90,57,82,23,38), +(2,6,43,92,58,84,23,39), +(2,6,44,94,59,86,23,39), +(2,6,45,96,60,87,24,40), +(2,6,46,98,62,89,24,40), +(2,6,47,100,63,91,24,41), +(2,6,48,101,64,93,24,41), +(2,6,49,103,65,94,25,42), +(2,6,50,105,66,96,25,42), +(2,6,51,107,68,98,25,43), +(2,6,52,109,69,100,25,43), +(2,6,53,110,69,100,25,44), +(2,6,54,111,70,101,26,45), +(2,6,55,111,70,101,26,45), +(2,6,56,114,72,104,26,46), +(2,6,57,116,73,106,26,46), +(2,6,58,118,74,108,27,47), +(2,6,59,124,76,110,27,47), +(2,6,60,126,77,112,27,48), +(2,6,61,128,78,114,27,49), +(2,6,62,131,80,116,27,49), +(2,6,63,133,81,119,28,50), +(2,6,64,136,83,121,28,50), +(2,6,65,136,84,123,28,51), +(2,6,66,142,86,126,28,52), +(2,6,67,145,87,128,29,52), +(2,6,68,147,89,130,29,53), +(2,6,69,150,90,133,29,54), +(2,6,70,157,92,135,29,54), +(2,6,71,160,94,138,30,55), +(2,6,72,163,95,140,30,56), +(2,6,73,166,97,151,30,57), +(2,6,74,169,99,154,30,57), +(2,6,75,172,100,156,31,58), +(2,6,76,175,102,160,31,59), +(2,6,77,179,104,162,31,60), +(2,6,78,182,105,165,31,60), +(2,6,79,191,107,168,32,61), +(2,6,80,194,109,171,32,62), + +(2,7,1,24,17,23,18,25), +(2,7,2,25,17,24,19,26), +(2,7,3,26,18,25,20,27), +(2,7,4,26,18,26,21,28), +(2,7,5,27,19,27,22,29), +(2,7,6,28,19,28,23,30), +(2,7,7,29,20,29,24,31), +(2,7,8,30,20,30,25,32), +(2,7,9,31,21,31,26,33), +(2,7,10,32,21,32,27,34), +(2,7,11,33,22,33,28,36), +(2,7,12,34,22,34,29,37), +(2,7,13,34,23,35,30,38), +(2,7,14,35,23,36,31,39), +(2,7,15,36,24,37,32,40), +(2,7,16,37,24,39,33,41), +(2,7,17,38,25,40,34,43), +(2,7,18,39,25,41,35,44), +(2,7,19,40,26,42,36,45), +(2,7,20,41,26,43,37,46), +(2,7,21,42,27,44,38,47), +(2,7,22,43,27,45,39,49), +(2,7,23,44,28,47,40,50), +(2,7,24,45,28,48,41,51), +(2,7,25,47,29,49,43,52), +(2,7,26,48,30,50,44,54), +(2,7,27,49,30,52,45,55), +(2,7,28,50,31,53,46,56), +(2,7,29,51,31,54,47,58), +(2,7,30,52,32,55,48,59), +(2,7,31,53,33,57,50,60), +(2,7,32,54,33,58,51,62), +(2,7,33,55,34,59,52,63), +(2,7,34,57,34,61,53,65), +(2,7,35,58,35,62,55,66), +(2,7,36,59,36,63,56,67), +(2,7,37,60,36,65,57,69), +(2,7,38,61,37,66,58,70), +(2,7,39,62,38,67,60,72), +(2,7,40,64,38,69,61,73), +(2,7,41,65,39,70,62,75), +(2,7,42,66,40,72,64,76), +(2,7,43,67,40,73,65,78), +(2,7,44,69,41,74,66,79), +(2,7,45,70,42,76,68,81), +(2,7,46,71,42,77,69,82), +(2,7,47,72,43,79,70,84), +(2,7,48,74,44,80,72,85), +(2,7,49,75,45,82,73,87), +(2,7,50,76,45,83,75,89), +(2,7,51,78,46,85,76,90), +(2,7,52,79,47,86,77,92), +(2,7,53,80,47,88,79,93), +(2,7,54,82,48,90,80,95), +(2,7,55,83,49,91,82,97), +(2,7,56,85,50,93,83,98), +(2,7,57,86,50,94,85,100), +(2,7,58,87,51,96,86,102), +(2,7,59,89,52,97,88,103), +(2,7,60,90,53,99,89,105), +(2,7,61,92,54,101,91,107), +(2,7,62,93,54,102,92,109), +(2,7,63,95,55,104,94,110), +(2,7,64,96,56,106,95,112), +(2,7,65,97,57,107,97,114), +(2,7,66,99,58,109,99,116), +(2,7,67,100,58,111,100,118), +(2,7,68,102,59,113,102,119), +(2,7,69,103,60,114,103,121), +(2,7,70,105,61,116,105,123), +(2,7,71,106,62,118,117,125), +(2,7,72,108,63,120,119,128), +(2,7,73,110,64,122,122,130), +(2,7,74,112,65,125,124,132), +(2,7,75,114,66,127,126,134), +(2,7,76,116,67,129,128,137), +(2,7,77,117,68,131,128,139), +(2,7,78,119,69,133,133,141), +(2,7,79,121,70,136,135,144), +(2,7,80,123,71,138,137,146), + +(2,9,1,23,17,23,19,25), +(2,9,2,23,17,24,20,26), +(2,9,3,24,18,24,21,27), +(2,9,4,24,18,25,23,28), +(2,9,5,24,18,25,24,30), +(2,9,6,24,19,26,25,31), +(2,9,7,25,19,26,26,32), +(2,9,8,25,20,27,27,33), +(2,9,9,25,20,27,29,34), +(2,9,10,26,20,28,30,36), +(2,9,11,26,21,29,31,37), +(2,9,12,26,21,29,33,38), +(2,9,13,27,22,30,34,39), +(2,9,14,27,22,31,35,41), +(2,9,15,27,23,31,37,42), +(2,9,16,28,23,32,38,43), +(2,9,17,28,23,32,39,45), +(2,9,18,28,24,33,41,46), +(2,9,19,29,24,34,42,47), +(2,9,20,29,25,34,43,49), +(2,9,21,29,25,35,45,50), +(2,9,22,30,26,36,46,51), +(2,9,23,30,26,37,48,53), +(2,9,24,30,27,37,49,54), +(2,9,25,31,27,38,51,56), +(2,9,26,31,28,39,52,57), +(2,9,27,32,28,39,54,59), +(2,9,28,32,29,40,55,60), +(2,9,29,32,29,41,57,62), +(2,9,30,33,30,42,58,63), +(2,9,31,33,30,42,60,65), +(2,9,32,34,31,43,61,66), +(2,9,33,34,31,44,63,68), +(2,9,34,35,32,45,64,69), +(2,9,35,35,32,45,66,71), +(2,9,36,36,33,46,68,72), +(2,9,37,36,34,47,69,74), +(2,9,38,36,34,48,71,76), +(2,9,39,37,35,49,72,77), +(2,9,40,37,35,50,74,79), +(2,9,41,38,36,50,76,80), +(2,9,42,38,36,51,77,82), +(2,9,43,39,37,52,79,84), +(2,9,44,39,38,53,81,85), +(2,9,45,40,38,54,83,87), +(2,9,46,40,39,55,84,89), +(2,9,47,41,39,56,86,91), +(2,9,48,41,40,56,88,92), +(2,9,49,42,41,57,90,94), +(2,9,50,42,41,58,91,96), +(2,9,51,43,42,59,93,98), +(2,9,52,43,43,60,95,99), +(2,9,53,44,43,61,97,101), +(2,9,54,45,44,62,99,103), +(2,9,55,45,45,63,101,105), +(2,9,56,46,45,64,102,107), +(2,9,57,46,46,65,104,109), +(2,9,58,47,47,66,106,110), +(2,9,59,47,47,67,108,112), +(2,9,60,48,48,68,110,114), +(2,9,61,48,49,69,112,116), +(2,9,62,49,49,70,114,118), +(2,9,63,50,50,71,116,120), +(2,9,64,50,51,72,118,122), +(2,9,65,51,51,73,120,124), +(2,9,66,52,52,74,122,126), +(2,9,67,52,53,75,124,128), +(2,9,68,53,54,76,126,130), +(2,9,69,53,54,77,128,132), +(2,9,70,54,55,78,130,134), +(2,9,71,55,56,88,134,145), +(2,9,72,56,56,89,135,147), +(2,9,73,57,57,90,137,150), +(2,9,74,57,58,91,142,153), +(2,9,75,58,59,93,142,155), +(2,9,76,59,60,94,145,158), +(2,9,77,60,61,95,148,161), +(2,9,78,60,62,97,150,164), +(2,9,79,61,63,98,153,167), +(2,9,80,62,64,99,156,169), + +(3,1,1,25,16,25,19,19), +(3,1,2,26,17,26,19,19), +(3,1,3,28,18,27,19,20), +(3,1,4,29,18,28,19,20), +(3,1,5,30,19,30,19,20), +(3,1,6,31,20,31,19,20), +(3,1,7,33,21,32,20,21), +(3,1,8,34,22,33,20,21), +(3,1,9,36,23,35,20,21), +(3,1,10,37,23,36,20,22), +(3,1,11,38,24,37,20,22), +(3,1,12,40,25,38,20,22), +(3,1,13,41,26,40,20,23), +(3,1,14,43,27,41,20,23), +(3,1,15,44,28,42,20,23), +(3,1,16,46,29,44,21,24), +(3,1,17,47,30,45,21,24), +(3,1,18,49,31,46,21,24), +(3,1,19,50,32,48,21,25), +(3,1,20,52,33,49,21,25), +(3,1,21,53,34,51,21,26), +(3,1,22,55,34,52,21,26), +(3,1,23,56,35,53,21,26), +(3,1,24,58,36,55,22,27), +(3,1,25,59,37,56,22,27), +(3,1,26,61,38,58,22,27), +(3,1,27,63,39,59,22,28), +(3,1,28,64,41,61,22,28), +(3,1,29,66,42,62,22,29), +(3,1,30,68,43,64,23,29), +(3,1,31,69,44,65,23,30), +(3,1,32,71,45,67,23,30), +(3,1,33,73,46,68,23,30), +(3,1,34,75,47,70,23,31), +(3,1,35,76,48,72,24,31), +(3,1,36,78,49,73,24,32), +(3,1,37,80,50,75,24,32), +(3,1,38,82,51,76,24,33), +(3,1,39,84,52,78,24,33), +(3,1,40,85,54,80,24,34), +(3,1,41,87,55,81,25,34), +(3,1,42,89,56,83,25,35), +(3,1,43,91,57,85,25,35), +(3,1,44,93,58,87,25,36), +(3,1,45,95,59,88,26,36), +(3,1,46,97,61,90,26,37), +(3,1,47,99,62,92,26,37), +(3,1,48,101,63,94,26,38), +(3,1,49,102,64,95,26,38), +(3,1,50,104,65,97,27,39), +(3,1,51,106,67,99,27,39), +(3,1,52,108,68,101,27,40), +(3,1,53,110,69,103,27,40), +(3,1,54,112,70,104,28,41), +(3,1,55,115,72,106,28,41), +(3,1,56,117,73,108,28,42), +(3,1,57,119,74,110,28,42), +(3,1,58,121,76,112,29,43), +(3,1,59,123,77,114,29,43), +(3,1,60,125,78,116,29,44), +(3,1,61,127,80,118,29,45), +(3,1,62,129,81,120,30,45), +(3,1,63,131,82,122,30,46), +(3,1,64,134,84,124,30,46), +(3,1,65,136,85,126,31,47), +(3,1,66,138,86,128,31,48), +(3,1,67,140,88,130,31,48), +(3,1,68,142,89,132,31,49), +(3,1,69,145,91,134,32,49), +(3,1,70,147,92,136,32,50), +(3,1,71,150,93,138,32,51), +(3,1,72,152,95,141,32,52), +(3,1,73,164,97,151,32,53), +(3,1,74,164,98,151,33,53), +(3,1,75,170,100,156,33,54), +(3,1,76,173,102,160,33,55), +(3,1,77,173,104,160,34,56), +(3,1,78,176,105,162,34,56), +(3,1,79,183,107,168,34,57), +(3,1,80,186,109,171,35,58), + +(3,2,1,24,16,25,19,20), +(3,2,2,25,17,26,20,21), +(3,2,3,26,17,27,20,21), +(3,2,4,27,18,28,21,22), +(3,2,5,28,18,29,22,23), +(3,2,6,29,19,30,22,24), +(3,2,7,31,20,31,23,24), +(3,2,8,32,20,32,24,25), +(3,2,9,33,21,33,24,26), +(3,2,10,34,21,34,25,26), +(3,2,11,35,22,36,26,27), +(3,2,12,36,23,37,26,28), +(3,2,13,38,23,38,27,29), +(3,2,14,39,24,39,28,30), +(3,2,15,40,25,40,29,30), +(3,2,16,41,25,41,29,31), +(3,2,17,43,26,43,30,32), +(3,2,18,44,27,44,31,33), +(3,2,19,45,28,45,32,34), +(3,2,20,47,28,46,32,35), +(3,2,21,48,29,47,33,35), +(3,2,22,49,30,49,34,36), +(3,2,23,51,30,50,35,37), +(3,2,24,52,31,51,36,38), +(3,2,25,53,32,52,36,39), +(3,2,26,55,33,54,37,40), +(3,2,27,56,33,55,38,41), +(3,2,28,57,34,56,39,42), +(3,2,29,59,35,58,40,43), +(3,2,30,60,36,59,41,43), +(3,2,31,62,37,60,42,44), +(3,2,32,63,37,62,42,45), +(3,2,33,65,38,63,43,46), +(3,2,34,66,39,65,44,47), +(3,2,35,68,40,66,45,48), +(3,2,36,69,41,67,46,49), +(3,2,37,71,41,69,47,50), +(3,2,38,72,42,70,48,51), +(3,2,39,74,43,72,49,52), +(3,2,40,75,44,73,50,53), +(3,2,41,77,45,75,51,54), +(3,2,42,78,46,76,52,55), +(3,2,43,80,47,78,53,56), +(3,2,44,82,47,79,54,57), +(3,2,45,83,48,81,55,59), +(3,2,46,85,49,82,56,60), +(3,2,47,87,50,84,57,61), +(3,2,48,88,51,85,58,62), +(3,2,49,90,52,87,59,63), +(3,2,50,92,53,89,60,64), +(3,2,51,93,54,90,61,65), +(3,2,52,95,55,92,62,66), +(3,2,53,97,56,93,63,67), +(3,2,54,98,57,95,64,69), +(3,2,55,100,58,97,65,70), +(3,2,56,102,59,98,66,71), +(3,2,57,104,60,100,67,72), +(3,2,58,106,61,102,68,73), +(3,2,59,107,62,103,69,74), +(3,2,60,109,63,105,70,76), +(3,2,61,111,64,107,72,77), +(3,2,62,113,65,109,73,78), +(3,2,63,115,66,110,74,79), +(3,2,64,117,67,112,75,80), +(3,2,65,118,68,114,76,82), +(3,2,66,120,69,116,77,83), +(3,2,67,122,70,118,78,84), +(3,2,68,124,71,119,80,85), +(3,2,69,126,72,121,81,87), +(3,2,70,128,73,123,82,88), +(3,2,71,150,74,125,83,89), +(3,2,72,152,75,128,85,91), +(3,2,73,156,76,130,86,93), +(3,2,74,158,78,132,88,94), +(3,2,75,161,79,134,89,96), +(3,2,76,164,80,137,91,97), +(3,2,77,166,82,139,92,99), +(3,2,78,170,83,141,94,101), +(3,2,79,172,84,144,95,102), +(3,2,80,175,86,146,97,104), + +(3,3,1,22,19,24,19,20), +(3,3,2,22,20,25,20,21), +(3,3,3,23,22,26,20,21), +(3,3,4,23,23,27,21,22), +(3,3,5,24,25,28,21,23), +(3,3,6,24,26,29,22,23), +(3,3,7,25,27,29,23,24), +(3,3,8,25,29,30,23,25), +(3,3,9,25,30,31,24,25), +(3,3,10,26,32,32,24,26), +(3,3,11,26,33,33,25,27), +(3,3,12,27,35,34,26,27), +(3,3,13,27,36,35,26,28), +(3,3,14,28,38,36,27,29), +(3,3,15,28,39,37,28,29), +(3,3,16,29,41,38,28,30), +(3,3,17,29,42,39,29,31), +(3,3,18,30,44,41,30,32), +(3,3,19,30,46,42,30,32), +(3,3,20,31,47,43,31,33), +(3,3,21,32,49,44,32,34), +(3,3,22,32,51,45,33,35), +(3,3,23,33,52,46,33,36), +(3,3,24,33,54,47,34,36), +(3,3,25,34,56,48,35,37), +(3,3,26,34,57,49,35,38), +(3,3,27,35,59,51,36,39), +(3,3,28,35,61,52,37,40), +(3,3,29,36,63,53,38,40), +(3,3,30,37,64,54,39,41), +(3,3,31,37,66,55,39,42), +(3,3,32,38,68,57,40,43), +(3,3,33,38,70,58,41,44), +(3,3,34,39,71,59,42,45), +(3,3,35,40,73,60,43,46), +(3,3,36,40,75,62,43,47), +(3,3,37,41,77,63,44,47), +(3,3,38,42,79,64,45,48), +(3,3,39,42,81,65,46,49), +(3,3,40,43,83,67,47,50), +(3,3,41,44,85,68,48,51), +(3,3,42,44,87,69,49,52), +(3,3,43,45,89,71,49,53), +(3,3,44,46,91,72,50,54), +(3,3,45,46,93,73,51,55), +(3,3,46,47,95,75,52,56), +(3,3,47,48,97,76,53,57), +(3,3,48,49,99,78,54,58), +(3,3,49,49,101,79,55,59), +(3,3,50,50,103,80,56,60), +(3,3,51,51,105,82,57,61), +(3,3,52,51,107,83,58,62), +(3,3,53,52,109,85,59,63), +(3,3,54,53,111,86,60,64), +(3,3,55,54,113,88,61,65), +(3,3,56,55,115,89,62,66), +(3,3,57,55,118,91,62,67), +(3,3,58,56,120,92,63,68), +(3,3,59,57,122,94,64,70), +(3,3,60,58,124,95,65,71), +(3,3,61,58,126,97,67,72), +(3,3,62,59,129,98,68,73), +(3,3,63,60,131,100,69,74), +(3,3,64,61,133,101,70,75), +(3,3,65,62,135,103,71,76), +(3,3,66,63,138,105,72,77), +(3,3,67,63,140,106,73,78), +(3,3,68,64,142,108,74,80), +(3,3,69,65,145,109,75,81), +(3,3,70,66,147,111,76,82), +(3,3,71,67,150,113,77,83), +(3,3,72,68,153,115,78,84), +(3,3,73,69,156,117,79,86), +(3,3,74,70,159,119,81,87), +(3,3,75,71,162,121,82,89), +(3,3,76,72,165,123,83,90), +(3,3,77,73,168,125,85,92), +(3,3,78,74,171,127,86,93), +(3,3,79,75,174,129,87,95), +(3,3,80,76,177,131,89,96), + +(3,4,1,23,19,24,19,19), +(3,4,2,24,20,25,19,19), +(3,4,3,24,22,25,19,20), +(3,4,4,25,23,26,19,20), +(3,4,5,26,25,27,20,20), +(3,4,6,27,26,27,20,21), +(3,4,7,28,28,28,20,21), +(3,4,8,28,29,29,20,22), +(3,4,9,29,31,30,20,22), +(3,4,10,30,32,30,20,22), +(3,4,11,31,34,31,21,23), +(3,4,12,32,36,32,21,23), +(3,4,13,33,37,33,21,24), +(3,4,14,33,39,33,21,24), +(3,4,15,34,40,34,21,25), +(3,4,16,35,42,35,22,25), +(3,4,17,36,44,36,22,25), +(3,4,18,37,45,37,22,26), +(3,4,19,38,47,38,22,26), +(3,4,20,39,49,38,22,27), +(3,4,21,40,51,39,23,27), +(3,4,22,41,52,40,23,28), +(3,4,23,42,54,41,23,28), +(3,4,24,43,56,42,23,29), +(3,4,25,44,58,43,24,29), +(3,4,26,44,59,44,24,30), +(3,4,27,45,61,44,24,30), +(3,4,28,46,63,45,24,31), +(3,4,29,47,65,46,25,31), +(3,4,30,48,67,47,25,32), +(3,4,31,49,69,48,25,32), +(3,4,32,51,71,49,25,33), +(3,4,33,52,72,50,26,33), +(3,4,34,53,74,51,26,34), +(3,4,35,54,76,52,26,34), +(3,4,36,55,78,53,26,35), +(3,4,37,56,80,54,27,35), +(3,4,38,57,82,55,27,36), +(3,4,39,58,84,56,27,37), +(3,4,40,59,86,57,28,37), +(3,4,41,60,88,58,28,38), +(3,4,42,61,90,59,28,38), +(3,4,43,63,92,60,28,39), +(3,4,44,64,95,61,29,39), +(3,4,45,65,97,62,29,40), +(3,4,46,66,99,63,29,41), +(3,4,47,67,101,64,30,41), +(3,4,48,68,103,66,30,42), +(3,4,49,70,105,67,30,43), +(3,4,50,71,107,68,31,43), +(3,4,51,72,110,69,31,44), +(3,4,52,73,112,70,31,44), +(3,4,53,74,114,71,32,45), +(3,4,54,76,116,72,32,46), +(3,4,55,77,118,73,32,46), +(3,4,56,78,121,75,33,47), +(3,4,57,80,123,76,33,48), +(3,4,58,81,125,77,33,48), +(3,4,59,82,128,78,34,49), +(3,4,60,83,130,79,34,50), +(3,4,61,85,132,81,34,51), +(3,4,62,86,135,82,35,51), +(3,4,63,87,137,83,35,52), +(3,4,64,89,139,84,36,53), +(3,4,65,90,142,86,36,53), +(3,4,66,91,144,87,36,54), +(3,4,67,93,147,88,37,55), +(3,4,68,94,149,89,37,56), +(3,4,69,96,152,91,38,56), +(3,4,70,97,154,92,38,57), +(3,4,71,99,157,93,38,58), +(3,4,72,101,160,96,39,58), +(3,4,73,102,163,97,39,59), +(3,4,74,104,166,98,40,60), +(3,4,75,106,169,100,40,61), +(3,4,76,107,172,101,40,62), +(3,4,77,109,175,103,41,63), +(3,4,78,111,179,105,41,64), +(3,4,79,113,182,106,42,65), +(3,4,80,115,185,108,42,66), + +(3,5,1,22,16,23,21,22), +(3,5,2,22,16,23,22,23), +(3,5,3,22,16,24,24,25), +(3,5,4,22,17,24,25,26), +(3,5,5,23,17,24,26,27), +(3,5,6,23,17,25,28,29), +(3,5,7,23,17,25,29,30), +(3,5,8,23,18,26,30,32), +(3,5,9,23,18,26,32,33), +(3,5,10,23,18,26,33,35), +(3,5,11,24,18,27,35,36), +(3,5,12,24,19,27,36,38), +(3,5,13,24,19,28,37,39), +(3,5,14,24,19,28,39,41), +(3,5,15,24,19,28,40,42), +(3,5,16,24,20,29,42,44), +(3,5,17,25,20,29,43,45), +(3,5,18,25,20,30,45,47), +(3,5,19,25,21,30,46,49), +(3,5,20,25,21,31,48,50), +(3,5,21,25,21,31,50,52), +(3,5,22,26,22,31,51,53), +(3,5,23,26,22,32,53,55), +(3,5,24,26,22,32,54,57), +(3,5,25,26,22,33,56,58), +(3,5,26,27,23,33,58,60), +(3,5,27,27,23,34,59,62), +(3,5,28,27,23,34,61,64), +(3,5,29,27,24,35,63,65), +(3,5,30,28,24,35,64,67), +(3,5,31,28,24,36,66,69), +(3,5,32,28,25,36,68,71), +(3,5,33,28,25,37,70,72), +(3,5,34,29,26,38,71,74), +(3,5,35,29,26,38,73,76), +(3,5,36,29,26,39,75,78), +(3,5,37,29,27,39,77,80), +(3,5,38,30,27,40,78,82), +(3,5,39,30,27,40,80,84), +(3,5,40,30,28,41,82,86), +(3,5,41,31,28,41,84,88), +(3,5,42,31,29,42,86,89), +(3,5,43,31,29,43,88,91), +(3,5,44,32,29,43,90,93), +(3,5,45,32,30,44,92,95), +(3,5,46,32,30,44,93,97), +(3,5,47,32,30,45,95,99), +(3,5,48,33,31,46,97,101), +(3,5,49,33,31,46,99,103), +(3,5,50,33,32,47,101,106), +(3,5,51,34,32,48,103,108), +(3,5,52,34,33,48,105,110), +(3,5,53,35,33,49,107,112), +(3,5,54,35,33,50,109,114), +(3,5,55,35,34,50,111,116), +(3,5,56,36,34,51,113,118), +(3,5,57,36,35,52,116,120), +(3,5,58,36,35,52,118,123), +(3,5,59,37,36,53,120,125), +(3,5,60,37,36,54,122,127), +(3,5,61,37,37,54,124,129), +(3,5,62,38,37,55,126,131), +(3,5,63,38,38,56,128,134), +(3,5,64,39,38,57,131,136), +(3,5,65,39,39,57,133,138), +(3,5,66,39,39,58,135,141), +(3,5,67,40,40,59,137,143), +(3,5,68,40,40,59,139,145), +(3,5,69,41,40,60,142,148), +(3,5,70,41,41,61,144,150), +(3,5,71,41,42,62,147,153), +(3,5,72,42,42,62,150,163), +(3,5,73,42,43,63,153,166), +(3,5,74,43,43,64,155,170), +(3,5,75,43,44,65,158,173), +(3,5,76,43,45,66,161,176), +(3,5,77,44,45,67,164,179), +(3,5,78,44,46,68,167,182), +(3,5,79,45,46,69,170,184), +(3,5,80,45,47,70,173,189), + +(3,6,1,25,16,25,19,19), +(3,6,2,26,17,26,19,19), +(3,6,3,28,18,27,19,20), +(3,6,4,29,18,28,19,20), +(3,6,5,30,19,30,19,20), +(3,6,6,31,20,31,19,20), +(3,6,7,33,21,32,20,21), +(3,6,8,34,22,33,20,21), +(3,6,9,36,23,35,20,21), +(3,6,10,37,23,36,20,22), +(3,6,11,38,24,37,20,22), +(3,6,12,40,25,38,20,22), +(3,6,13,41,26,40,20,23), +(3,6,14,43,27,41,20,23), +(3,6,15,44,28,42,20,23), +(3,6,16,46,29,44,21,24), +(3,6,17,47,30,45,21,24), +(3,6,18,49,31,46,21,24), +(3,6,19,50,32,48,21,25), +(3,6,20,52,33,49,21,25), +(3,6,21,53,34,51,21,26), +(3,6,22,55,34,52,21,26), +(3,6,23,56,35,53,21,26), +(3,6,24,58,36,55,22,27), +(3,6,25,59,37,56,22,27), +(3,6,26,61,38,58,22,27), +(3,6,27,63,39,59,22,28), +(3,6,28,64,41,61,22,28), +(3,6,29,66,42,62,22,29), +(3,6,30,68,43,64,23,29), +(3,6,31,69,44,65,23,30), +(3,6,32,71,45,67,23,30), +(3,6,33,73,46,68,23,30), +(3,6,34,75,47,70,23,31), +(3,6,35,76,48,72,24,31), +(3,6,36,78,49,73,24,32), +(3,6,37,80,50,75,24,32), +(3,6,38,82,51,76,24,33), +(3,6,39,84,52,78,24,33), +(3,6,40,85,54,80,24,34), +(3,6,41,87,55,81,25,34), +(3,6,42,89,56,83,25,35), +(3,6,43,91,57,85,25,35), +(3,6,44,93,58,87,25,36), +(3,6,45,95,59,88,26,36), +(3,6,46,97,61,90,26,37), +(3,6,47,99,62,92,26,37), +(3,6,48,101,63,94,26,38), +(3,6,49,102,64,95,26,38), +(3,6,50,104,65,97,27,39), +(3,6,51,106,67,99,27,39), +(3,6,52,108,68,99,27,40), +(3,6,53,109,68,101,27,40), +(3,6,54,110,69,101,28,41), +(3,6,55,110,69,102,28,41), +(3,6,56,113,71,105,28,42), +(3,6,57,118,72,107,28,42), +(3,6,58,120,73,109,29,43), +(3,6,59,123,75,111,29,43), +(3,6,60,125,76,113,29,44), +(3,6,61,126,77,115,29,45), +(3,6,62,127,79,117,29,45), +(3,6,63,129,80,120,30,46), +(3,6,64,132,82,122,30,46), +(3,6,65,135,83,124,30,47), +(3,6,66,137,85,127,30,48), +(3,6,67,144,86,129,31,48), +(3,6,68,146,88,131,31,49), +(3,6,69,149,89,133,31,50), +(3,6,70,152,91,136,31,50), +(3,6,71,154,93,139,32,51), +(3,6,72,157,94,141,32,52), +(3,6,73,160,96,144,32,53), +(3,6,74,163,98,146,32,53), +(3,6,75,166,99,150,33,54), +(3,6,76,169,101,152,33,55), +(3,6,77,172,103,155,33,56), +(3,6,78,176,104,157,33,56), +(3,6,79,179,106,160,34,57), +(3,6,80,182,108,163,34,58), + +(4,1,1,20,25,21,20,20), +(4,1,2,21,26,22,20,20), +(4,1,3,23,27,23,20,21), +(4,1,4,24,27,25,20,21), +(4,1,5,25,28,26,20,21), +(4,1,6,27,29,27,20,21), +(4,1,7,28,30,28,21,22), +(4,1,8,29,31,29,21,22), +(4,1,9,31,31,31,21,22), +(4,1,10,32,32,32,21,23), +(4,1,11,33,33,33,21,23), +(4,1,12,35,34,34,21,23), +(4,1,13,36,35,36,21,24), +(4,1,14,38,36,37,21,24), +(4,1,15,39,37,38,21,24), +(4,1,16,41,37,40,21,25), +(4,1,17,42,38,41,22,25), +(4,1,18,44,39,43,22,25), +(4,1,19,45,40,44,22,26), +(4,1,20,47,41,45,22,26), +(4,1,21,48,42,47,22,26), +(4,1,22,50,43,48,22,27), +(4,1,23,52,44,50,22,27), +(4,1,24,53,45,51,23,28), +(4,1,25,55,46,52,23,28), +(4,1,26,56,47,54,23,28), +(4,1,27,58,48,55,23,29), +(4,1,28,60,49,57,23,29), +(4,1,29,61,50,58,23,30), +(4,1,30,63,51,60,24,30), +(4,1,31,65,52,62,24,30), +(4,1,32,66,53,63,24,31), +(4,1,33,68,54,65,24,31), +(4,1,34,70,55,66,24,32), +(4,1,35,72,56,68,24,32), +(4,1,36,73,58,69,25,33), +(4,1,37,75,59,71,25,33), +(4,1,38,77,60,73,25,34), +(4,1,39,79,61,74,25,34), +(4,1,40,81,62,76,25,35), +(4,1,41,82,63,78,26,35), +(4,1,42,84,64,79,26,35), +(4,1,43,86,66,81,26,36), +(4,1,44,88,67,83,26,36), +(4,1,45,90,68,85,26,37), +(4,1,46,92,69,86,27,37), +(4,1,47,94,70,88,27,38), +(4,1,48,96,72,90,27,38), +(4,1,49,98,73,92,27,39), +(4,1,50,100,74,93,28,40), +(4,1,51,102,75,95,28,40), +(4,1,52,104,77,97,28,41), +(4,1,53,106,78,99,28,41), +(4,1,54,108,79,101,29,42), +(4,1,55,110,80,103,29,42), +(4,1,56,112,82,104,29,43), +(4,1,57,114,83,106,29,43), +(4,1,58,116,84,108,30,44), +(4,1,59,118,86,110,30,44), +(4,1,60,120,87,112,30,45), +(4,1,61,122,88,114,30,46), +(4,1,62,124,90,116,31,46), +(4,1,63,127,91,118,31,47), +(4,1,64,129,92,120,31,47), +(4,1,65,131,94,122,32,48), +(4,1,66,133,95,124,32,49), +(4,1,67,135,97,126,32,49), +(4,1,68,138,98,128,32,50), +(4,1,69,140,100,130,33,50), +(4,1,70,142,101,132,33,51), +(4,1,71,145,102,134,33,52), +(4,1,72,147,104,137,33,53), +(4,1,73,150,106,139,33,54), +(4,1,74,153,107,142,34,54), +(4,1,75,156,109,144,34,55), +(4,1,76,159,111,148,34,56), +(4,1,77,162,113,150,35,57), +(4,1,78,165,114,152,35,57), +(4,1,79,178,116,164,35,58), +(4,1,80,181,118,167,36,59), + +(4,3,1,17,28,20,20,21), +(4,3,2,17,29,21,21,22), +(4,3,3,18,31,22,21,22), +(4,3,4,18,32,23,22,23), +(4,3,5,19,33,24,22,24), +(4,3,6,19,35,25,23,24), +(4,3,7,20,36,26,24,25), +(4,3,8,20,38,27,24,25), +(4,3,9,21,39,27,25,26), +(4,3,10,21,40,28,25,27), +(4,3,11,22,42,29,26,28), +(4,3,12,22,43,30,27,28), +(4,3,13,23,45,31,27,29), +(4,3,14,23,46,32,28,30), +(4,3,15,24,48,34,29,30), +(4,3,16,24,50,35,29,31), +(4,3,17,25,51,36,30,32), +(4,3,18,25,53,37,31,33), +(4,3,19,26,54,38,31,33), +(4,3,20,26,56,39,32,34), +(4,3,21,27,57,40,33,35), +(4,3,22,27,59,41,33,36), +(4,3,23,28,61,42,34,36), +(4,3,24,28,62,43,35,37), +(4,3,25,29,64,44,36,38), +(4,3,26,30,66,46,36,39), +(4,3,27,30,68,47,37,40), +(4,3,28,31,69,48,38,41), +(4,3,29,31,71,49,39,41), +(4,3,30,32,73,50,39,42), +(4,3,31,33,75,52,40,43), +(4,3,32,33,76,53,41,44), +(4,3,33,34,78,54,42,45), +(4,3,34,34,80,55,43,46), +(4,3,35,35,82,57,44,47), +(4,3,36,36,84,58,44,48), +(4,3,37,36,86,59,45,48), +(4,3,38,37,87,60,46,49), +(4,3,39,38,89,62,47,50), +(4,3,40,38,91,63,48,51), +(4,3,41,39,93,64,49,52), +(4,3,42,40,95,66,49,53), +(4,3,43,40,97,67,50,54), +(4,3,44,41,99,68,51,55), +(4,3,45,42,101,70,52,56), +(4,3,46,42,103,71,53,57), +(4,3,47,43,105,72,54,58), +(4,3,48,44,107,74,55,59), +(4,3,49,45,109,75,56,60), +(4,3,50,45,111,77,57,61), +(4,3,51,46,113,78,58,62), +(4,3,52,47,115,79,59,63), +(4,3,53,47,118,81,60,64), +(4,3,54,48,120,82,61,65), +(4,3,55,49,122,84,61,66), +(4,3,56,50,124,85,62,67), +(4,3,57,50,126,87,63,68), +(4,3,58,51,128,88,64,69), +(4,3,59,52,131,90,65,70), +(4,3,60,53,133,91,66,72), +(4,3,61,54,135,93,67,73), +(4,3,62,54,137,94,69,74), +(4,3,63,55,140,96,70,75), +(4,3,64,56,142,97,71,76), +(4,3,65,57,144,99,72,77), +(4,3,66,58,147,101,73,78), +(4,3,67,58,149,102,74,79), +(4,3,68,59,151,104,75,81), +(4,3,69,60,154,105,76,82), +(4,3,70,61,156,107,77,83), +(4,3,71,62,159,109,78,84), +(4,3,72,63,162,111,79,85), +(4,3,73,64,165,113,80,87), +(4,3,74,65,168,115,82,88), +(4,3,75,66,171,117,83,90), +(4,3,76,67,174,119,84,91), +(4,3,77,68,177,121,86,93), +(4,3,78,69,180,123,87,94), +(4,3,79,70,190,125,91,96), +(4,3,80,71,193,127,93,97), + +(4,4,1,18,28,20,20,20), +(4,4,2,19,29,21,20,20), +(4,4,3,20,31,21,20,21), +(4,4,4,20,32,22,20,21), +(4,4,5,21,34,23,21,21), +(4,4,6,22,35,24,21,22), +(4,4,7,23,37,24,21,22), +(4,4,8,24,38,25,21,23), +(4,4,9,24,40,26,21,23), +(4,4,10,25,41,26,21,23), +(4,4,11,26,43,27,22,24), +(4,4,12,27,44,28,22,24), +(4,4,13,28,46,29,22,25), +(4,4,14,29,48,30,22,25), +(4,4,15,29,49,30,22,25), +(4,4,16,30,51,31,23,26), +(4,4,17,31,52,32,23,26), +(4,4,18,32,54,33,23,27), +(4,4,19,33,56,34,23,27), +(4,4,20,34,57,35,23,28), +(4,4,21,35,59,35,24,28), +(4,4,22,36,61,36,24,29), +(4,4,23,37,63,37,24,29), +(4,4,24,38,64,38,24,30), +(4,4,25,39,66,39,25,30), +(4,4,26,40,68,40,25,31), +(4,4,27,41,70,41,25,31), +(4,4,28,42,72,42,25,32), +(4,4,29,43,73,43,25,32), +(4,4,30,44,75,43,26,33), +(4,4,31,45,77,44,26,33), +(4,4,32,46,79,45,26,34), +(4,4,33,47,81,46,27,34), +(4,4,34,48,83,47,27,35), +(4,4,35,49,85,48,27,35), +(4,4,36,50,87,49,27,36), +(4,4,37,51,89,50,28,36), +(4,4,38,52,91,51,28,37), +(4,4,39,53,93,52,28,38), +(4,4,40,54,95,53,28,38), +(4,4,41,56,97,54,29,39), +(4,4,42,57,99,55,29,39), +(4,4,43,58,101,56,29,40), +(4,4,44,59,103,57,30,40), +(4,4,45,60,105,59,30,41), +(4,4,46,61,107,60,30,42), +(4,4,47,62,109,61,31,42), +(4,4,48,64,112,62,31,43), +(4,4,49,65,114,63,31,44), +(4,4,50,66,116,64,32,44), +(4,4,51,67,118,65,32,45), +(4,4,52,68,120,66,32,45), +(4,4,53,70,123,67,33,46), +(4,4,54,71,125,69,33,47), +(4,4,55,72,127,70,33,47), +(4,4,56,73,129,71,34,48), +(4,4,57,75,132,72,34,49), +(4,4,58,76,134,73,34,49), +(4,4,59,77,136,74,35,50), +(4,4,60,79,139,76,35,51), +(4,4,61,80,141,77,35,51), +(4,4,62,81,143,78,36,52), +(4,4,63,82,146,79,36,53), +(4,4,64,84,148,80,37,54), +(4,4,65,85,151,82,37,54), +(4,4,66,87,153,83,37,55), +(4,4,67,88,156,84,38,56), +(4,4,68,89,158,85,38,57), +(4,4,69,91,160,87,39,57), +(4,4,70,92,163,88,39,58), +(4,4,71,94,166,90,39,59), +(4,4,72,96,169,91,40,59), +(4,4,73,97,172,93,40,60), +(4,4,74,99,175,94,41,61), +(4,4,75,101,178,96,41,62), +(4,4,76,102,181,97,41,63), +(4,4,77,104,184,99,42,64), +(4,4,78,106,188,101,42,65), +(4,4,79,108,191,102,43,66), +(4,4,80,110,194,104,43,67), + +(4,5,1,17,25,19,22,23), +(4,5,2,17,25,19,23,24), +(4,5,3,17,25,20,25,26), +(4,5,4,17,26,20,26,27), +(4,5,5,18,26,20,27,28), +(4,5,6,18,26,21,29,30), +(4,5,7,18,26,21,30,31), +(4,5,8,18,26,22,31,33), +(4,5,9,18,27,22,33,34), +(4,5,10,19,27,22,34,36), +(4,5,11,19,27,23,36,37), +(4,5,12,19,27,23,37,39), +(4,5,13,19,28,24,38,40), +(4,5,14,19,28,24,40,42), +(4,5,15,19,28,25,41,43), +(4,5,16,20,28,25,43,45), +(4,5,17,20,29,25,44,46), +(4,5,18,20,29,26,46,48), +(4,5,19,20,29,26,47,49), +(4,5,20,21,30,27,49,51), +(4,5,21,21,30,27,51,53), +(4,5,22,21,30,28,52,54), +(4,5,23,21,30,28,54,56), +(4,5,24,21,31,29,55,58), +(4,5,25,22,31,29,57,59), +(4,5,26,22,31,30,59,61), +(4,5,27,22,32,30,60,63), +(4,5,28,22,32,31,62,65), +(4,5,29,23,32,31,64,66), +(4,5,30,23,33,32,65,68), +(4,5,31,23,33,32,67,70), +(4,5,32,23,33,33,69,72), +(4,5,33,24,34,33,70,73), +(4,5,34,24,34,34,72,75), +(4,5,35,24,34,34,74,77), +(4,5,36,24,35,35,76,79), +(4,5,37,25,35,35,78,81), +(4,5,38,25,35,36,79,83), +(4,5,39,25,36,37,81,85), +(4,5,40,26,36,37,83,87), +(4,5,41,26,37,38,85,88), +(4,5,42,26,37,38,87,90), +(4,5,43,27,37,39,89,92), +(4,5,44,27,38,39,91,94), +(4,5,45,27,38,40,92,96), +(4,5,46,27,39,41,94,98), +(4,5,47,28,39,41,96,100), +(4,5,48,28,39,42,98,102), +(4,5,49,28,40,43,100,104), +(4,5,50,29,40,43,102,106), +(4,5,51,29,41,44,104,109), +(4,5,52,29,41,44,106,111), +(4,5,53,30,42,45,108,113), +(4,5,54,30,42,46,110,115), +(4,5,55,30,43,46,112,117), +(4,5,56,31,43,47,114,119), +(4,5,57,31,43,48,117,121), +(4,5,58,31,44,48,119,124), +(4,5,59,32,44,49,121,126), +(4,5,60,32,45,50,123,128), +(4,5,61,33,45,51,125,130), +(4,5,62,33,46,51,127,132), +(4,5,63,33,46,52,129,135), +(4,5,64,34,47,53,132,137), +(4,5,65,34,47,53,134,139), +(4,5,66,34,48,54,136,142), +(4,5,67,35,48,55,138,144), +(4,5,68,35,49,56,140,146), +(4,5,69,36,49,56,143,149), +(4,5,70,36,50,57,145,151), +(4,5,71,36,51,58,148,161), +(4,5,72,37,51,58,151,164), +(4,5,73,37,52,59,154,168), +(4,5,74,38,52,60,156,171), +(4,5,75,38,53,61,159,174), +(4,5,76,38,54,62,162,177), +(4,5,77,39,54,63,165,180), +(4,5,78,39,55,64,168,183), +(4,5,79,40,55,65,171,186), +(4,5,80,40,56,66,200,191), + +(4,6,1,20,25,21,20,20), +(4,6,2,21,26,22,20,20), +(4,6,3,23,27,23,20,21), +(4,6,4,24,27,25,20,21), +(4,6,5,25,28,26,20,21), +(4,6,6,27,29,27,20,21), +(4,6,7,28,30,28,21,22), +(4,6,8,29,31,29,21,22), +(4,6,9,31,31,31,21,22), +(4,6,10,32,32,32,21,23), +(4,6,11,33,33,33,21,23), +(4,6,12,35,34,34,21,23), +(4,6,13,36,35,36,21,24), +(4,6,14,38,36,37,21,24), +(4,6,15,39,37,38,21,24), +(4,6,16,41,37,40,21,25), +(4,6,17,42,38,41,22,25), +(4,6,18,44,39,43,22,25), +(4,6,19,45,40,44,22,26), +(4,6,20,47,41,45,22,26), +(4,6,21,48,42,47,22,26), +(4,6,22,50,43,48,22,27), +(4,6,23,52,44,50,22,27), +(4,6,24,53,45,51,23,28), +(4,6,25,55,46,52,23,28), +(4,6,26,56,47,54,23,28), +(4,6,27,58,48,55,23,29), +(4,6,28,60,49,57,23,29), +(4,6,29,61,50,58,23,30), +(4,6,30,63,51,60,24,30), +(4,6,31,65,52,62,24,30), +(4,6,32,66,53,63,24,31), +(4,6,33,68,54,65,24,31), +(4,6,34,70,55,66,24,32), +(4,6,35,72,56,68,24,32), +(4,6,36,73,58,69,25,33), +(4,6,37,75,59,71,25,33), +(4,6,38,77,60,73,25,34), +(4,6,39,79,61,74,25,34), +(4,6,40,81,62,76,25,35), +(4,6,41,82,63,78,26,35), +(4,6,42,84,64,79,26,35), +(4,6,43,86,66,81,26,36), +(4,6,44,88,67,83,26,36), +(4,6,45,90,68,85,26,37), +(4,6,46,92,69,86,27,37), +(4,6,47,94,70,88,27,38), +(4,6,48,96,72,90,27,38), +(4,6,49,98,73,92,27,39), +(4,6,50,100,74,93,28,40), +(4,6,51,101,75,94,28,40), +(4,6,52,102,76,95,28,41), +(4,6,53,103,77,96,28,41), +(4,6,54,104,77,97,29,42), +(4,6,55,105,78,98,29,42), +(4,6,56,108,80,101,29,43), +(4,6,57,113,81,103,29,43), +(4,6,58,115,82,105,30,44), +(4,6,59,115,84,107,30,44), +(4,6,60,120,85,109,30,45), +(4,6,61,122,86,111,30,46), +(4,6,62,122,88,113,30,46), +(4,6,63,127,89,116,31,47), +(4,6,64,127,91,118,31,47), +(4,6,65,133,92,120,31,48), +(4,6,66,135,94,123,31,49), +(4,6,67,136,95,125,32,49), +(4,6,68,137,97,127,32,50), +(4,6,69,140,98,130,32,51), +(4,6,70,147,100,132,32,51), +(4,6,71,154,102,135,33,52), +(4,6,72,156,103,137,33,53), +(4,6,73,157,105,140,33,54), +(4,6,74,158,107,142,33,54), +(4,6,75,161,108,145,34,55), +(4,6,76,164,110,148,34,56), +(4,6,77,167,112,150,34,57), +(4,6,78,170,113,153,34,57), +(4,6,79,172,115,156,35,58), +(4,6,80,177,117,159,35,59), + +(4,11,1,18,25,19,22,22), +(4,11,2,19,25,20,23,23), +(4,11,3,19,26,20,24,24), +(4,11,4,20,26,21,25,26), +(4,11,5,20,27,22,26,27), +(4,11,6,21,27,22,27,28), +(4,11,7,21,28,23,28,29), +(4,11,8,22,28,24,29,30), +(4,11,9,23,29,24,30,32), +(4,11,10,23,29,25,32,33), +(4,11,11,24,30,26,33,34), +(4,11,12,24,31,26,34,35), +(4,11,13,25,31,27,35,37), +(4,11,14,26,32,28,36,38), +(4,11,15,26,32,29,37,39), +(4,11,16,27,33,29,38,41), +(4,11,17,28,33,30,40,42), +(4,11,18,28,34,31,41,43), +(4,11,19,29,35,32,42,45), +(4,11,20,30,35,32,43,46), +(4,11,21,30,36,33,45,48), +(4,11,22,31,36,34,46,49), +(4,11,23,32,37,35,47,51), +(4,11,24,32,38,36,48,52), +(4,11,25,33,38,36,50,53), +(4,11,26,34,39,37,51,55), +(4,11,27,35,40,38,52,56), +(4,11,28,35,40,39,54,58), +(4,11,29,36,41,40,55,59), +(4,11,30,37,42,41,56,61), +(4,11,31,38,42,42,58,62), +(4,11,32,38,43,42,59,64), +(4,11,33,39,44,43,60,66), +(4,11,34,40,44,44,62,67), +(4,11,35,41,45,45,63,69), +(4,11,36,42,46,46,65,70), +(4,11,37,42,47,47,66,72), +(4,11,38,43,47,48,67,74), +(4,11,39,44,48,49,69,75), +(4,11,40,45,49,50,70,77), +(4,11,41,46,50,51,72,79), +(4,11,42,46,50,52,73,80), +(4,11,43,47,51,53,75,82), +(4,11,44,48,52,54,76,84), +(4,11,45,49,53,55,78,85), +(4,11,46,50,54,56,79,87), +(4,11,47,51,54,57,81,89), +(4,11,48,52,55,58,83,91), +(4,11,49,53,56,59,84,93), +(4,11,50,53,57,60,86,94), +(4,11,51,54,58,61,87,96), +(4,11,52,55,59,62,89,98), +(4,11,53,56,59,63,91,100), +(4,11,54,57,60,64,92,102), +(4,11,55,58,61,65,94,103), +(4,11,56,59,62,66,95,105), +(4,11,57,60,63,67,97,107), +(4,11,58,61,64,68,99,109), +(4,11,59,62,65,69,101,111), +(4,11,60,63,66,70,102,113), +(4,11,61,64,66,72,104,115), +(4,11,62,65,67,73,106,117), +(4,11,63,66,68,74,107,119), +(4,11,64,67,69,75,109,121), +(4,11,65,68,70,76,111,123), +(4,11,66,69,71,77,113,125), +(4,11,67,70,72,78,115,127), +(4,11,68,71,73,80,116,129), +(4,11,69,72,74,81,118,131), +(4,11,70,73,75,82,120,133), +(4,11,71,75,76,83,122,135), +(4,11,72,76,78,85,125,138), +(4,11,73,77,79,86,127,140), +(4,11,74,78,80,88,131,143), +(4,11,75,80,81,89,133,145), +(4,11,76,81,82,91,134,148), +(4,11,77,82,83,92,136,151), +(4,11,78,84,85,94,138,153), +(4,11,79,85,86,95,141,156), +(4,11,80,86,87,97,143,159), + +(5,1,1,22,18,23,18,25), +(5,1,2,23,19,24,18,25), +(5,1,3,25,20,25,18,26), +(5,1,4,26,20,26,18,26), +(5,1,5,27,21,28,18,26), +(5,1,6,29,22,29,18,26), +(5,1,7,30,23,30,19,27), +(5,1,8,31,24,31,19,27), +(5,1,9,33,25,33,19,27), +(5,1,10,34,25,34,19,28), +(5,1,11,35,26,35,19,28), +(5,1,12,37,27,36,19,28), +(5,1,13,38,28,38,19,28), +(5,1,14,40,29,39,19,29), +(5,1,15,41,30,40,19,29), +(5,1,16,43,31,42,20,29), +(5,1,17,44,32,43,20,30), +(5,1,18,46,33,44,20,30), +(5,1,19,47,34,46,20,31), +(5,1,20,49,34,47,20,31), +(5,1,21,50,35,49,20,31), +(5,1,22,52,36,50,20,32), +(5,1,23,53,37,51,21,32), +(5,1,24,55,38,53,21,32), +(5,1,25,57,39,54,21,33), +(5,1,26,58,40,56,21,33), +(5,1,27,60,41,57,21,34), +(5,1,28,62,42,59,21,34), +(5,1,29,63,43,60,21,34), +(5,1,30,65,44,62,22,35), +(5,1,31,67,46,63,22,35), +(5,1,32,68,47,65,22,36), +(5,1,33,70,48,67,22,36), +(5,1,34,72,49,68,22,36), +(5,1,35,74,50,70,23,37), +(5,1,36,75,51,71,23,37), +(5,1,37,77,52,73,23,38), +(5,1,38,79,53,75,23,38), +(5,1,39,81,54,76,23,39), +(5,1,40,83,55,78,24,39), +(5,1,41,84,57,80,24,40), +(5,1,42,86,58,81,24,40), +(5,1,43,88,59,83,24,41), +(5,1,44,90,60,85,24,41), +(5,1,45,92,61,86,25,42), +(5,1,46,94,62,88,25,42), +(5,1,47,96,64,90,25,43), +(5,1,48,98,65,92,25,43), +(5,1,49,100,66,93,25,44), +(5,1,50,102,67,95,26,44), +(5,1,51,104,69,97,26,45), +(5,1,52,106,70,99,26,45), +(5,1,53,108,71,101,26,46), +(5,1,54,110,72,103,27,46), +(5,1,55,112,74,104,27,47), +(5,1,56,114,75,106,27,48), +(5,1,57,116,76,108,27,48), +(5,1,58,118,78,110,28,49), +(5,1,59,120,79,112,28,49), +(5,1,60,122,80,114,28,50), +(5,1,61,124,82,116,28,50), +(5,1,62,126,83,118,29,51), +(5,1,63,128,84,120,29,52), +(5,1,64,131,86,122,29,52), +(5,1,65,133,87,124,30,53), +(5,1,66,135,88,126,30,53), +(5,1,67,137,90,128,30,54), +(5,1,68,139,91,130,30,55), +(5,1,69,142,93,132,31,55), +(5,1,70,144,94,134,31,56), +(5,1,71,147,95,136,31,57), +(5,1,72,150,97,139,31,58), +(5,1,73,152,99,141,31,59), +(5,1,74,155,100,144,32,59), +(5,1,75,158,102,146,32,60), +(5,1,76,163,104,149,32,61), +(5,1,77,167,106,152,33,62), +(5,1,78,167,107,154,33,62), +(5,1,79,170,109,157,33,63), +(5,1,80,173,111,160,34,64), + +(5,4,1,20,21,22,18,25), +(5,4,2,21,22,23,18,25), +(5,4,3,22,24,23,18,26), +(5,4,4,22,25,24,18,26), +(5,4,5,23,27,25,19,26), +(5,4,6,24,28,25,19,27), +(5,4,7,25,30,26,19,27), +(5,4,8,25,31,27,19,27), +(5,4,9,26,33,28,19,28), +(5,4,10,27,34,28,19,28), +(5,4,11,28,36,29,20,29), +(5,4,12,29,38,30,20,29), +(5,4,13,30,39,31,20,29), +(5,4,14,31,41,32,20,30), +(5,4,15,31,42,32,20,30), +(5,4,16,32,44,33,21,31), +(5,4,17,33,46,34,21,31), +(5,4,18,34,47,35,21,32), +(5,4,19,35,49,36,21,32), +(5,4,20,36,51,36,21,32), +(5,4,21,37,52,37,22,33), +(5,4,22,38,54,38,22,33), +(5,4,23,39,56,39,22,34), +(5,4,24,40,58,40,22,34), +(5,4,25,41,60,41,23,35), +(5,4,26,42,61,42,23,35), +(5,4,27,43,63,43,23,36), +(5,4,28,44,65,44,23,36), +(5,4,29,45,67,44,24,37), +(5,4,30,46,69,45,24,37), +(5,4,31,47,71,46,24,38), +(5,4,32,48,72,47,24,38), +(5,4,33,49,74,48,25,39), +(5,4,34,50,76,49,25,39), +(5,4,35,51,78,50,25,40), +(5,4,36,52,80,51,25,41), +(5,4,37,53,82,52,26,41), +(5,4,38,54,84,53,26,42), +(5,4,39,55,86,54,26,42), +(5,4,40,56,88,55,27,43), +(5,4,41,57,90,56,27,43), +(5,4,42,59,92,57,27,44), +(5,4,43,60,94,58,27,45), +(5,4,44,61,96,59,28,45), +(5,4,45,62,99,60,28,46), +(5,4,46,63,101,61,28,46), +(5,4,47,64,103,63,29,47), +(5,4,48,66,105,64,29,48), +(5,4,49,67,107,65,29,48), +(5,4,50,68,109,66,30,49), +(5,4,51,69,111,67,30,50), +(5,4,52,70,114,68,30,50), +(5,4,53,72,116,69,31,51), +(5,4,54,73,118,70,31,52), +(5,4,55,74,120,72,31,52), +(5,4,56,75,123,73,32,53), +(5,4,57,77,125,74,32,54), +(5,4,58,78,127,75,32,54), +(5,4,59,79,130,76,33,55), +(5,4,60,81,132,77,33,56), +(5,4,61,82,134,79,34,56), +(5,4,62,83,137,80,34,57), +(5,4,63,84,139,81,34,58), +(5,4,64,86,141,82,35,59), +(5,4,65,87,144,84,35,59), +(5,4,66,88,146,85,35,60), +(5,4,67,90,149,86,36,61), +(5,4,68,91,151,87,36,61), +(5,4,69,93,154,89,37,62), +(5,4,70,94,156,90,37,63), +(5,4,71,96,159,91,37,64), +(5,4,72,98,162,93,38,64), +(5,4,73,99,165,95,38,65), +(5,4,74,101,168,96,39,66), +(5,4,75,103,171,98,39,67), +(5,4,76,104,174,99,39,68), +(5,4,77,106,177,101,40,69), +(5,4,78,108,181,103,40,70), +(5,4,79,110,184,104,41,71), +(5,4,80,112,187,106,41,72), + +(5,5,1,19,18,21,20,28), +(5,5,2,19,18,21,21,29), +(5,5,3,19,18,22,23,31), +(5,5,4,19,19,22,24,32), +(5,5,5,20,19,22,25,33), +(5,5,6,20,19,23,27,35), +(5,5,7,20,19,23,28,36), +(5,5,8,20,20,24,29,38), +(5,5,9,20,20,24,31,39), +(5,5,10,20,20,24,32,40), +(5,5,11,21,20,25,34,42), +(5,5,12,21,21,25,35,43), +(5,5,13,21,21,26,37,45), +(5,5,14,21,21,26,38,46), +(5,5,15,21,21,26,39,48), +(5,5,16,22,22,27,41,50), +(5,5,17,22,22,27,42,51), +(5,5,18,22,22,28,44,53), +(5,5,19,22,23,28,46,54), +(5,5,20,22,23,29,47,56), +(5,5,21,23,23,29,49,57), +(5,5,22,23,23,30,50,59), +(5,5,23,23,24,30,52,61), +(5,5,24,23,24,31,53,62), +(5,5,25,24,24,31,55,64), +(5,5,26,24,25,32,57,66), +(5,5,27,24,25,32,58,68), +(5,5,28,24,25,33,60,69), +(5,5,29,25,26,33,62,71), +(5,5,30,25,26,34,63,73), +(5,5,31,25,26,34,65,75), +(5,5,32,25,27,35,67,76), +(5,5,33,26,27,35,69,78), +(5,5,34,26,27,36,70,80), +(5,5,35,26,28,36,72,82), +(5,5,36,26,28,37,74,84), +(5,5,37,27,28,37,76,86), +(5,5,38,27,29,38,77,87), +(5,5,39,27,29,38,79,89), +(5,5,40,28,30,39,81,91), +(5,5,41,28,30,40,83,93), +(5,5,42,28,30,40,85,95), +(5,5,43,28,31,41,87,97), +(5,5,44,29,31,41,89,99), +(5,5,45,29,32,42,91,101), +(5,5,46,29,32,43,92,103), +(5,5,47,30,32,43,94,105), +(5,5,48,30,33,44,96,107), +(5,5,49,30,33,44,98,109), +(5,5,50,31,34,45,100,111), +(5,5,51,31,34,46,102,113), +(5,5,52,31,35,46,104,115), +(5,5,53,32,35,47,106,118), +(5,5,54,32,35,48,108,120), +(5,5,55,32,36,48,110,122), +(5,5,56,33,36,49,113,124), +(5,5,57,33,37,50,115,126), +(5,5,58,33,37,50,117,128), +(5,5,59,34,38,51,119,131), +(5,5,60,34,38,52,121,133), +(5,5,61,34,39,52,123,135), +(5,5,62,35,39,53,125,137), +(5,5,63,35,40,54,127,140), +(5,5,64,36,40,55,130,142), +(5,5,65,36,41,55,132,144), +(5,5,66,36,41,56,134,147), +(5,5,67,37,41,57,136,149), +(5,5,68,37,42,58,138,151), +(5,5,69,38,42,58,141,154), +(5,5,70,38,43,59,143,156), +(5,5,71,38,44,60,146,159), +(5,5,72,39,44,60,149,162), +(5,5,73,39,45,61,152,165), +(5,5,74,40,45,62,157,168), +(5,5,75,40,46,63,157,171), +(5,5,76,40,47,64,160,174), +(5,5,77,41,47,65,163,177), +(5,5,78,41,48,66,166,180), +(5,5,79,42,48,67,169,183), +(5,5,80,42,49,68,172,186), + +(5,6,1,22,18,23,18,25), +(5,6,2,23,19,24,18,25), +(5,6,3,25,20,25,18,26), +(5,6,4,26,20,26,18,26), +(5,6,5,27,21,28,18,26), +(5,6,6,29,22,29,18,26), +(5,6,7,30,23,30,19,27), +(5,6,8,31,24,31,19,27), +(5,6,9,33,25,33,19,27), +(5,6,10,34,25,34,19,28), +(5,6,11,35,26,35,19,28), +(5,6,12,37,27,36,19,28), +(5,6,13,38,28,38,19,28), +(5,6,14,40,29,39,19,29), +(5,6,15,41,30,40,19,29), +(5,6,16,43,31,42,20,29), +(5,6,17,44,32,43,20,30), +(5,6,18,46,33,44,20,30), +(5,6,19,47,34,46,20,31), +(5,6,20,49,34,47,20,31), +(5,6,21,50,35,49,20,31), +(5,6,22,52,36,50,20,32), +(5,6,23,53,37,51,21,32), +(5,6,24,55,38,53,21,32), +(5,6,25,57,39,54,21,33), +(5,6,26,58,40,56,21,33), +(5,6,27,60,41,57,21,34), +(5,6,28,62,42,59,21,34), +(5,6,29,63,43,60,21,34), +(5,6,30,65,44,62,22,35), +(5,6,31,67,46,63,22,35), +(5,6,32,68,47,65,22,36), +(5,6,33,70,48,67,22,36), +(5,6,34,72,49,68,22,36), +(5,6,35,74,50,70,23,37), +(5,6,36,75,51,71,23,37), +(5,6,37,77,52,73,23,38), +(5,6,38,79,53,75,23,38), +(5,6,39,81,54,76,23,39), +(5,6,40,83,55,78,24,39), +(5,6,41,84,57,80,24,40), +(5,6,42,86,58,81,24,40), +(5,6,43,88,59,83,24,41), +(5,6,44,90,60,85,24,41), +(5,6,45,92,61,86,25,42), +(5,6,46,94,62,88,25,42), +(5,6,47,96,64,90,25,43), +(5,6,48,98,65,92,25,43), +(5,6,49,100,66,93,25,44), +(5,6,50,102,67,95,26,44), +(5,6,51,103,67,96,26,45), +(5,6,52,104,68,97,26,45), +(5,6,53,105,69,98,26,46), +(5,6,54,106,70,99,27,46), +(5,6,55,107,71,100,27,47), +(5,6,56,110,73,103,27,48), +(5,6,57,112,74,105,27,48), +(5,6,58,114,75,107,28,49), +(5,6,59,119,77,109,28,49), +(5,6,60,122,78,111,28,50), +(5,6,61,124,79,113,28,51), +(5,6,62,127,81,115,28,51), +(5,6,63,129,82,118,29,52), +(5,6,64,136,84,120,29,52), +(5,6,65,137,85,123,29,53), +(5,6,66,138,87,125,29,54), +(5,6,67,141,88,127,30,54), +(5,6,68,143,90,129,30,55), +(5,6,69,146,91,132,30,56), +(5,6,70,149,93,134,30,56), +(5,6,71,152,95,137,31,57), +(5,6,72,154,96,139,31,58), +(5,6,73,157,98,142,31,59), +(5,6,74,158,100,145,31,59), +(5,6,75,159,101,147,32,60), +(5,6,76,162,103,150,32,61), +(5,6,77,167,105,152,32,62), +(5,6,78,173,106,155,32,62), +(5,6,79,174,108,158,33,63), +(5,6,80,174,110,161,33,64), + +(5,8,1,19,18,21,21,27), +(5,8,2,19,18,21,22,28), +(5,8,3,19,18,22,24,30), +(5,8,4,19,18,22,25,31), +(5,8,5,19,19,22,26,32), +(5,8,6,19,19,22,28,34), +(5,8,7,20,19,23,29,35), +(5,8,8,20,19,23,31,36), +(5,8,9,20,19,23,32,38), +(5,8,10,20,19,24,34,39), +(5,8,11,20,20,24,35,40), +(5,8,12,20,20,24,37,42), +(5,8,13,20,20,25,38,43), +(5,8,14,20,20,25,40,45), +(5,8,15,20,20,25,41,46), +(5,8,16,21,21,26,43,48), +(5,8,17,21,21,26,44,49), +(5,8,18,21,21,26,46,51), +(5,8,19,21,21,27,48,52), +(5,8,20,21,21,27,49,54), +(5,8,21,21,22,27,51,55), +(5,8,22,21,22,28,52,57), +(5,8,23,21,22,28,54,58), +(5,8,24,22,22,29,56,60), +(5,8,25,22,23,29,57,62), +(5,8,26,22,23,29,59,63), +(5,8,27,22,23,30,61,65), +(5,8,28,22,23,30,63,67), +(5,8,29,22,24,31,64,68), +(5,8,30,23,24,31,66,70), +(5,8,31,23,24,31,68,72), +(5,8,32,23,24,32,70,73), +(5,8,33,23,25,32,72,75), +(5,8,34,23,25,33,73,77), +(5,8,35,24,25,33,75,79), +(5,8,36,24,25,34,77,80), +(5,8,37,24,26,34,79,82), +(5,8,38,24,26,35,81,84), +(5,8,39,24,26,35,83,86), +(5,8,40,24,27,35,85,88), +(5,8,41,25,27,36,87,90), +(5,8,42,25,27,36,89,91), +(5,8,43,25,27,37,90,93), +(5,8,44,25,28,37,92,95), +(5,8,45,26,28,38,94,97), +(5,8,46,26,28,38,96,99), +(5,8,47,26,29,39,98,101), +(5,8,48,26,29,39,100,103), +(5,8,49,26,29,40,103,105), +(5,8,50,27,30,40,105,107), +(5,8,51,27,30,41,107,109), +(5,8,52,27,30,42,109,111), +(5,8,53,27,31,42,111,113), +(5,8,54,28,31,43,113,115), +(5,8,55,28,31,43,115,117), +(5,8,56,28,32,44,117,119), +(5,8,57,28,32,44,119,121), +(5,8,58,29,32,45,122,123), +(5,8,59,29,33,45,124,126), +(5,8,60,29,33,46,126,128), +(5,8,61,29,34,47,128,130), +(5,8,62,30,34,47,131,132), +(5,8,63,30,34,48,133,134), +(5,8,64,30,35,48,135,136), +(5,8,65,31,35,49,137,139), +(5,8,66,31,35,50,140,141), +(5,8,67,31,36,50,142,143), +(5,8,68,31,36,51,144,145), +(5,8,69,32,37,51,147,148), +(5,8,70,32,37,52,149,150), +(5,8,71,32,37,53,152,153), +(5,8,72,32,38,54,155,156), +(5,8,73,32,38,55,158,159), +(5,8,74,33,39,55,161,161), +(5,8,75,33,39,56,164,164), +(5,8,76,33,39,57,167,167), +(5,8,77,34,40,58,170,170), +(5,8,78,34,40,58,173,173), +(5,8,79,34,41,59,176,176), +(5,8,80,35,41,60,179,179), + +(5,9,1,19,18,22,20,27), +(5,9,2,19,18,23,21,28), +(5,9,3,20,19,23,22,29), +(5,9,4,20,19,24,24,30), +(5,9,5,20,19,24,25,32), +(5,9,6,20,20,25,26,33), +(5,9,7,21,20,25,27,34), +(5,9,8,21,21,26,28,35), +(5,9,9,21,21,26,30,36), +(5,9,10,22,21,27,31,38), +(5,9,11,22,22,28,32,39), +(5,9,12,22,22,28,34,40), +(5,9,13,23,23,29,35,41), +(5,9,14,23,23,30,36,43), +(5,9,15,23,24,30,37,44), +(5,9,16,24,24,31,39,45), +(5,9,17,24,24,31,40,47), +(5,9,18,24,25,32,42,48), +(5,9,19,25,25,33,43,49), +(5,9,20,25,26,33,44,51), +(5,9,21,26,26,34,46,52), +(5,9,22,26,27,35,47,53), +(5,9,23,26,27,36,49,55), +(5,9,24,27,28,36,50,56), +(5,9,25,27,28,37,52,58), +(5,9,26,27,29,38,53,59), +(5,9,27,28,29,38,55,60), +(5,9,28,28,30,39,56,62), +(5,9,29,29,30,40,58,63), +(5,9,30,29,31,41,59,65), +(5,9,31,30,31,41,61,66), +(5,9,32,30,32,42,62,68), +(5,9,33,30,32,43,64,69), +(5,9,34,31,33,44,65,71), +(5,9,35,31,33,45,67,73), +(5,9,36,32,34,45,69,74), +(5,9,37,32,34,46,70,76), +(5,9,38,33,35,47,72,77), +(5,9,39,33,36,48,73,79), +(5,9,40,34,36,49,75,81), +(5,9,41,34,37,49,77,82), +(5,9,42,35,37,50,78,84), +(5,9,43,35,38,51,80,86), +(5,9,44,36,39,52,82,87), +(5,9,45,36,39,53,84,89), +(5,9,46,37,40,54,85,91), +(5,9,47,37,40,55,87,92), +(5,9,48,38,41,55,89,94), +(5,9,49,38,42,56,91,96), +(5,9,50,39,42,57,92,98), +(5,9,51,39,43,58,94,100), +(5,9,52,40,44,59,96,101), +(5,9,53,40,44,60,98,103), +(5,9,54,41,45,61,100,105), +(5,9,55,41,45,62,102,107), +(5,9,56,42,46,63,103,109), +(5,9,57,42,47,64,105,111), +(5,9,58,43,47,65,107,112), +(5,9,59,43,48,66,109,114), +(5,9,60,44,49,67,111,116), +(5,9,61,45,50,68,113,118), +(5,9,62,45,50,69,115,120), +(5,9,63,46,51,70,117,122), +(5,9,64,46,52,71,119,124), +(5,9,65,47,52,72,121,126), +(5,9,66,48,53,73,123,128), +(5,9,67,48,54,74,125,130), +(5,9,68,49,55,75,127,132), +(5,9,69,49,55,76,129,134), +(5,9,70,50,56,77,131,136), +(5,9,71,51,57,86,135,147), +(5,9,72,52,57,88,136,149), +(5,9,73,53,58,89,138,152), +(5,9,74,53,59,90,141,155), +(5,9,75,54,60,92,143,157), +(5,9,76,55,61,93,146,160), +(5,9,77,56,62,94,149,163), +(5,9,78,56,63,96,151,166), +(5,9,79,57,64,97,154,169), +(5,9,80,58,65,99,157,171), + +(6,1,1,28,15,24,15,22), +(6,1,2,29,16,25,15,22), +(6,1,3,31,17,26,15,23), +(6,1,4,32,17,27,15,23), +(6,1,5,33,18,29,15,23), +(6,1,6,34,19,30,15,23), +(6,1,7,36,20,31,16,24), +(6,1,8,37,21,32,16,24), +(6,1,9,38,22,34,16,24), +(6,1,10,40,22,35,16,25), +(6,1,11,41,23,36,16,25), +(6,1,12,43,24,37,16,25), +(6,1,13,44,25,39,16,26), +(6,1,14,46,26,40,16,26), +(6,1,15,47,27,41,17,26), +(6,1,16,48,28,43,17,27), +(6,1,17,50,29,44,17,27), +(6,1,18,51,30,45,17,27), +(6,1,19,53,31,47,17,28), +(6,1,20,54,32,48,17,28), +(6,1,21,56,33,50,17,28), +(6,1,22,58,34,51,18,29), +(6,1,23,59,35,52,18,29), +(6,1,24,61,36,54,18,30), +(6,1,25,62,37,55,18,30), +(6,1,26,64,38,57,18,30), +(6,1,27,66,39,58,18,31), +(6,1,28,67,40,60,18,31), +(6,1,29,69,41,61,19,32), +(6,1,30,71,42,63,19,32), +(6,1,31,72,43,64,19,32), +(6,1,32,74,44,66,19,33), +(6,1,33,76,45,67,19,33), +(6,1,34,77,46,69,20,34), +(6,1,35,79,47,71,20,34), +(6,1,36,81,48,72,20,35), +(6,1,37,83,49,74,20,35), +(6,1,38,85,50,76,20,35), +(6,1,39,86,51,77,21,36), +(6,1,40,88,53,79,21,36), +(6,1,41,90,54,81,21,37), +(6,1,42,92,55,82,21,37), +(6,1,43,94,56,84,21,38), +(6,1,44,96,57,86,22,38), +(6,1,45,98,58,87,22,39), +(6,1,46,99,60,89,22,39), +(6,1,47,101,61,91,22,40), +(6,1,48,103,62,93,22,40), +(6,1,49,105,63,94,23,41), +(6,1,50,107,65,96,23,41), +(6,1,51,109,66,98,23,42), +(6,1,52,111,67,100,23,42), +(6,1,53,113,68,102,24,43), +(6,1,54,115,70,104,24,44), +(6,1,55,117,71,105,24,44), +(6,1,56,119,72,107,24,45), +(6,1,57,122,73,109,25,45), +(6,1,58,124,75,111,25,46), +(6,1,59,126,76,113,25,46), +(6,1,60,128,77,115,25,47), +(6,1,61,130,79,117,26,48), +(6,1,62,132,80,119,26,48), +(6,1,63,134,81,121,26,49), +(6,1,64,137,83,123,26,49), +(6,1,65,139,84,125,27,50), +(6,1,66,141,85,127,27,51), +(6,1,67,143,87,129,27,51), +(6,1,68,145,88,131,27,52), +(6,1,69,148,90,133,28,52), +(6,1,70,150,91,135,28,53), +(6,1,71,153,92,137,28,54), +(6,1,72,155,94,140,28,55), +(6,1,73,158,96,142,28,56), +(6,1,74,161,97,145,29,56), +(6,1,75,164,99,147,29,57), +(6,1,76,167,101,150,29,58), +(6,1,77,170,103,153,30,59), +(6,1,78,173,104,155,30,59), +(6,1,79,176,106,164,30,60), +(6,1,80,179,108,170,31,61), + +(6,3,1,25,18,23,15,23), +(6,3,2,25,19,24,16,24), +(6,3,3,26,21,25,16,24), +(6,3,4,26,22,26,17,25), +(6,3,5,27,24,27,17,25), +(6,3,6,27,25,28,18,26), +(6,3,7,28,26,28,19,27), +(6,3,8,28,28,29,19,27), +(6,3,9,28,29,30,20,28), +(6,3,10,29,31,31,20,29), +(6,3,11,29,32,32,21,29), +(6,3,12,30,34,33,22,30), +(6,3,13,30,35,34,22,31), +(6,3,14,31,37,35,23,32), +(6,3,15,31,38,36,24,32), +(6,3,16,32,40,37,24,33), +(6,3,17,32,41,39,25,34), +(6,3,18,33,43,40,26,35), +(6,3,19,33,45,41,27,35), +(6,3,20,34,46,42,27,36), +(6,3,21,34,48,43,28,37), +(6,3,22,35,50,44,29,38), +(6,3,23,35,51,45,29,38), +(6,3,24,36,53,46,30,39), +(6,3,25,37,55,47,31,40), +(6,3,26,37,56,48,32,41), +(6,3,27,38,58,50,32,42), +(6,3,28,38,60,51,33,42), +(6,3,29,39,62,52,34,43), +(6,3,30,39,63,53,35,44), +(6,3,31,40,65,54,36,45), +(6,3,32,41,67,56,36,46), +(6,3,33,41,69,57,37,47), +(6,3,34,42,71,58,38,48), +(6,3,35,43,72,59,39,48), +(6,3,36,43,74,61,40,49), +(6,3,37,44,76,62,40,50), +(6,3,38,45,78,63,41,51), +(6,3,39,45,80,64,42,52), +(6,3,40,46,82,66,43,53), +(6,3,41,47,84,67,44,54), +(6,3,42,47,86,68,45,55), +(6,3,43,48,88,70,46,56), +(6,3,44,49,90,71,46,57), +(6,3,45,49,92,72,47,58), +(6,3,46,50,94,74,48,59), +(6,3,47,51,96,75,49,60), +(6,3,48,51,98,77,50,61), +(6,3,49,52,100,78,51,62), +(6,3,50,53,102,79,52,63), +(6,3,51,54,104,81,53,64), +(6,3,52,54,106,82,54,65), +(6,3,53,55,108,84,55,66), +(6,3,54,56,110,85,56,67), +(6,3,55,57,112,87,57,68), +(6,3,56,57,114,88,58,69), +(6,3,57,58,117,90,59,70), +(6,3,58,59,119,91,60,71), +(6,3,59,60,121,93,61,72), +(6,3,60,61,123,94,62,74), +(6,3,61,61,125,96,63,75), +(6,3,62,62,128,97,64,76), +(6,3,63,63,130,99,65,77), +(6,3,64,64,132,100,66,78), +(6,3,65,65,134,102,67,79), +(6,3,66,66,137,104,68,80), +(6,3,67,66,139,105,69,81), +(6,3,68,67,141,107,70,83), +(6,3,69,68,144,108,71,84), +(6,3,70,69,146,110,72,85), +(6,3,71,70,149,112,73,86), +(6,3,72,71,152,114,74,87), +(6,3,73,72,155,116,75,89), +(6,3,74,73,158,118,77,90), +(6,3,75,74,161,120,78,92), +(6,3,76,75,164,122,79,93), +(6,3,77,76,167,124,81,95), +(6,3,78,77,176,126,85,96), +(6,3,79,78,179,128,86,98), +(6,3,80,79,183,130,88,99), + +(6,6,1,28,15,24,15,22), +(6,6,2,29,16,25,15,22), +(6,6,3,31,17,26,15,23), +(6,6,4,32,17,27,15,23), +(6,6,5,33,18,29,15,23), +(6,6,6,34,19,30,15,23), +(6,6,7,36,20,31,16,24), +(6,6,8,37,21,32,16,24), +(6,6,9,38,22,34,16,24), +(6,6,10,40,22,35,16,25), +(6,6,11,41,23,36,16,25), +(6,6,12,43,24,37,16,25), +(6,6,13,44,25,39,16,26), +(6,6,14,46,26,40,16,26), +(6,6,15,47,27,41,17,26), +(6,6,16,48,28,43,17,27), +(6,6,17,50,29,44,17,27), +(6,6,18,51,30,45,17,27), +(6,6,19,53,31,47,17,28), +(6,6,20,54,32,48,17,28), +(6,6,21,56,33,50,17,28), +(6,6,22,58,34,51,18,29), +(6,6,23,59,35,52,18,29), +(6,6,24,61,36,54,18,30), +(6,6,25,62,37,55,18,30), +(6,6,26,64,38,57,18,30), +(6,6,27,66,39,58,18,31), +(6,6,28,67,40,60,18,31), +(6,6,29,69,41,61,19,32), +(6,6,30,71,42,63,19,32), +(6,6,31,72,43,64,19,32), +(6,6,32,74,44,66,19,33), +(6,6,33,76,45,67,19,33), +(6,6,34,77,46,69,20,34), +(6,6,35,79,47,71,20,34), +(6,6,36,81,48,72,20,35), +(6,6,37,83,49,74,20,35), +(6,6,38,85,50,76,20,35), +(6,6,39,86,51,77,21,36), +(6,6,40,88,53,79,21,36), +(6,6,41,90,54,81,21,37), +(6,6,42,92,55,82,21,37), +(6,6,43,94,56,84,21,38), +(6,6,44,96,57,86,22,38), +(6,6,45,98,58,87,22,39), +(6,6,46,99,60,89,22,39), +(6,6,47,101,60,91,22,40), +(6,6,48,103,61,93,22,40), +(6,6,49,105,62,94,23,41), +(6,6,50,107,63,96,23,41), +(6,6,51,109,64,97,23,42), +(6,6,52,110,65,98,23,42), +(6,6,53,111,66,99,24,43), +(6,6,54,112,67,100,24,44), +(6,6,55,113,68,101,24,44), +(6,6,56,116,70,104,24,45), +(6,6,57,121,71,106,24,45), +(6,6,58,123,72,108,25,46), +(6,6,59,123,74,110,25,46), +(6,6,60,125,75,112,25,47), +(6,6,61,127,76,114,25,48), +(6,6,62,133,78,116,25,48), +(6,6,63,135,79,119,26,49), +(6,6,64,139,81,121,26,49), +(6,6,65,142,82,123,26,50), +(6,6,66,146,84,126,26,51), +(6,6,67,150,85,132,27,51), +(6,6,68,153,87,137,27,52), +(6,6,69,157,88,140,27,53), +(6,6,70,160,90,143,27,53), +(6,6,71,163,92,146,28,54), +(6,6,72,165,93,148,28,55), +(6,6,73,167,95,150,28,56), +(6,6,74,171,97,153,28,56), +(6,6,75,174,98,156,29,57), +(6,6,76,178,100,156,29,58), +(6,6,77,179,102,156,29,59), +(6,6,78,179,103,156,29,59), +(6,6,79,182,105,159,30,60), +(6,6,80,185,107,162,30,61), + +(6,7,1,26,15,23,16,24), +(6,7,2,27,15,24,17,25), +(6,7,3,28,16,25,18,26), +(6,7,4,28,16,26,19,27), +(6,7,5,29,17,27,20,28), +(6,7,6,30,17,28,21,29), +(6,7,7,31,18,29,22,30), +(6,7,8,32,18,30,23,31), +(6,7,9,33,19,31,24,32), +(6,7,10,34,19,32,25,33), +(6,7,11,35,20,33,26,35), +(6,7,12,35,20,34,27,36), +(6,7,13,36,21,35,28,37), +(6,7,14,37,21,36,29,38), +(6,7,15,38,22,37,30,39), +(6,7,16,39,22,39,31,40), +(6,7,17,40,23,40,32,42), +(6,7,18,41,23,41,33,43), +(6,7,19,42,24,42,34,44), +(6,7,20,43,24,43,35,45), +(6,7,21,44,25,44,36,46), +(6,7,22,45,25,45,37,48), +(6,7,23,46,26,47,38,49), +(6,7,24,47,27,48,40,50), +(6,7,25,48,27,49,41,51), +(6,7,26,49,28,50,42,53), +(6,7,27,51,28,52,43,54), +(6,7,28,52,29,53,44,55), +(6,7,29,53,29,54,45,57), +(6,7,30,54,30,55,47,58), +(6,7,31,55,31,57,48,59), +(6,7,32,56,31,58,49,61), +(6,7,33,57,32,59,50,62), +(6,7,34,58,33,61,51,64), +(6,7,35,60,33,62,53,65), +(6,7,36,61,34,63,54,66), +(6,7,37,62,34,65,55,68), +(6,7,38,63,35,66,57,69), +(6,7,39,64,36,67,58,71), +(6,7,40,66,36,69,59,72), +(6,7,41,67,37,70,60,74), +(6,7,42,68,38,72,62,75), +(6,7,43,69,38,73,63,77), +(6,7,44,70,39,74,64,78), +(6,7,45,72,40,76,66,80), +(6,7,46,73,41,77,67,81), +(6,7,47,74,41,79,69,83), +(6,7,48,76,42,80,70,84), +(6,7,49,77,43,82,71,86), +(6,7,50,78,43,83,73,88), +(6,7,51,80,44,85,74,89), +(6,7,52,81,45,86,76,91), +(6,7,53,82,46,88,77,92), +(6,7,54,84,46,90,78,94), +(6,7,55,85,47,91,80,96), +(6,7,56,86,48,93,81,97), +(6,7,57,88,49,94,83,99), +(6,7,58,89,49,96,84,101), +(6,7,59,91,50,97,86,102), +(6,7,60,92,51,99,87,104), +(6,7,61,94,52,101,89,106), +(6,7,62,95,52,102,90,108), +(6,7,63,96,53,104,92,109), +(6,7,64,98,54,106,93,111), +(6,7,65,99,55,107,95,113), +(6,7,66,101,56,109,97,115), +(6,7,67,102,57,111,98,117), +(6,7,68,104,57,113,100,118), +(6,7,69,105,58,114,101,120), +(6,7,70,107,59,116,103,122), +(6,7,71,108,60,118,113,124), +(6,7,72,110,61,120,117,127), +(6,7,73,112,62,122,119,129), +(6,7,74,114,63,125,122,131), +(6,7,75,116,64,127,124,133), +(6,7,76,118,65,129,126,136), +(6,7,77,119,66,131,128,138), +(6,7,78,121,67,133,130,140), +(6,7,79,123,68,136,133,143), +(6,7,80,125,69,138,135,145), + +(6,11,1,26,15,22,17,24), +(6,11,2,27,16,23,18,25), +(6,11,3,27,16,23,19,26), +(6,11,4,28,17,24,20,27), +(6,11,5,28,17,25,21,29), +(6,11,6,29,18,25,22,30), +(6,11,7,29,18,26,23,31), +(6,11,8,30,19,27,24,32), +(6,11,9,30,19,27,26,34), +(6,11,10,31,20,28,27,35), +(6,11,11,32,20,29,28,36), +(6,11,12,32,21,29,29,37), +(6,11,13,33,21,30,30,39), +(6,11,14,33,22,31,31,40), +(6,11,15,34,23,32,32,41), +(6,11,16,35,23,32,34,43), +(6,11,17,35,24,33,35,44), +(6,11,18,36,24,34,36,45), +(6,11,19,37,25,35,37,47), +(6,11,20,37,26,35,39,48), +(6,11,21,38,26,36,40,50), +(6,11,22,39,27,37,41,51), +(6,11,23,39,28,38,42,52), +(6,11,24,40,28,39,44,54), +(6,11,25,41,29,39,45,55), +(6,11,26,41,30,40,46,57), +(6,11,27,42,30,41,47,58), +(6,11,28,43,31,42,49,60), +(6,11,29,44,32,43,50,61), +(6,11,30,44,32,44,52,63), +(6,11,31,45,33,44,53,64), +(6,11,32,46,34,45,54,66), +(6,11,33,47,34,46,56,67), +(6,11,34,47,35,47,57,69), +(6,11,35,48,36,48,58,71), +(6,11,36,49,36,49,60,72), +(6,11,37,50,37,50,61,74), +(6,11,38,51,38,51,63,76), +(6,11,39,52,39,52,64,77), +(6,11,40,52,39,53,66,79), +(6,11,41,53,40,54,67,81), +(6,11,42,54,41,55,69,82), +(6,11,43,55,42,56,70,84), +(6,11,44,56,43,57,72,86), +(6,11,45,57,43,57,73,87), +(6,11,46,57,44,58,75,89), +(6,11,47,58,45,60,76,91), +(6,11,48,59,46,61,78,93), +(6,11,49,60,47,62,79,94), +(6,11,50,61,47,63,81,96), +(6,11,51,62,48,64,83,98), +(6,11,52,63,49,65,84,100), +(6,11,53,64,50,66,86,102), +(6,11,54,65,51,67,87,104), +(6,11,55,66,51,68,89,105), +(6,11,56,67,52,69,91,107), +(6,11,57,68,53,70,92,109), +(6,11,58,69,54,71,94,111), +(6,11,59,70,55,72,96,113), +(6,11,60,71,56,73,97,115), +(6,11,61,72,57,74,99,117), +(6,11,62,73,58,76,101,119), +(6,11,63,74,59,77,103,121), +(6,11,64,75,59,78,104,123), +(6,11,65,76,60,79,106,125), +(6,11,66,77,61,80,108,127), +(6,11,67,78,62,81,110,129), +(6,11,68,79,63,83,111,131), +(6,11,69,80,64,84,113,133), +(6,11,70,81,65,85,115,135), +(6,11,71,83,66,86,117,137), +(6,11,72,84,68,88,120,140), +(6,11,73,85,69,89,122,142), +(6,11,74,86,70,91,124,145), +(6,11,75,88,71,92,126,147), +(6,11,76,89,72,94,128,150), +(6,11,77,90,73,95,131,153), +(6,11,78,92,75,97,133,155), +(6,11,79,93,76,98,136,158), +(6,11,80,94,77,100,138,185), + +(7,1,1,18,23,21,24,20), +(7,1,2,19,24,22,24,20), +(7,1,3,21,25,23,24,21), +(7,1,4,22,25,25,24,21), +(7,1,5,23,26,26,24,21), +(7,1,6,25,27,27,24,21), +(7,1,7,26,28,28,24,22), +(7,1,8,27,29,29,25,22), +(7,1,9,29,29,31,25,22), +(7,1,10,30,30,32,25,23), +(7,1,11,32,31,33,25,23), +(7,1,12,33,32,34,25,23), +(7,1,13,34,33,36,25,24), +(7,1,14,36,34,37,25,24), +(7,1,15,37,35,38,25,24), +(7,1,16,39,36,40,25,25), +(7,1,17,40,36,41,25,25), +(7,1,18,42,37,43,26,25), +(7,1,19,43,38,44,26,26), +(7,1,20,45,39,45,26,26), +(7,1,21,47,40,47,26,26), +(7,1,22,48,41,48,26,27), +(7,1,23,50,42,50,26,27), +(7,1,24,51,43,51,26,28), +(7,1,25,53,44,52,27,28), +(7,1,26,55,45,54,27,28), +(7,1,27,56,46,55,27,29), +(7,1,28,58,47,57,27,29), +(7,1,29,59,48,58,27,30), +(7,1,30,61,49,60,27,30), +(7,1,31,63,50,62,27,30), +(7,1,32,65,51,63,28,31), +(7,1,33,66,52,65,28,31), +(7,1,34,68,53,66,28,32), +(7,1,35,70,55,68,28,32), +(7,1,36,72,56,69,28,33), +(7,1,37,73,57,71,29,33), +(7,1,38,75,58,73,29,34), +(7,1,39,77,59,74,29,34), +(7,1,40,79,60,76,29,35), +(7,1,41,81,61,78,29,35), +(7,1,42,82,62,79,30,35), +(7,1,43,84,64,81,30,36), +(7,1,44,86,65,83,30,36), +(7,1,45,88,66,85,30,37), +(7,1,46,90,67,86,30,37), +(7,1,47,92,68,88,31,38), +(7,1,48,94,70,90,31,38), +(7,1,49,96,71,92,31,39), +(7,1,50,98,72,93,31,40), +(7,1,51,100,73,95,32,40), +(7,1,52,102,75,97,32,41), +(7,1,53,104,76,99,32,41), +(7,1,54,106,77,101,32,42), +(7,1,55,108,78,103,33,42), +(7,1,56,110,80,104,33,43), +(7,1,57,112,81,106,33,43), +(7,1,58,114,82,108,33,44), +(7,1,59,116,84,110,34,44), +(7,1,60,118,85,112,34,45), +(7,1,61,120,86,114,34,46), +(7,1,62,122,88,116,35,46), +(7,1,63,125,89,118,35,47), +(7,1,64,127,91,120,35,47), +(7,1,65,129,92,122,35,48), +(7,1,66,131,93,124,36,49), +(7,1,67,133,95,126,36,49), +(7,1,68,136,96,128,36,50), +(7,1,69,138,98,130,37,50), +(7,1,70,140,99,132,37,51), +(7,1,71,143,100,134,37,52), +(7,1,72,145,102,137,37,53), +(7,1,73,148,104,139,37,54), +(7,1,74,151,105,142,38,54), +(7,1,75,154,107,144,38,55), +(7,1,76,157,109,147,38,56), +(7,1,77,163,111,153,39,57), +(7,1,78,169,112,158,39,57), +(7,1,79,172,114,161,39,58), +(7,1,80,175,116,164,40,59), + +(7,4,1,16,26,20,24,20), +(7,4,2,17,27,21,24,20), +(7,4,3,18,29,21,24,21), +(7,4,4,18,30,22,24,21), +(7,4,5,19,32,23,25,21), +(7,4,6,20,33,24,25,22), +(7,4,7,21,35,24,25,22), +(7,4,8,22,36,25,25,23), +(7,4,9,22,38,26,25,23), +(7,4,10,23,39,26,25,23), +(7,4,11,24,41,27,25,24), +(7,4,12,25,42,28,26,24), +(7,4,13,26,44,29,26,25), +(7,4,14,27,46,30,26,25), +(7,4,15,28,47,30,26,25), +(7,4,16,28,49,31,26,26), +(7,4,17,29,50,32,27,26), +(7,4,18,30,52,33,27,27), +(7,4,19,31,54,34,27,27), +(7,4,20,32,56,35,27,28), +(7,4,21,33,57,35,27,28), +(7,4,22,34,59,36,28,29), +(7,4,23,35,61,37,28,29), +(7,4,24,36,62,38,28,30), +(7,4,25,37,64,39,28,30), +(7,4,26,38,66,40,29,31), +(7,4,27,39,68,41,29,31), +(7,4,28,40,70,42,29,32), +(7,4,29,41,72,43,29,32), +(7,4,30,42,73,43,29,33), +(7,4,31,43,75,44,30,33), +(7,4,32,44,77,45,30,34), +(7,4,33,45,79,46,30,34), +(7,4,34,46,81,47,31,35), +(7,4,35,47,83,48,31,35), +(7,4,36,48,85,49,31,36), +(7,4,37,49,87,50,31,36), +(7,4,38,50,89,51,32,37), +(7,4,39,51,91,52,32,38), +(7,4,40,53,93,53,32,38), +(7,4,41,54,95,54,33,39), +(7,4,42,55,97,55,33,39), +(7,4,43,56,99,56,33,40), +(7,4,44,57,101,57,33,40), +(7,4,45,58,103,59,34,41), +(7,4,46,59,105,60,34,42), +(7,4,47,61,107,61,34,42), +(7,4,48,62,110,62,35,43), +(7,4,49,63,112,63,35,44), +(7,4,50,64,114,64,35,44), +(7,4,51,65,116,65,36,45), +(7,4,52,67,118,66,36,45), +(7,4,53,68,121,67,36,46), +(7,4,54,69,123,69,37,47), +(7,4,55,70,125,70,37,47), +(7,4,56,72,127,71,37,48), +(7,4,57,73,130,72,38,49), +(7,4,58,74,132,73,38,49), +(7,4,59,75,134,74,39,50), +(7,4,60,77,137,76,39,51), +(7,4,61,78,139,77,39,51), +(7,4,62,79,141,78,40,52), +(7,4,63,81,144,79,40,53), +(7,4,64,82,146,80,41,54), +(7,4,65,83,149,82,41,54), +(7,4,66,85,151,83,41,55), +(7,4,67,86,154,84,42,56), +(7,4,68,87,156,85,42,57), +(7,4,69,89,158,87,43,57), +(7,4,70,90,161,88,43,58), +(7,4,71,92,164,89,44,59), +(7,4,72,94,167,91,45,59), +(7,4,73,95,170,93,45,60), +(7,4,74,97,173,94,46,61), +(7,4,75,99,176,96,46,62), +(7,4,76,100,179,97,46,63), +(7,4,77,102,182,102,47,64), +(7,4,78,104,186,105,47,65), +(7,4,79,106,189,106,48,66), +(7,4,80,108,192,108,48,67), + +(7,6,1,18,23,21,24,20), +(7,6,2,19,24,22,24,20), +(7,6,3,21,25,23,24,21), +(7,6,4,22,25,25,24,21), +(7,6,5,23,26,26,24,21), +(7,6,6,25,27,27,24,21), +(7,6,7,26,28,28,24,22), +(7,6,8,27,29,29,25,22), +(7,6,9,29,29,31,25,22), +(7,6,10,30,30,32,25,23), +(7,6,11,32,31,33,25,23), +(7,6,12,33,32,34,25,23), +(7,6,13,34,33,36,25,24), +(7,6,14,36,34,37,25,24), +(7,6,15,37,35,38,25,24), +(7,6,16,39,36,40,25,25), +(7,6,17,40,36,41,25,25), +(7,6,18,42,37,43,26,25), +(7,6,19,43,38,44,26,26), +(7,6,20,45,39,45,26,26), +(7,6,21,47,40,47,26,26), +(7,6,22,48,41,48,26,27), +(7,6,23,50,42,50,26,27), +(7,6,24,51,43,51,26,28), +(7,6,25,53,44,52,27,28), +(7,6,26,55,45,54,27,28), +(7,6,27,56,46,55,27,29), +(7,6,28,58,47,57,27,29), +(7,6,29,59,48,58,27,30), +(7,6,30,61,49,60,27,30), +(7,6,31,63,50,62,27,30), +(7,6,32,65,51,63,28,31), +(7,6,33,66,52,65,28,31), +(7,6,34,68,53,66,28,32), +(7,6,35,70,55,68,28,32), +(7,6,36,72,56,69,28,33), +(7,6,37,73,57,71,29,33), +(7,6,38,75,58,73,29,34), +(7,6,39,77,59,74,29,34), +(7,6,40,79,60,76,29,35), +(7,6,41,81,61,78,29,35), +(7,6,42,82,62,79,30,35), +(7,6,43,84,64,81,30,36), +(7,6,44,86,65,83,30,36), +(7,6,45,88,66,85,30,37), +(7,6,46,90,67,86,30,37), +(7,6,47,92,68,88,31,38), +(7,6,48,94,70,90,31,38), +(7,6,49,96,71,92,31,39), +(7,6,50,98,72,93,31,40), +(7,6,51,99,72,93,32,40), +(7,6,52,100,73,95,32,41), +(7,6,53,101,74,96,32,41), +(7,6,54,102,75,97,32,42), +(7,6,55,103,76,98,33,42), +(7,6,56,106,78,101,33,43), +(7,6,57,111,79,103,33,43), +(7,6,58,113,80,105,34,44), +(7,6,59,116,82,107,34,44), +(7,6,60,118,83,109,34,45), +(7,6,61,120,84,111,34,46), +(7,6,62,127,86,119,34,46), +(7,6,63,129,87,122,35,47), +(7,6,64,132,89,125,35,47), +(7,6,65,135,90,127,35,48), +(7,6,66,137,92,130,35,49), +(7,6,67,138,93,130,36,49), +(7,6,68,140,95,131,36,50), +(7,6,69,142,96,131,36,51), +(7,6,70,145,98,132,36,51), +(7,6,71,148,100,135,37,52), +(7,6,72,150,101,137,37,53), +(7,6,73,153,103,140,37,54), +(7,6,74,154,105,142,37,54), +(7,6,75,155,106,145,38,55), +(7,6,76,158,108,151,38,56), +(7,6,77,161,110,157,38,57), +(7,6,78,164,111,162,38,57), +(7,6,79,167,113,165,39,58), +(7,6,80,170,115,168,39,59), + +(7,8,1,15,23,19,27,22), +(7,8,2,15,23,19,28,23), +(7,8,3,15,23,20,30,25), +(7,8,4,15,23,20,31,26), +(7,8,5,15,24,20,32,27), +(7,8,6,15,24,20,34,29), +(7,8,7,16,24,21,35,30), +(7,8,8,16,24,21,37,31), +(7,8,9,16,24,21,38,33), +(7,8,10,16,24,22,40,34), +(7,8,11,16,25,22,41,36), +(7,8,12,16,25,22,42,37), +(7,8,13,16,25,23,44,38), +(7,8,14,16,25,23,45,40), +(7,8,15,17,25,23,47,41), +(7,8,16,17,25,24,49,43), +(7,8,17,17,26,24,50,44), +(7,8,18,17,26,24,52,46), +(7,8,19,17,26,25,53,47), +(7,8,20,17,26,25,55,49), +(7,8,21,17,26,26,57,51), +(7,8,22,18,27,26,58,52), +(7,8,23,18,27,26,60,54), +(7,8,24,18,27,27,61,55), +(7,8,25,18,27,27,63,57), +(7,8,26,18,28,27,65,59), +(7,8,27,18,28,28,67,60), +(7,8,28,18,28,28,68,62), +(7,8,29,19,28,29,70,64), +(7,8,30,19,29,29,72,65), +(7,8,31,19,29,30,74,67), +(7,8,32,19,29,30,75,69), +(7,8,33,19,29,30,77,70), +(7,8,34,20,30,31,79,72), +(7,8,35,20,30,31,81,74), +(7,8,36,20,30,32,83,76), +(7,8,37,20,30,32,85,78), +(7,8,38,20,31,33,86,79), +(7,8,39,21,31,33,88,81), +(7,8,40,21,31,34,90,83), +(7,8,41,21,32,34,92,85), +(7,8,42,21,32,35,94,87), +(7,8,43,21,32,35,96,89), +(7,8,44,22,32,36,98,91), +(7,8,45,22,33,36,100,92), +(7,8,46,22,33,37,102,94), +(7,8,47,22,33,37,104,96), +(7,8,48,22,34,38,106,98), +(7,8,49,23,34,38,108,100), +(7,8,50,23,34,39,110,102), +(7,8,51,23,35,39,112,104), +(7,8,52,23,35,40,114,106), +(7,8,53,24,35,40,117,108), +(7,8,54,24,36,41,119,110), +(7,8,55,24,36,41,121,112), +(7,8,56,24,37,42,123,114), +(7,8,57,25,37,42,125,117), +(7,8,58,25,37,43,127,119), +(7,8,59,25,38,43,130,121), +(7,8,60,25,38,44,132,123), +(7,8,61,26,38,45,134,125), +(7,8,62,26,39,45,136,127), +(7,8,63,26,39,46,139,129), +(7,8,64,26,40,46,141,132), +(7,8,65,27,40,47,143,134), +(7,8,66,27,40,48,146,136), +(7,8,67,27,41,48,148,138), +(7,8,68,27,41,49,150,140), +(7,8,69,28,42,49,153,143), +(7,8,70,28,42,50,155,145), +(7,8,71,28,42,51,168,148), +(7,8,72,28,43,52,168,151), +(7,8,73,28,43,53,171,154), +(7,8,74,29,44,53,174,156), +(7,8,75,29,44,54,177,159), +(7,8,76,29,44,55,180,162), +(7,8,77,30,45,56,183,165), +(7,8,78,30,45,56,186,168), +(7,8,79,30,46,57,190,171), +(7,8,80,31,46,58,193,174), + +(7,9,1,15,23,20,26,22), +(7,9,2,15,23,21,27,23), +(7,9,3,16,24,21,28,24), +(7,9,4,16,24,22,29,25), +(7,9,5,16,24,22,31,27), +(7,9,6,17,25,23,32,28), +(7,9,7,17,25,23,33,29), +(7,9,8,17,26,24,34,30), +(7,9,9,17,26,25,36,31), +(7,9,10,18,26,25,37,33), +(7,9,11,18,27,26,38,34), +(7,9,12,18,27,26,39,35), +(7,9,13,19,28,27,41,36), +(7,9,14,19,28,28,42,38), +(7,9,15,20,28,28,43,39), +(7,9,16,20,29,29,45,40), +(7,9,17,20,29,30,46,42), +(7,9,18,21,30,30,47,43), +(7,9,19,21,30,31,49,44), +(7,9,20,21,31,32,50,46), +(7,9,21,22,31,32,51,47), +(7,9,22,22,31,33,53,49), +(7,9,23,23,32,34,54,50), +(7,9,24,23,32,34,56,51), +(7,9,25,23,33,35,57,53), +(7,9,26,24,33,36,59,54), +(7,9,27,24,34,37,60,56), +(7,9,28,25,34,37,62,57), +(7,9,29,25,35,38,63,59), +(7,9,30,25,35,39,65,60), +(7,9,31,26,36,40,66,62), +(7,9,32,26,36,40,68,63), +(7,9,33,27,37,41,69,65), +(7,9,34,27,38,42,71,66), +(7,9,35,28,38,43,73,68), +(7,9,36,28,39,43,74,69), +(7,9,37,28,39,44,76,71), +(7,9,38,29,40,45,77,73), +(7,9,39,29,40,46,79,74), +(7,9,40,30,41,47,81,76), +(7,9,41,30,41,48,82,78), +(7,9,42,31,42,48,84,79), +(7,9,43,31,43,49,86,81), +(7,9,44,32,43,50,88,83), +(7,9,45,32,44,51,89,84), +(7,9,46,33,44,52,91,86), +(7,9,47,33,45,53,93,88), +(7,9,48,34,46,54,95,89), +(7,9,49,34,46,54,96,91), +(7,9,50,35,47,55,98,93), +(7,9,51,35,48,56,100,95), +(7,9,52,36,48,57,102,97), +(7,9,53,36,49,58,104,98), +(7,9,54,37,50,59,105,100), +(7,9,55,37,50,60,107,102), +(7,9,56,38,51,61,109,104), +(7,9,57,38,52,62,111,106), +(7,9,58,39,52,63,113,108), +(7,9,59,40,53,64,115,109), +(7,9,60,40,54,65,117,111), +(7,9,61,41,54,66,119,113), +(7,9,62,41,55,67,121,115), +(7,9,63,42,56,68,123,117), +(7,9,64,42,57,69,125,119), +(7,9,65,43,57,70,127,121), +(7,9,66,44,58,71,129,123), +(7,9,67,44,59,72,131,125), +(7,9,68,45,59,73,133,127), +(7,9,69,45,60,74,135,129), +(7,9,70,46,61,75,137,131), +(7,9,71,47,62,84,147,142), +(7,9,72,48,62,85,148,144), +(7,9,73,49,63,85,153,147), +(7,9,74,49,64,88,153,150), +(7,9,75,50,65,90,155,152), +(7,9,76,51,66,91,158,155), +(7,9,77,52,67,92,161,158), +(7,9,78,52,68,93,163,161), +(7,9,79,53,69,95,166,164), +(7,9,80,54,70,96,170,166), + +(8,1,1,24,22,23,16,21), +(8,1,2,25,23,24,16,21), +(8,1,3,27,24,25,16,22), +(8,1,4,28,24,26,16,22), +(8,1,5,29,25,28,16,22), +(8,1,6,31,26,29,16,22), +(8,1,7,32,27,30,17,23), +(8,1,8,33,28,31,17,23), +(8,1,9,35,28,33,17,23), +(8,1,10,36,29,34,17,24), +(8,1,11,37,30,35,17,24), +(8,1,12,39,31,36,17,24), +(8,1,13,40,32,38,17,25), +(8,1,14,42,33,39,17,25), +(8,1,15,43,34,40,18,25), +(8,1,16,45,35,42,18,26), +(8,1,17,46,35,43,18,26), +(8,1,18,48,36,44,18,26), +(8,1,19,49,37,46,18,27), +(8,1,20,51,38,47,18,27), +(8,1,21,52,39,49,18,27), +(8,1,22,54,40,50,18,28), +(8,1,23,55,41,51,19,28), +(8,1,24,57,42,53,19,29), +(8,1,25,59,43,54,19,29), +(8,1,26,60,44,56,19,29), +(8,1,27,62,45,57,19,30), +(8,1,28,63,46,59,19,30), +(8,1,29,65,47,60,20,31), +(8,1,30,67,48,62,20,31), +(8,1,31,69,49,63,20,31), +(8,1,32,70,50,65,20,32), +(8,1,33,72,51,67,20,32), +(8,1,34,74,53,68,20,33), +(8,1,35,75,54,70,21,33), +(8,1,36,77,55,71,21,34), +(8,1,37,79,56,73,21,34), +(8,1,38,81,57,75,21,35), +(8,1,39,83,58,76,21,35), +(8,1,40,84,59,78,22,35), +(8,1,41,86,60,80,22,36), +(8,1,42,88,62,81,22,36), +(8,1,43,90,63,83,22,37), +(8,1,44,92,64,85,22,37), +(8,1,45,94,65,86,23,38), +(8,1,46,96,66,88,23,38), +(8,1,47,98,67,90,23,39), +(8,1,48,100,69,92,23,39), +(8,1,49,102,70,93,24,40), +(8,1,50,103,71,95,24,40), +(8,1,51,105,72,97,24,41), +(8,1,52,107,74,99,24,42), +(8,1,53,109,75,101,25,42), +(8,1,54,112,76,103,25,43), +(8,1,55,114,78,104,25,43), +(8,1,56,116,79,106,25,44), +(8,1,57,118,80,108,25,44), +(8,1,58,120,81,110,26,45), +(8,1,59,122,83,112,26,45), +(8,1,60,124,84,114,26,46), +(8,1,61,126,85,116,27,47), +(8,1,62,128,87,118,27,47), +(8,1,63,130,88,120,27,48), +(8,1,64,133,90,122,27,48), +(8,1,65,135,91,124,28,49), +(8,1,66,137,92,126,28,50), +(8,1,67,139,94,128,28,50), +(8,1,68,141,95,130,28,51), +(8,1,69,144,97,132,29,51), +(8,1,70,146,98,134,29,52), +(8,1,71,149,99,136,29,53), +(8,1,72,151,101,139,29,54), +(8,1,73,154,103,141,29,55), +(8,1,74,157,104,144,30,55), +(8,1,75,166,106,151,30,56), +(8,1,76,172,108,157,30,57), +(8,1,77,175,110,161,31,58), +(8,1,78,179,111,163,31,58), +(8,1,79,182,113,164,31,59), +(8,1,80,185,115,169,32,60), + +(8,3,1,21,25,22,16,22), +(8,3,2,21,26,23,17,23), +(8,3,3,22,28,24,17,23), +(8,3,4,22,29,25,18,24), +(8,3,5,23,30,26,18,25), +(8,3,6,23,32,27,19,25), +(8,3,7,24,33,28,20,26), +(8,3,8,24,35,28,20,26), +(8,3,9,25,36,29,21,27), +(8,3,10,25,38,30,21,28), +(8,3,11,25,39,31,22,29), +(8,3,12,26,41,32,23,29), +(8,3,13,26,42,33,23,30), +(8,3,14,27,44,34,24,31), +(8,3,15,27,45,35,25,31), +(8,3,16,28,47,36,25,32), +(8,3,17,28,48,38,26,33), +(8,3,18,29,50,39,27,34), +(8,3,19,29,51,40,28,34), +(8,3,20,30,53,41,28,35), +(8,3,21,31,55,42,29,36), +(8,3,22,31,56,43,30,37), +(8,3,23,32,58,44,30,37), +(8,3,24,32,60,45,31,38), +(8,3,25,33,61,46,32,39), +(8,3,26,33,63,48,33,40), +(8,3,27,34,65,49,33,41), +(8,3,28,35,66,50,34,41), +(8,3,29,35,68,51,35,42), +(8,3,30,36,70,52,36,43), +(8,3,31,36,72,53,37,44), +(8,3,32,37,73,55,37,45), +(8,3,33,38,75,56,38,46), +(8,3,34,38,77,57,39,47), +(8,3,35,39,79,58,40,48), +(8,3,36,39,81,60,41,48), +(8,3,37,40,83,61,41,49), +(8,3,38,41,85,62,42,50), +(8,3,39,41,86,63,43,51), +(8,3,40,42,88,65,44,52), +(8,3,41,43,90,66,45,53), +(8,3,42,43,92,67,46,54), +(8,3,43,44,94,69,47,55), +(8,3,44,45,96,70,47,56), +(8,3,45,45,98,71,48,57), +(8,3,46,46,100,73,49,58), +(8,3,47,47,102,74,50,59), +(8,3,48,48,104,76,51,60), +(8,3,49,48,106,77,52,61), +(8,3,50,49,108,78,53,62), +(8,3,51,50,110,80,54,63), +(8,3,52,51,113,81,55,64), +(8,3,53,51,115,83,56,65), +(8,3,54,52,117,84,57,66), +(8,3,55,53,119,86,58,67), +(8,3,56,54,121,87,59,68), +(8,3,57,54,123,89,60,69), +(8,3,58,55,126,90,61,70), +(8,3,59,56,128,92,62,71), +(8,3,60,57,130,93,63,73), +(8,3,61,58,132,95,64,74), +(8,3,62,58,134,96,65,75), +(8,3,63,59,137,98,66,76), +(8,3,64,60,139,99,67,77), +(8,3,65,61,141,101,68,78), +(8,3,66,62,144,103,69,79), +(8,3,67,62,146,104,70,80), +(8,3,68,63,148,106,71,82), +(8,3,69,64,151,107,72,83), +(8,3,70,65,153,109,73,84), +(8,3,71,66,156,111,74,85), +(8,3,72,67,159,113,75,86), +(8,3,73,68,162,115,76,88), +(8,3,74,69,165,117,78,89), +(8,3,75,70,174,119,82,91), +(8,3,76,71,177,121,83,92), +(8,3,77,72,180,123,85,94), +(8,3,78,73,184,125,86,95), +(8,3,79,74,187,127,87,97), +(8,3,80,75,190,129,89,98), + +(8,4,1,22,25,22,16,21), +(8,4,2,23,26,23,16,21), +(8,4,3,24,28,23,16,22), +(8,4,4,24,29,24,16,22), +(8,4,5,25,31,25,17,22), +(8,4,6,26,32,25,17,23), +(8,4,7,27,34,26,17,23), +(8,4,8,27,35,27,17,24), +(8,4,9,28,37,28,17,24), +(8,4,10,29,38,28,18,24), +(8,4,11,30,40,29,18,25), +(8,4,12,31,41,30,18,25), +(8,4,13,32,43,31,18,26), +(8,4,14,32,45,32,18,26), +(8,4,15,33,46,32,19,26), +(8,4,16,34,48,33,19,27), +(8,4,17,35,50,34,19,27), +(8,4,18,36,51,35,19,28), +(8,4,19,37,53,36,19,28), +(8,4,20,38,55,36,20,29), +(8,4,21,39,56,37,20,29), +(8,4,22,40,58,38,20,30), +(8,4,23,41,60,39,20,30), +(8,4,24,42,62,40,20,31), +(8,4,25,43,63,41,21,31), +(8,4,26,44,65,42,21,32), +(8,4,27,45,67,43,21,32), +(8,4,28,46,69,44,21,33), +(8,4,29,47,71,44,22,33), +(8,4,30,48,72,45,22,34), +(8,4,31,49,74,46,22,34), +(8,4,32,50,76,47,22,35), +(8,4,33,51,78,48,23,35), +(8,4,34,52,80,49,23,36), +(8,4,35,53,82,50,23,36), +(8,4,36,54,84,51,24,37), +(8,4,37,55,86,52,24,37), +(8,4,38,56,88,53,24,38), +(8,4,39,57,90,54,24,38), +(8,4,40,58,92,55,25,39), +(8,4,41,59,94,56,25,40), +(8,4,42,60,96,57,25,40), +(8,4,43,62,98,58,26,41), +(8,4,44,63,100,59,26,41), +(8,4,45,64,102,60,26,42), +(8,4,46,65,104,61,27,43), +(8,4,47,66,107,63,27,43), +(8,4,48,67,109,64,27,44), +(8,4,49,69,111,65,27,44), +(8,4,50,70,113,66,28,45), +(8,4,51,71,115,67,28,46), +(8,4,52,72,117,68,28,46), +(8,4,53,74,120,69,29,47), +(8,4,54,75,122,70,29,48), +(8,4,55,76,124,72,29,48), +(8,4,56,77,126,73,30,49), +(8,4,57,79,129,74,30,50), +(8,4,58,80,131,75,30,50), +(8,4,59,81,133,76,31,51), +(8,4,60,82,136,77,31,52), +(8,4,61,84,138,79,32,52), +(8,4,62,85,140,80,32,53), +(8,4,63,86,143,81,32,54), +(8,4,64,88,145,82,33,55), +(8,4,65,89,148,84,33,55), +(8,4,66,90,150,85,33,56), +(8,4,67,92,153,86,34,57), +(8,4,68,93,155,87,34,58), +(8,4,69,95,157,89,35,58), +(8,4,70,96,160,90,35,59), +(8,4,71,98,163,94,35,60), +(8,4,72,100,166,96,36,60), +(8,4,73,101,169,96,36,61), +(8,4,74,103,172,97,37,62), +(8,4,75,105,175,98,37,63), +(8,4,76,106,178,99,37,64), +(8,4,77,108,181,105,38,65), +(8,4,78,110,185,107,38,66), +(8,4,79,112,188,109,39,67), +(8,4,80,114,191,110,39,68), + +(8,5,1,21,22,21,18,24), +(8,5,2,21,22,21,19,25), +(8,5,3,21,22,22,21,27), +(8,5,4,21,23,22,22,28), +(8,5,5,22,23,22,23,29), +(8,5,6,22,23,23,25,31), +(8,5,7,22,23,23,26,32), +(8,5,8,22,24,24,27,34), +(8,5,9,22,24,24,29,35), +(8,5,10,22,24,24,30,37), +(8,5,11,23,24,25,32,38), +(8,5,12,23,24,25,33,40), +(8,5,13,23,25,26,35,41), +(8,5,14,23,25,26,36,43), +(8,5,15,23,25,26,38,44), +(8,5,16,24,26,27,39,46), +(8,5,17,24,26,27,41,47), +(8,5,18,24,26,28,42,49), +(8,5,19,24,26,28,44,50), +(8,5,20,24,27,29,45,52), +(8,5,21,25,27,29,47,54), +(8,5,22,25,27,30,48,55), +(8,5,23,25,28,30,50,57), +(8,5,24,25,28,31,52,59), +(8,5,25,25,28,31,53,60), +(8,5,26,26,28,32,55,62), +(8,5,27,26,29,32,56,64), +(8,5,28,26,29,33,58,65), +(8,5,29,26,29,33,60,67), +(8,5,30,27,30,34,62,69), +(8,5,31,27,30,34,63,71), +(8,5,32,27,30,35,65,73), +(8,5,33,27,31,35,67,74), +(8,5,34,28,31,36,68,76), +(8,5,35,28,32,36,70,78), +(8,5,36,28,32,37,72,80), +(8,5,37,29,32,37,74,82), +(8,5,38,29,33,38,76,84), +(8,5,39,29,33,38,77,86), +(8,5,40,29,33,39,79,87), +(8,5,41,30,34,40,81,89), +(8,5,42,30,34,40,83,91), +(8,5,43,30,35,41,85,93), +(8,5,44,31,35,41,87,95), +(8,5,45,31,35,42,89,97), +(8,5,46,31,36,43,91,99), +(8,5,47,32,36,43,93,101), +(8,5,48,32,37,44,94,103), +(8,5,49,32,37,44,96,105), +(8,5,50,33,37,45,98,107), +(8,5,51,33,38,46,100,110), +(8,5,52,33,38,46,102,112), +(8,5,53,34,39,47,104,114), +(8,5,54,34,39,48,106,116), +(8,5,55,34,40,48,109,118), +(8,5,56,35,40,49,111,120), +(8,5,57,35,41,50,113,122), +(8,5,58,35,41,50,115,125), +(8,5,59,36,42,51,117,127), +(8,5,60,36,42,52,119,129), +(8,5,61,36,42,52,121,131), +(8,5,62,37,43,53,123,133), +(8,5,63,37,43,54,125,136), +(8,5,64,38,44,55,128,138), +(8,5,65,38,44,55,130,140), +(8,5,66,38,45,56,132,143), +(8,5,67,39,45,57,134,145), +(8,5,68,39,46,58,136,147), +(8,5,69,40,46,58,139,150), +(8,5,70,40,47,59,141,152), +(8,5,71,40,48,60,144,155), +(8,5,72,41,48,60,147,158), +(8,5,73,41,49,61,150,161), +(8,5,74,42,49,62,152,164), +(8,5,75,42,50,63,155,167), +(8,5,76,42,51,64,158,170), +(8,5,77,43,51,65,161,173), +(8,5,78,43,52,66,164,176), +(8,5,79,44,52,67,167,179), +(8,5,80,44,53,68,170,182), + +(8,6,1,24,22,23,16,21), +(8,6,2,25,23,24,16,21), +(8,6,3,27,24,25,16,22), +(8,6,4,28,24,26,16,22), +(8,6,5,29,25,28,16,22), +(8,6,6,31,26,29,16,22), +(8,6,7,32,27,30,17,23), +(8,6,8,33,28,31,17,23), +(8,6,9,35,28,33,17,23), +(8,6,10,36,29,34,17,24), +(8,6,11,37,30,35,17,24), +(8,6,12,39,31,36,17,24), +(8,6,13,40,32,38,17,25), +(8,6,14,42,33,39,17,25), +(8,6,15,43,34,40,18,25), +(8,6,16,45,35,42,18,26), +(8,6,17,46,35,43,18,26), +(8,6,18,48,36,44,18,26), +(8,6,19,49,37,46,18,27), +(8,6,20,51,38,47,18,27), +(8,6,21,52,39,49,18,27), +(8,6,22,54,40,50,18,28), +(8,6,23,55,41,51,19,28), +(8,6,24,57,42,53,19,29), +(8,6,25,59,43,54,19,29), +(8,6,26,60,44,56,19,29), +(8,6,27,62,45,57,19,30), +(8,6,28,63,46,59,19,30), +(8,6,29,65,47,60,20,31), +(8,6,30,67,48,62,20,31), +(8,6,31,69,49,63,20,31), +(8,6,32,70,50,65,20,32), +(8,6,33,72,51,67,20,32), +(8,6,34,74,53,68,20,33), +(8,6,35,75,54,70,21,33), +(8,6,36,77,55,71,21,34), +(8,6,37,79,56,73,21,34), +(8,6,38,81,57,75,21,35), +(8,6,39,83,58,76,21,35), +(8,6,40,84,59,78,22,35), +(8,6,41,86,60,80,22,36), +(8,6,42,88,62,81,22,36), +(8,6,43,90,63,83,22,37), +(8,6,44,92,64,85,22,37), +(8,6,45,94,65,86,23,38), +(8,6,46,96,66,88,23,38), +(8,6,47,98,67,90,23,39), +(8,6,48,100,69,92,23,39), +(8,6,49,102,70,93,24,40), +(8,6,50,103,71,95,24,40), +(8,6,51,105,72,96,24,41), +(8,6,52,106,74,97,24,42), +(8,6,53,107,73,98,25,42), +(8,6,54,108,74,99,25,43), +(8,6,55,109,75,100,25,43), +(8,6,56,112,77,103,25,44), +(8,6,57,114,78,105,25,44), +(8,6,58,118,79,107,26,45), +(8,6,59,119,81,109,26,45), +(8,6,60,121,82,111,26,46), +(8,6,61,123,83,113,26,47), +(8,6,62,126,85,115,26,47), +(8,6,63,128,86,118,27,48), +(8,6,64,131,88,120,27,48), +(8,6,65,138,89,122,27,49), +(8,6,66,140,91,125,27,50), +(8,6,67,143,92,127,28,50), +(8,6,68,145,94,129,28,51), +(8,6,69,148,95,132,28,52), +(8,6,70,151,97,134,28,52), +(8,6,71,154,99,137,29,53), +(8,6,72,156,100,139,29,54), +(8,6,73,159,102,142,29,55), +(8,6,74,162,104,144,29,55), +(8,6,75,165,105,147,30,56), +(8,6,76,168,107,150,30,57), +(8,6,77,169,109,153,30,58), +(8,6,78,170,110,155,30,58), +(8,6,79,178,112,158,31,59), +(8,6,80,181,114,161,31,60), + +(8,7,1,22,22,22,17,23), +(8,7,2,23,22,23,18,24), +(8,7,3,24,23,24,19,25), +(8,7,4,25,23,25,20,26), +(8,7,5,25,24,26,21,27), +(8,7,6,26,24,27,22,28), +(8,7,7,27,25,28,23,29), +(8,7,8,28,25,29,24,30), +(8,7,9,29,25,30,25,31), +(8,7,10,30,26,31,26,33), +(8,7,11,31,26,32,27,34), +(8,7,12,32,27,33,28,35), +(8,7,13,33,27,34,29,36), +(8,7,14,34,28,35,30,37), +(8,7,15,34,28,36,31,38), +(8,7,16,35,29,38,32,39), +(8,7,17,36,29,39,33,41), +(8,7,18,37,30,40,34,42), +(8,7,19,38,30,41,35,43), +(8,7,20,39,31,42,36,44), +(8,7,21,40,32,43,37,45), +(8,7,22,41,32,45,38,47), +(8,7,23,43,33,46,39,48), +(8,7,24,44,33,47,40,49), +(8,7,25,45,34,48,42,51), +(8,7,26,46,34,49,43,52), +(8,7,27,47,35,51,44,53), +(8,7,28,48,35,52,45,54), +(8,7,29,49,36,53,46,56), +(8,7,30,50,37,54,48,57), +(8,7,31,51,37,56,49,59), +(8,7,32,52,38,57,50,60), +(8,7,33,53,38,58,51,61), +(8,7,34,55,39,60,52,63), +(8,7,35,56,40,61,54,64), +(8,7,36,57,40,62,55,66), +(8,7,37,58,41,64,56,67), +(8,7,38,59,42,65,57,68), +(8,7,39,61,42,66,59,70), +(8,7,40,62,43,68,60,71), +(8,7,41,63,44,69,61,73), +(8,7,42,64,44,71,63,74), +(8,7,43,65,45,72,64,76), +(8,7,44,67,46,74,65,77), +(8,7,45,68,46,75,67,79), +(8,7,46,69,47,76,68,80), +(8,7,47,71,48,78,69,82), +(8,7,48,72,49,79,71,83), +(8,7,49,73,49,81,72,85), +(8,7,50,74,50,82,74,87), +(8,7,51,76,51,84,75,88), +(8,7,52,77,51,85,77,90), +(8,7,53,78,52,87,78,92), +(8,7,54,80,53,89,79,93), +(8,7,55,81,54,90,81,95), +(8,7,56,83,55,92,82,96), +(8,7,57,84,55,93,84,98), +(8,7,58,85,56,95,85,100), +(8,7,59,87,57,97,87,102), +(8,7,60,88,58,98,88,103), +(8,7,61,90,58,100,90,105), +(8,7,62,91,59,101,91,107), +(8,7,63,93,60,103,93,108), +(8,7,64,94,61,105,94,110), +(8,7,65,95,62,106,96,112), +(8,7,66,97,63,108,98,114), +(8,7,67,98,63,110,99,116), +(8,7,68,100,64,112,101,117), +(8,7,69,101,65,113,102,119), +(8,7,70,103,66,115,104,121), +(8,7,71,104,67,117,116,123), +(8,7,72,106,68,119,118,126), +(8,7,73,108,69,121,121,128), +(8,7,74,110,70,124,123,130), +(8,7,75,112,71,126,125,132), +(8,7,76,114,72,128,127,135), +(8,7,77,115,73,130,129,137), +(8,7,78,117,74,132,132,139), +(8,7,79,119,75,135,134,142), +(8,7,80,121,76,137,136,144), + +(8,8,1,21,22,21,19,23), +(8,8,2,21,22,21,20,24), +(8,8,3,21,22,22,22,26), +(8,8,4,21,22,22,23,27), +(8,8,5,21,23,22,25,28), +(8,8,6,21,23,22,26,30), +(8,8,7,21,23,23,27,31), +(8,8,8,22,23,23,29,32), +(8,8,9,22,23,23,30,34), +(8,8,10,22,23,24,32,35), +(8,8,11,22,24,24,33,37), +(8,8,12,22,24,24,35,38), +(8,8,13,22,24,25,36,39), +(8,8,14,22,24,25,38,41), +(8,8,15,22,24,25,39,42), +(8,8,16,22,24,26,41,44), +(8,8,17,23,25,26,42,45), +(8,8,18,23,25,26,44,47), +(8,8,19,23,25,27,46,48), +(8,8,20,23,25,27,47,50), +(8,8,21,23,25,27,49,51), +(8,8,22,23,26,28,51,53), +(8,8,23,23,26,28,52,55), +(8,8,24,24,26,29,54,56), +(8,8,25,24,26,29,56,58), +(8,8,26,24,27,29,57,60), +(8,8,27,24,27,30,59,61), +(8,8,28,24,27,30,61,63), +(8,8,29,24,27,31,63,65), +(8,8,30,24,28,31,64,66), +(8,8,31,25,28,31,66,68), +(8,8,32,25,28,32,68,70), +(8,8,33,25,28,32,70,71), +(8,8,34,25,29,33,71,73), +(8,8,35,25,29,33,73,75), +(8,8,36,26,29,34,75,77), +(8,8,37,26,29,34,77,79), +(8,8,38,26,30,35,79,80), +(8,8,39,26,30,35,81,82), +(8,8,40,26,30,35,83,84), +(8,8,41,27,31,36,85,86), +(8,8,42,27,31,36,87,88), +(8,8,43,27,31,37,89,90), +(8,8,44,27,32,37,91,91), +(8,8,45,27,32,38,93,93), +(8,8,46,28,32,38,95,95), +(8,8,47,28,32,39,97,97), +(8,8,48,28,33,39,99,99), +(8,8,49,28,33,40,101,101), +(8,8,50,29,33,40,103,103), +(8,8,51,29,34,41,105,105), +(8,8,52,29,34,42,107,107), +(8,8,53,29,35,42,109,109), +(8,8,54,30,35,43,111,111), +(8,8,55,30,35,43,113,113), +(8,8,56,30,36,44,115,115), +(8,8,57,30,36,44,118,118), +(8,8,58,31,36,45,120,120), +(8,8,59,31,37,45,122,122), +(8,8,60,31,37,46,124,124), +(8,8,61,31,37,47,126,126), +(8,8,62,32,38,47,129,128), +(8,8,63,32,38,48,131,130), +(8,8,64,32,39,48,133,133), +(8,8,65,33,39,49,135,135), +(8,8,66,33,39,50,138,137), +(8,8,67,33,40,50,140,139), +(8,8,68,33,40,51,142,141), +(8,8,69,34,41,51,145,144), +(8,8,70,34,41,52,147,146), +(8,8,71,34,41,53,150,149), +(8,8,72,34,42,54,153,152), +(8,8,73,34,42,55,156,155), +(8,8,74,35,43,55,159,157), +(8,8,75,35,43,56,162,160), +(8,8,76,35,43,57,168,163), +(8,8,77,36,44,58,168,166), +(8,8,78,36,44,58,171,169), +(8,8,79,36,45,59,177,172), +(8,8,80,37,45,60,177,175), + +(10,2,1,19,22,21,24,20), +(10,2,2,20,23,22,25,21), +(10,2,3,21,23,23,25,21), +(10,2,4,22,24,24,26,22), +(10,2,5,23,24,25,27,23), +(10,2,6,25,25,26,27,24), +(10,2,7,26,25,27,28,24), +(10,2,8,27,26,28,29,25), +(10,2,9,28,27,29,29,26), +(10,2,10,29,27,31,30,26), +(10,2,11,30,28,32,31,27), +(10,2,12,32,29,33,31,28), +(10,2,13,33,29,34,32,29), +(10,2,14,34,30,35,33,30), +(10,2,15,35,31,36,33,30), +(10,2,16,37,31,37,34,31), +(10,2,17,38,32,39,35,32), +(10,2,18,39,33,40,36,33), +(10,2,19,40,33,41,36,34), +(10,2,20,42,34,42,37,35), +(10,2,21,43,35,44,38,35), +(10,2,22,44,35,45,39,36), +(10,2,23,46,36,46,40,37), +(10,2,24,47,37,47,40,38), +(10,2,25,49,38,49,41,39), +(10,2,26,50,38,50,42,40), +(10,2,27,51,39,51,43,41), +(10,2,28,53,40,53,44,42), +(10,2,29,54,41,54,45,43), +(10,2,30,56,41,55,45,43), +(10,2,31,57,42,57,46,44), +(10,2,32,58,43,58,47,45), +(10,2,33,60,44,59,48,46), +(10,2,34,61,45,61,49,47), +(10,2,35,63,45,62,50,48), +(10,2,36,64,46,64,51,49), +(10,2,37,66,47,65,52,50), +(10,2,38,67,48,67,53,51), +(10,2,39,69,49,68,54,52), +(10,2,40,71,50,69,55,53), +(10,2,41,72,50,71,55,54), +(10,2,42,74,51,72,56,55), +(10,2,43,75,52,74,57,56), +(10,2,44,77,53,75,58,57), +(10,2,45,79,54,77,59,59), +(10,2,46,80,55,78,60,60), +(10,2,47,82,56,80,61,61), +(10,2,48,83,57,82,62,62), +(10,2,49,85,58,83,63,63), +(10,2,50,87,59,85,64,64), +(10,2,51,89,60,86,66,65), +(10,2,52,90,61,88,67,66), +(10,2,53,92,61,90,68,67), +(10,2,54,94,62,91,69,69), +(10,2,55,95,63,93,70,70), +(10,2,56,97,64,95,71,71), +(10,2,57,99,65,96,72,72), +(10,2,58,101,66,98,73,73), +(10,2,59,102,67,100,74,74), +(10,2,60,104,68,101,75,76), +(10,2,61,106,69,103,76,77), +(10,2,62,108,70,105,78,78), +(10,2,63,110,72,106,79,79), +(10,2,64,112,73,108,80,80), +(10,2,65,113,74,110,81,82), +(10,2,66,115,75,112,82,83), +(10,2,67,117,76,114,83,84), +(10,2,68,119,77,115,85,85), +(10,2,69,121,78,117,86,87), +(10,2,70,123,79,119,87,88), +(10,2,71,125,80,120,88,89), +(10,2,72,128,81,123,90,91), +(10,2,73,130,82,125,91,93), +(10,2,74,133,84,127,93,94), +(10,2,75,135,85,129,94,96), +(10,2,76,137,86,132,96,97), +(10,2,77,140,88,134,97,99), +(10,2,78,143,89,136,99,101), +(10,2,79,145,90,139,100,102), +(10,2,80,148,92,141,102,104), + +(10,3,1,17,25,20,24,20), +(10,3,2,17,26,21,25,21), +(10,3,3,18,28,22,25,21), +(10,3,4,18,29,23,26,22), +(10,3,5,19,30,24,26,23), +(10,3,6,19,32,25,27,23), +(10,3,7,20,33,26,27,24), +(10,3,8,20,35,27,28,25), +(10,3,9,21,36,27,29,25), +(10,3,10,21,38,28,29,26), +(10,3,11,22,39,29,30,27), +(10,3,12,22,41,30,31,27), +(10,3,13,23,42,31,31,28), +(10,3,14,23,44,32,32,29), +(10,3,15,24,45,34,32,29), +(10,3,16,24,47,35,33,30), +(10,3,17,25,48,36,34,31), +(10,3,18,25,50,37,34,32), +(10,3,19,26,51,38,35,32), +(10,3,20,26,53,39,36,33), +(10,3,21,27,55,40,37,34), +(10,3,22,27,56,41,37,35), +(10,3,23,28,58,42,38,36), +(10,3,24,28,60,43,39,36), +(10,3,25,29,61,44,39,37), +(10,3,26,30,63,46,40,38), +(10,3,27,30,65,47,41,39), +(10,3,28,31,66,48,42,40), +(10,3,29,31,68,49,42,40), +(10,3,30,32,70,50,43,41), +(10,3,31,33,72,52,44,42), +(10,3,32,33,73,53,45,43), +(10,3,33,34,75,54,46,44), +(10,3,34,34,77,55,46,45), +(10,3,35,35,79,57,47,46), +(10,3,36,36,81,58,48,47), +(10,3,37,36,83,59,49,47), +(10,3,38,37,85,60,50,48), +(10,3,39,38,86,62,51,49), +(10,3,40,38,88,63,51,50), +(10,3,41,39,90,64,52,51), +(10,3,42,40,92,66,53,52), +(10,3,43,40,94,67,54,53), +(10,3,44,41,96,68,55,54), +(10,3,45,42,98,70,56,55), +(10,3,46,42,100,71,57,56), +(10,3,47,43,102,72,58,57), +(10,3,48,44,104,74,59,58), +(10,3,49,45,106,75,60,59), +(10,3,50,45,108,77,61,60), +(10,3,51,46,110,78,61,61), +(10,3,52,47,113,79,62,62), +(10,3,53,47,115,81,63,63), +(10,3,54,48,117,82,64,64), +(10,3,55,49,119,84,65,65), +(10,3,56,50,121,85,66,66), +(10,3,57,50,123,87,67,67), +(10,3,58,51,126,88,68,68), +(10,3,59,52,128,90,69,70), +(10,3,60,53,130,91,70,71), +(10,3,61,54,132,93,71,72), +(10,3,62,54,134,94,72,73), +(10,3,63,55,137,96,73,74), +(10,3,64,56,139,97,75,75), +(10,3,65,57,141,99,76,76), +(10,3,66,58,144,101,77,77), +(10,3,67,58,146,102,78,78), +(10,3,68,59,148,104,79,80), +(10,3,69,60,151,105,80,81), +(10,3,70,61,153,107,81,82), +(10,3,71,62,156,108,82,83), +(10,3,72,63,159,110,83,84), +(10,3,73,64,162,112,84,86), +(10,3,74,65,165,114,86,87), +(10,3,75,66,168,116,87,89), +(10,3,76,67,171,118,89,90), +(10,3,77,68,174,120,90,92), +(10,3,78,69,177,122,91,93), +(10,3,79,70,180,124,92,95), +(10,3,80,71,183,126,94,96), + +(10,4,1,18,25,20,24,19), +(10,4,2,19,26,21,24,19), +(10,4,3,20,28,21,24,20), +(10,4,4,20,29,22,24,20), +(10,4,5,21,31,23,25,20), +(10,4,6,22,32,24,25,21), +(10,4,7,23,34,24,25,21), +(10,4,8,24,35,25,25,22), +(10,4,9,24,37,26,25,22), +(10,4,10,25,38,26,25,22), +(10,4,11,26,40,27,25,23), +(10,4,12,27,41,28,26,23), +(10,4,13,28,43,29,26,24), +(10,4,14,29,45,30,26,24), +(10,4,15,29,46,30,26,25), +(10,4,16,30,48,31,26,25), +(10,4,17,31,50,32,27,25), +(10,4,18,32,51,33,27,26), +(10,4,19,33,53,34,27,26), +(10,4,20,34,55,35,27,27), +(10,4,21,35,56,35,27,27), +(10,4,22,36,58,36,28,28), +(10,4,23,37,60,37,28,28), +(10,4,24,38,62,38,28,29), +(10,4,25,39,63,39,28,29), +(10,4,26,40,65,40,29,30), +(10,4,27,41,67,41,29,30), +(10,4,28,42,69,42,29,31), +(10,4,29,43,71,43,29,31), +(10,4,30,44,72,43,29,32), +(10,4,31,45,74,44,30,32), +(10,4,32,46,76,45,30,33), +(10,4,33,47,78,46,30,33), +(10,4,34,48,80,47,31,34), +(10,4,35,49,82,48,31,34), +(10,4,36,50,84,49,31,35), +(10,4,37,51,86,50,31,35), +(10,4,38,52,88,51,32,36), +(10,4,39,53,90,52,32,37), +(10,4,40,54,92,53,32,37), +(10,4,41,56,94,54,33,38), +(10,4,42,57,96,55,33,38), +(10,4,43,58,98,56,33,39), +(10,4,44,59,100,57,33,39), +(10,4,45,60,102,59,34,40), +(10,4,46,61,104,60,34,41), +(10,4,47,62,107,61,34,41), +(10,4,48,64,109,62,35,42), +(10,4,49,65,111,63,35,43), +(10,4,50,66,113,64,35,43), +(10,4,51,67,115,65,36,44), +(10,4,52,68,117,66,36,44), +(10,4,53,70,120,67,36,45), +(10,4,54,71,122,69,37,46), +(10,4,55,72,124,70,37,46), +(10,4,56,73,126,71,37,47), +(10,4,57,75,129,72,38,48), +(10,4,58,76,131,73,38,48), +(10,4,59,77,133,74,39,49), +(10,4,60,79,136,76,39,50), +(10,4,61,80,138,77,39,51), +(10,4,62,81,140,78,40,51), +(10,4,63,82,143,79,40,52), +(10,4,64,84,145,80,41,53), +(10,4,65,85,148,82,41,53), +(10,4,66,87,150,83,41,54), +(10,4,67,88,153,84,42,55), +(10,4,68,89,155,85,42,56), +(10,4,69,91,157,87,43,56), +(10,4,70,92,160,88,43,57), +(10,4,71,94,163,88,43,58), +(10,4,72,96,166,90,44,58), +(10,4,73,97,169,92,44,59), +(10,4,74,99,172,93,45,60), +(10,4,75,101,175,95,45,61), +(10,4,76,102,178,96,45,62), +(10,4,77,104,181,101,46,63), +(10,4,78,106,185,104,46,64), +(10,4,79,108,188,105,47,65), +(10,4,80,110,191,107,47,66), + +(10,5,1,17,22,19,26,22), +(10,5,2,17,22,19,27,23), +(10,5,3,17,22,20,29,25), +(10,5,4,17,23,20,30,26), +(10,5,5,18,23,20,31,27), +(10,5,6,18,23,21,33,29), +(10,5,7,18,23,21,34,30), +(10,5,8,18,24,22,35,32), +(10,5,9,18,24,22,37,33), +(10,5,10,19,24,22,38,35), +(10,5,11,19,24,23,39,36), +(10,5,12,19,24,23,41,38), +(10,5,13,19,25,24,42,39), +(10,5,14,19,25,24,44,41), +(10,5,15,19,25,25,45,42), +(10,5,16,20,26,25,47,44), +(10,5,17,20,26,25,48,45), +(10,5,18,20,26,26,50,47), +(10,5,19,20,26,26,51,49), +(10,5,20,21,27,27,53,50), +(10,5,21,21,27,27,54,52), +(10,5,22,21,27,28,56,53), +(10,5,23,21,28,28,58,55), +(10,5,24,21,28,29,59,57), +(10,5,25,22,28,29,61,58), +(10,5,26,22,28,30,62,60), +(10,5,27,22,29,30,64,62), +(10,5,28,22,29,31,66,64), +(10,5,29,23,29,31,67,65), +(10,5,30,23,30,32,69,67), +(10,5,31,23,30,32,71,69), +(10,5,32,23,30,33,72,71), +(10,5,33,24,31,33,74,72), +(10,5,34,24,31,34,76,74), +(10,5,35,24,32,34,78,76), +(10,5,36,24,32,35,80,78), +(10,5,37,25,32,35,81,80), +(10,5,38,25,33,36,83,82), +(10,5,39,25,33,37,85,84), +(10,5,40,26,33,37,87,86), +(10,5,41,26,34,38,89,88), +(10,5,42,26,34,38,91,89), +(10,5,43,27,35,39,92,91), +(10,5,44,27,35,39,94,93), +(10,5,45,27,35,40,96,95), +(10,5,46,27,36,41,98,97), +(10,5,47,28,36,41,100,99), +(10,5,48,28,37,42,102,101), +(10,5,49,28,37,43,104,103), +(10,5,50,29,37,43,106,106), +(10,5,51,29,38,44,108,108), +(10,5,52,29,38,44,110,110), +(10,5,53,30,39,45,112,112), +(10,5,54,30,39,46,114,114), +(10,5,55,30,40,46,116,116), +(10,5,56,31,40,47,118,118), +(10,5,57,31,41,48,120,120), +(10,5,58,31,41,48,123,123), +(10,5,59,32,42,49,125,125), +(10,5,60,32,42,50,127,127), +(10,5,61,33,42,51,129,129), +(10,5,62,33,43,51,131,131), +(10,5,63,33,43,52,133,134), +(10,5,64,34,44,53,135,136), +(10,5,65,34,44,53,138,138), +(10,5,66,34,45,54,140,141), +(10,5,67,35,45,55,142,143), +(10,5,68,35,46,56,144,145), +(10,5,69,36,46,56,147,148), +(10,5,70,36,47,57,149,150), +(10,5,71,36,48,57,152,153), +(10,5,72,37,48,57,155,156), +(10,5,73,37,49,58,158,159), +(10,5,74,38,49,59,160,163), +(10,5,75,38,50,60,163,165), +(10,5,76,38,51,61,166,170), +(10,5,77,39,51,62,168,175), +(10,5,78,39,52,63,172,174), +(10,5,79,40,52,64,175,177), +(10,5,80,40,53,65,178,180), + +(10,6,1,18,23,21,24,20), +(10,6,2,19,24,22,24,20), +(10,6,3,21,25,23,24,21), +(10,6,4,22,25,25,24,21), +(10,6,5,23,26,26,24,21), +(10,6,6,25,27,27,24,21), +(10,6,7,26,28,28,24,22), +(10,6,8,27,29,29,25,22), +(10,6,9,29,29,31,25,22), +(10,6,10,30,30,32,25,23), +(10,6,11,32,31,33,25,23), +(10,6,12,33,32,34,25,23), +(10,6,13,34,33,36,25,24), +(10,6,14,36,34,37,25,24), +(10,6,15,37,35,38,25,24), +(10,6,16,39,36,40,25,25), +(10,6,17,40,36,41,25,25), +(10,6,18,42,37,43,26,25), +(10,6,19,43,38,44,26,26), +(10,6,20,45,39,45,26,26), +(10,6,21,47,40,47,26,26), +(10,6,22,48,41,48,26,27), +(10,6,23,50,42,50,26,27), +(10,6,24,51,43,51,26,28), +(10,6,25,53,44,52,27,28), +(10,6,26,55,45,54,27,28), +(10,6,27,56,46,55,27,29), +(10,6,28,58,47,57,27,29), +(10,6,29,59,48,58,27,30), +(10,6,30,61,49,60,27,30), +(10,6,31,63,50,62,27,30), +(10,6,32,65,51,63,28,31), +(10,6,33,66,52,65,28,31), +(10,6,34,68,53,66,28,32), +(10,6,35,70,55,68,28,32), +(10,6,36,72,56,69,28,33), +(10,6,37,73,57,71,29,33), +(10,6,38,75,58,73,29,34), +(10,6,39,77,59,74,29,34), +(10,6,40,79,60,76,29,35), +(10,6,41,81,61,78,29,35), +(10,6,42,82,62,79,30,35), +(10,6,43,84,64,81,30,36), +(10,6,44,86,65,83,30,36), +(10,6,45,88,66,85,30,37), +(10,6,46,90,67,86,30,37), +(10,6,47,92,68,88,31,38), +(10,6,48,94,69,90,31,38), +(10,6,49,96,69,92,31,39), +(10,6,50,98,70,93,31,40), +(10,6,51,100,71,95,32,40), +(10,6,52,102,72,96,32,41), +(10,6,53,103,73,97,32,41), +(10,6,54,104,74,98,32,41), +(10,6,55,105,75,97,33,41), +(10,6,56,108,77,100,33,42), +(10,6,57,113,78,102,33,42), +(10,6,58,115,79,104,34,43), +(10,6,59,117,81,106,34,43), +(10,6,60,118,82,108,34,44), +(10,6,61,119,83,110,34,45), +(10,6,62,121,85,112,34,45), +(10,6,63,124,86,115,35,46), +(10,6,64,127,88,117,35,46), +(10,6,65,133,89,119,35,47), +(10,6,66,135,91,122,35,48), +(10,6,67,139,92,124,36,48), +(10,6,68,141,94,126,36,49), +(10,6,69,142,95,129,36,50), +(10,6,70,145,97,131,36,50), +(10,6,71,150,99,134,37,51), +(10,6,72,152,100,136,37,52), +(10,6,73,155,102,139,37,53), +(10,6,74,158,104,141,37,53), +(10,6,75,159,105,144,38,54), +(10,6,76,160,107,147,38,55), +(10,6,77,163,109,149,38,56), +(10,6,78,166,110,152,38,56), +(10,6,79,169,112,155,39,57), +(10,6,80,172,114,158,39,58), + +(10,8,1,17,22,19,27,21), +(10,8,2,17,22,19,28,22), +(10,8,3,17,22,20,30,24), +(10,8,4,17,22,20,31,25), +(10,8,5,17,23,20,32,26), +(10,8,6,17,23,20,34,28), +(10,8,7,18,23,21,35,29), +(10,8,8,18,23,21,37,30), +(10,8,9,18,23,21,38,32), +(10,8,10,18,23,22,40,33), +(10,8,11,18,24,22,41,35), +(10,8,12,18,24,22,42,36), +(10,8,13,18,24,23,44,37), +(10,8,14,18,24,23,45,39), +(10,8,15,18,24,23,47,40), +(10,8,16,19,24,24,49,42), +(10,8,17,19,25,24,50,43), +(10,8,18,19,25,24,52,45), +(10,8,19,19,25,25,53,46), +(10,8,20,19,25,25,55,48), +(10,8,21,19,25,26,57,50), +(10,8,22,19,26,26,58,51), +(10,8,23,20,26,26,60,53), +(10,8,24,20,26,27,61,54), +(10,8,25,20,26,27,63,56), +(10,8,26,20,27,27,65,58), +(10,8,27,20,27,28,67,59), +(10,8,28,20,27,28,68,61), +(10,8,29,21,27,29,70,63), +(10,8,30,21,28,29,72,64), +(10,8,31,21,28,30,74,66), +(10,8,32,21,28,30,75,68), +(10,8,33,21,28,30,77,70), +(10,8,34,21,29,31,79,71), +(10,8,35,22,29,31,81,73), +(10,8,36,22,29,32,83,75), +(10,8,37,22,29,32,85,77), +(10,8,38,22,30,33,86,78), +(10,8,39,22,30,33,88,80), +(10,8,40,23,30,34,90,82), +(10,8,41,23,31,34,92,84), +(10,8,42,23,31,35,94,86), +(10,8,43,23,31,35,96,88), +(10,8,44,23,32,36,98,90), +(10,8,45,24,32,36,100,92), +(10,8,46,24,32,37,102,93), +(10,8,47,24,32,37,104,95), +(10,8,48,24,33,38,106,97), +(10,8,49,25,33,38,108,99), +(10,8,50,25,33,39,110,101), +(10,8,51,25,34,39,112,103), +(10,8,52,25,34,40,114,105), +(10,8,53,25,35,40,117,107), +(10,8,54,26,35,41,119,109), +(10,8,55,26,35,41,121,111), +(10,8,56,26,36,42,123,113), +(10,8,57,26,36,42,125,116), +(10,8,58,27,36,43,127,118), +(10,8,59,27,37,43,130,120), +(10,8,60,27,37,44,132,122), +(10,8,61,27,37,45,134,124), +(10,8,62,28,38,45,136,126), +(10,8,63,28,38,46,139,128), +(10,8,64,28,39,46,141,131), +(10,8,65,29,39,47,143,133), +(10,8,66,29,39,48,146,135), +(10,8,67,29,40,48,148,137), +(10,8,68,29,40,49,150,139), +(10,8,69,30,41,49,153,142), +(10,8,70,30,41,50,155,144), +(10,8,71,30,41,50,158,147), +(10,8,72,30,42,51,161,150), +(10,8,73,30,42,52,164,153), +(10,8,74,31,43,52,167,155), +(10,8,75,31,43,53,170,158), +(10,8,76,31,43,54,173,161), +(10,8,77,32,44,55,176,164), +(10,8,78,32,44,55,179,167), +(10,8,79,32,45,56,182,170), +(10,8,80,33,45,57,185,173), + +(10,9,1,17,22,20,26,21), +(10,9,2,17,22,21,27,22), +(10,9,3,18,23,21,28,23), +(10,9,4,18,23,22,29,24), +(10,9,5,18,23,22,31,26), +(10,9,6,18,24,23,32,27), +(10,9,7,19,24,23,33,28), +(10,9,8,19,25,24,34,29), +(10,9,9,19,25,25,36,30), +(10,9,10,20,25,25,37,32), +(10,9,11,20,26,26,38,33), +(10,9,12,20,26,26,39,34), +(10,9,13,21,27,27,41,36), +(10,9,14,21,27,28,42,37), +(10,9,15,21,27,28,43,38), +(10,9,16,22,28,29,45,39), +(10,9,17,22,28,30,46,41), +(10,9,18,23,29,30,47,42), +(10,9,19,23,29,31,49,43), +(10,9,20,23,30,32,50,45), +(10,9,21,24,30,32,51,46), +(10,9,22,24,31,33,53,48), +(10,9,23,24,31,34,54,49), +(10,9,24,25,31,34,56,50), +(10,9,25,25,32,35,57,52), +(10,9,26,26,32,36,59,53), +(10,9,27,26,33,37,60,55), +(10,9,28,26,33,37,62,56), +(10,9,29,27,34,38,63,58), +(10,9,30,27,34,39,65,59), +(10,9,31,28,35,40,66,61), +(10,9,32,28,36,40,68,62), +(10,9,33,29,36,41,69,64), +(10,9,34,29,37,42,71,65), +(10,9,35,29,37,43,73,67), +(10,9,36,30,38,43,74,69), +(10,9,37,30,38,44,76,70), +(10,9,38,31,39,45,77,72), +(10,9,39,31,39,46,79,73), +(10,9,40,32,40,47,81,75), +(10,9,41,32,41,48,82,77), +(10,9,42,33,41,48,84,78), +(10,9,43,33,42,49,86,80), +(10,9,44,34,42,50,88,82), +(10,9,45,34,43,51,89,83), +(10,9,46,35,44,52,91,85), +(10,9,47,35,44,53,93,87), +(10,9,48,36,45,54,95,89), +(10,9,49,36,45,54,96,90), +(10,9,50,37,46,55,98,92), +(10,9,51,37,47,56,100,94), +(10,9,52,38,47,57,102,96), +(10,9,53,38,48,58,104,97), +(10,9,54,39,49,59,105,99), +(10,9,55,39,49,60,107,101), +(10,9,56,40,50,61,109,103), +(10,9,57,40,51,62,111,105), +(10,9,58,41,51,63,113,107), +(10,9,59,42,52,64,115,108), +(10,9,60,42,53,65,117,110), +(10,9,61,43,53,66,119,112), +(10,9,62,43,54,67,121,114), +(10,9,63,44,55,68,123,116), +(10,9,64,44,56,69,125,118), +(10,9,65,45,56,70,127,120), +(10,9,66,46,57,71,129,122), +(10,9,67,46,58,72,131,124), +(10,9,68,47,58,73,133,126), +(10,9,69,47,59,74,135,128), +(10,9,70,48,60,75,137,130), +(10,9,71,49,61,83,139,141), +(10,9,72,50,61,84,142,143), +(10,9,73,51,62,84,144,146), +(10,9,74,51,63,86,147,149), +(10,9,75,52,64,89,149,151), +(10,9,76,53,65,90,155,154), +(10,9,77,54,66,91,155,157), +(10,9,78,54,67,93,157,160), +(10,9,79,55,68,94,160,163), +(10,9,80,56,69,95,163,165), + +(11,1,1,24,17,21,21,22), +(11,1,2,25,18,22,21,22), +(11,1,3,27,19,23,21,23), +(11,1,4,28,19,25,21,23), +(11,1,5,29,20,26,21,23), +(11,1,6,31,21,27,21,23), +(11,1,7,32,22,28,21,24), +(11,1,8,33,23,29,22,24), +(11,1,9,35,24,31,22,24), +(11,1,10,36,24,32,22,25), +(11,1,11,37,25,33,22,25), +(11,1,12,39,26,34,22,25), +(11,1,13,40,27,36,22,26), +(11,1,14,42,28,37,22,26), +(11,1,15,43,29,38,22,26), +(11,1,16,45,30,40,22,27), +(11,1,17,46,31,41,23,27), +(11,1,18,48,32,43,23,27), +(11,1,19,49,33,44,23,28), +(11,1,20,51,34,45,23,28), +(11,1,21,52,34,47,23,28), +(11,1,22,54,35,48,23,29), +(11,1,23,55,36,50,23,29), +(11,1,24,57,37,51,24,30), +(11,1,25,59,38,52,24,30), +(11,1,26,60,39,54,24,30), +(11,1,27,62,40,55,24,31), +(11,1,28,63,41,57,24,31), +(11,1,29,65,43,58,24,32), +(11,1,30,67,44,60,24,32), +(11,1,31,69,45,62,25,32), +(11,1,32,70,46,63,25,33), +(11,1,33,72,47,65,25,33), +(11,1,34,74,48,66,25,34), +(11,1,35,75,49,68,25,34), +(11,1,36,77,50,69,26,35), +(11,1,37,79,51,71,26,35), +(11,1,38,81,52,73,26,35), +(11,1,39,83,53,74,26,36), +(11,1,40,84,55,76,26,36), +(11,1,41,86,56,78,27,37), +(11,1,42,88,57,79,27,37), +(11,1,43,90,58,81,27,38), +(11,1,44,92,59,83,27,38), +(11,1,45,94,60,85,27,39), +(11,1,46,96,62,86,28,39), +(11,1,47,98,63,88,28,40), +(11,1,48,100,64,90,28,40), +(11,1,49,102,65,92,28,41), +(11,1,50,103,66,93,29,41), +(11,1,51,105,68,95,29,42), +(11,1,52,107,69,97,29,42), +(11,1,53,109,70,99,29,43), +(11,1,54,112,71,101,30,44), +(11,1,55,114,73,103,30,44), +(11,1,56,116,74,104,30,45), +(11,1,57,118,75,106,30,45), +(11,1,58,120,77,108,31,46), +(11,1,59,122,78,110,31,46), +(11,1,60,124,79,112,31,47), +(11,1,61,126,81,114,31,48), +(11,1,62,128,82,116,32,48), +(11,1,63,130,83,118,32,49), +(11,1,64,133,85,120,32,49), +(11,1,65,135,86,122,33,50), +(11,1,66,137,87,124,33,51), +(11,1,67,139,89,126,33,51), +(11,1,68,141,90,128,33,52), +(11,1,69,144,92,130,34,52), +(11,1,70,146,93,132,34,53), +(11,1,71,149,94,134,34,54), +(11,1,72,151,96,137,34,55), +(11,1,73,154,98,139,34,56), +(11,1,74,157,99,142,35,56), +(11,1,75,166,101,149,35,57), +(11,1,76,172,103,155,35,58), +(11,1,77,175,105,159,36,59), +(11,1,78,179,106,161,36,59), +(11,1,79,182,108,164,36,60), +(11,1,80,185,110,167,37,61), + +(11,2,1,23,17,21,21,23), +(11,2,2,24,18,22,22,24), +(11,2,3,25,18,23,22,24), +(11,2,4,26,19,24,23,25), +(11,2,5,27,19,25,24,26), +(11,2,6,29,20,26,24,26), +(11,2,7,30,21,27,25,27), +(11,2,8,31,21,28,26,28), +(11,2,9,32,22,29,26,29), +(11,2,10,33,22,31,27,29), +(11,2,11,34,23,32,28,30), +(11,2,12,36,24,33,28,31), +(11,2,13,37,24,34,29,32), +(11,2,14,38,25,35,30,32), +(11,2,15,39,26,36,31,33), +(11,2,16,40,26,37,31,34), +(11,2,17,42,27,39,32,35), +(11,2,18,43,28,40,33,36), +(11,2,19,44,28,41,34,37), +(11,2,20,46,29,42,34,37), +(11,2,21,47,30,44,35,38), +(11,2,22,48,31,45,36,39), +(11,2,23,50,31,46,37,40), +(11,2,24,51,32,47,38,41), +(11,2,25,52,33,49,38,42), +(11,2,26,54,34,50,39,43), +(11,2,27,55,34,51,40,44), +(11,2,28,56,35,53,41,44), +(11,2,29,58,36,54,42,45), +(11,2,30,59,37,55,43,46), +(11,2,31,61,37,57,43,47), +(11,2,32,62,38,58,44,48), +(11,2,33,64,39,59,45,49), +(11,2,34,65,40,61,46,50), +(11,2,35,67,41,62,47,51), +(11,2,36,68,42,64,48,52), +(11,2,37,70,42,65,49,53), +(11,2,38,71,43,67,50,54), +(11,2,39,73,44,68,51,55), +(11,2,40,74,45,69,52,56), +(11,2,41,76,46,71,53,57), +(11,2,42,78,47,72,54,58), +(11,2,43,79,47,74,55,59), +(11,2,44,81,48,75,56,60), +(11,2,45,82,49,77,57,61), +(11,2,46,84,50,78,58,62), +(11,2,47,86,51,80,59,64), +(11,2,48,87,52,82,60,65), +(11,2,49,89,53,83,61,66), +(11,2,50,91,54,85,62,67), +(11,2,51,92,55,86,63,68), +(11,2,52,94,56,88,64,69), +(11,2,53,96,57,90,65,70), +(11,2,54,97,58,91,66,71), +(11,2,55,99,59,93,67,73), +(11,2,56,101,60,95,68,74), +(11,2,57,103,61,96,69,75), +(11,2,58,105,62,98,70,76), +(11,2,59,106,63,100,71,77), +(11,2,60,108,64,101,72,78), +(11,2,61,110,65,103,74,80), +(11,2,62,112,66,105,75,81), +(11,2,63,114,67,106,76,82), +(11,2,64,116,68,108,77,83), +(11,2,65,117,69,110,78,85), +(11,2,66,119,70,112,79,86), +(11,2,67,121,71,114,80,87), +(11,2,68,123,72,115,82,88), +(11,2,69,125,73,117,83,90), +(11,2,70,127,74,119,84,91), +(11,2,71,130,75,121,87,92), +(11,2,72,132,76,124,90,94), +(11,2,73,134,77,126,93,96), +(11,2,74,137,79,128,97,97), +(11,2,75,139,80,130,101,99), +(11,2,76,142,81,133,106,100), +(11,2,77,144,83,135,108,102), +(11,2,78,147,84,137,110,104), +(11,2,79,149,85,140,111,105), +(11,2,80,152,87,142,113,107), + +(11,3,1,21,20,20,21,23), +(11,3,2,21,21,21,22,24), +(11,3,3,22,23,22,22,24), +(11,3,4,22,24,23,23,25), +(11,3,5,23,25,24,23,25), +(11,3,6,23,27,25,24,26), +(11,3,7,24,28,26,24,27), +(11,3,8,24,30,27,25,27), +(11,3,9,25,31,27,26,28), +(11,3,10,25,33,28,26,29), +(11,3,11,25,34,29,27,29), +(11,3,12,26,36,30,28,30), +(11,3,13,26,37,31,28,31), +(11,3,14,27,39,32,29,32), +(11,3,15,27,40,34,30,32), +(11,3,16,28,42,35,30,33), +(11,3,17,28,43,36,31,34), +(11,3,18,29,45,37,32,35), +(11,3,19,29,47,38,32,35), +(11,3,20,30,48,39,33,36), +(11,3,21,31,50,40,34,37), +(11,3,22,31,51,41,34,38), +(11,3,23,32,53,42,35,38), +(11,3,24,32,55,43,36,39), +(11,3,25,33,57,44,37,40), +(11,3,26,33,58,46,37,41), +(11,3,27,34,60,47,38,42), +(11,3,28,35,62,48,39,42), +(11,3,29,35,63,49,40,43), +(11,3,30,36,65,50,40,44), +(11,3,31,36,67,52,41,45), +(11,3,32,37,69,53,42,46), +(11,3,33,38,71,54,43,47), +(11,3,34,38,72,55,44,48), +(11,3,35,39,74,57,44,48), +(11,3,36,39,76,58,45,49), +(11,3,37,40,78,59,46,50), +(11,3,38,41,80,60,47,51), +(11,3,39,41,82,62,48,52), +(11,3,40,42,84,63,49,53), +(11,3,41,43,86,64,50,54), +(11,3,42,43,88,66,50,55), +(11,3,43,44,90,67,51,56), +(11,3,44,45,91,68,52,57), +(11,3,45,45,93,70,53,58), +(11,3,46,46,95,71,54,59), +(11,3,47,47,98,72,55,60), +(11,3,48,48,100,74,56,61), +(11,3,49,48,102,75,57,62), +(11,3,50,49,104,77,58,63), +(11,3,51,50,106,78,59,64), +(11,3,52,51,108,79,60,65), +(11,3,53,51,110,81,61,66), +(11,3,54,52,112,82,61,67), +(11,3,55,53,114,84,62,68), +(11,3,56,54,116,85,63,69), +(11,3,57,54,118,87,64,70), +(11,3,58,55,121,88,65,71), +(11,3,59,56,123,90,66,72), +(11,3,60,57,125,91,67,74), +(11,3,61,58,127,93,68,75), +(11,3,62,58,130,94,69,76), +(11,3,63,59,132,96,71,77), +(11,3,64,60,134,97,72,78), +(11,3,65,61,136,99,73,79), +(11,3,66,62,139,101,74,80), +(11,3,67,62,141,102,75,81), +(11,3,68,63,143,104,76,83), +(11,3,69,64,146,105,77,84), +(11,3,70,65,148,107,78,85), +(11,3,71,66,151,109,79,86), +(11,3,72,67,154,111,80,87), +(11,3,73,68,157,113,81,89), +(11,3,74,69,160,115,83,90), +(11,3,75,70,163,117,84,92), +(11,3,76,71,166,119,85,93), +(11,3,77,72,169,121,87,95), +(11,3,78,73,172,123,88,96), +(11,3,79,74,175,125,89,98), +(11,3,80,75,178,127,91,99), + +(11,5,1,21,17,19,23,25), +(11,5,2,21,17,19,24,26), +(11,5,3,21,17,20,26,28), +(11,5,4,21,18,20,27,29), +(11,5,5,22,18,20,28,30), +(11,5,6,22,18,21,30,32), +(11,5,7,22,18,21,31,33), +(11,5,8,22,19,22,32,35), +(11,5,9,22,19,22,34,36), +(11,5,10,22,19,22,35,38), +(11,5,11,23,19,23,37,39), +(11,5,12,23,20,23,38,41), +(11,5,13,23,20,24,39,42), +(11,5,14,23,20,24,41,44), +(11,5,15,23,20,25,42,45), +(11,5,16,24,21,25,44,47), +(11,5,17,24,21,25,45,48), +(11,5,18,24,21,26,47,50), +(11,5,19,24,22,26,48,51), +(11,5,20,24,22,27,50,53), +(11,5,21,25,22,27,51,55), +(11,5,22,25,22,28,53,56), +(11,5,23,25,23,28,55,58), +(11,5,24,25,23,29,56,60), +(11,5,25,25,23,29,58,61), +(11,5,26,26,24,30,60,63), +(11,5,27,26,24,30,61,65), +(11,5,28,26,24,31,63,66), +(11,5,29,26,25,31,65,68), +(11,5,30,27,25,32,66,70), +(11,5,31,27,25,32,68,72), +(11,5,32,27,26,33,70,73), +(11,5,33,27,26,33,71,75), +(11,5,34,28,26,34,73,77), +(11,5,35,28,27,34,75,79), +(11,5,36,28,27,35,77,81), +(11,5,37,29,28,35,79,83), +(11,5,38,29,28,36,80,85), +(11,5,39,29,28,37,82,86), +(11,5,40,29,29,37,84,88), +(11,5,41,30,29,38,86,90), +(11,5,42,30,29,38,88,92), +(11,5,43,30,30,39,90,94), +(11,5,44,31,30,39,91,96), +(11,5,45,31,31,40,93,98), +(11,5,46,31,31,41,95,100), +(11,5,47,32,31,41,97,102), +(11,5,48,32,32,42,99,104), +(11,5,49,32,32,43,101,106), +(11,5,50,33,33,43,103,108), +(11,5,51,33,33,44,105,110), +(11,5,52,33,34,44,107,113), +(11,5,53,34,34,45,109,115), +(11,5,54,34,34,46,111,117), +(11,5,55,34,35,46,113,119), +(11,5,56,35,35,47,115,121), +(11,5,57,35,36,48,118,123), +(11,5,58,35,36,48,120,126), +(11,5,59,36,37,49,122,128), +(11,5,60,36,37,50,124,130), +(11,5,61,36,38,51,126,132), +(11,5,62,37,38,51,128,134), +(11,5,63,37,39,52,130,137), +(11,5,64,38,39,53,133,139), +(11,5,65,38,40,53,135,141), +(11,5,66,38,40,54,137,144), +(11,5,67,39,40,55,139,146), +(11,5,68,39,41,56,141,148), +(11,5,69,40,41,56,144,151), +(11,5,70,40,42,57,146,153), +(11,5,71,40,43,58,149,156), +(11,5,72,41,43,58,155,159), +(11,5,73,41,44,59,157,160), +(11,5,74,42,44,61,160,163), +(11,5,75,42,45,62,164,166), +(11,5,76,42,46,62,167,169), +(11,5,77,43,46,63,168,172), +(11,5,78,43,47,64,169,177), +(11,5,79,44,47,65,172,180), +(11,5,80,44,48,66,175,183), + +(11,6,1,24,17,21,21,22), +(11,6,2,25,18,22,21,22), +(11,6,3,27,19,23,21,23), +(11,6,4,28,19,25,21,23), +(11,6,5,29,20,26,21,23), +(11,6,6,31,21,27,21,23), +(11,6,7,32,22,28,21,24), +(11,6,8,33,23,29,22,24), +(11,6,9,35,24,31,22,24), +(11,6,10,36,24,32,22,25), +(11,6,11,37,25,33,22,25), +(11,6,12,39,26,34,22,25), +(11,6,13,40,27,36,22,26), +(11,6,14,42,28,37,22,26), +(11,6,15,43,29,38,22,26), +(11,6,16,45,30,40,22,27), +(11,6,17,46,31,41,23,27), +(11,6,18,48,32,43,23,27), +(11,6,19,49,33,44,23,28), +(11,6,20,51,34,45,23,28), +(11,6,21,52,34,47,23,28), +(11,6,22,54,35,48,23,29), +(11,6,23,55,36,50,23,29), +(11,6,24,57,37,51,24,30), +(11,6,25,59,38,52,24,30), +(11,6,26,60,39,54,24,30), +(11,6,27,62,40,55,24,31), +(11,6,28,63,41,57,24,31), +(11,6,29,65,43,58,24,32), +(11,6,30,67,44,60,24,32), +(11,6,31,69,45,62,25,32), +(11,6,32,70,46,63,25,33), +(11,6,33,72,47,65,25,33), +(11,6,34,74,48,66,25,34), +(11,6,35,75,49,68,25,34), +(11,6,36,77,50,69,26,35), +(11,6,37,79,51,71,26,35), +(11,6,38,81,52,73,26,35), +(11,6,39,83,53,74,26,36), +(11,6,40,84,55,76,26,36), +(11,6,41,86,56,78,27,37), +(11,6,42,88,57,79,27,37), +(11,6,43,90,58,81,27,38), +(11,6,44,92,59,83,27,38), +(11,6,45,94,60,85,27,39), +(11,6,46,96,62,86,28,39), +(11,6,47,98,63,88,28,40), +(11,6,48,100,64,90,28,40), +(11,6,49,102,65,92,28,41), +(11,6,50,103,65,93,29,41), +(11,6,51,105,66,94,29,42), +(11,6,52,106,67,95,29,42), +(11,6,53,107,68,96,29,43), +(11,6,54,108,69,97,30,44), +(11,6,55,109,70,98,30,44), +(11,6,56,112,72,101,30,45), +(11,6,57,114,73,103,30,45), +(11,6,58,117,74,105,31,46), +(11,6,59,119,76,107,31,46), +(11,6,60,121,77,109,31,47), +(11,6,61,123,78,111,31,48), +(11,6,62,126,80,113,31,48), +(11,6,63,128,81,116,32,49), +(11,6,64,131,83,118,32,49), +(11,6,65,136,84,120,32,50), +(11,6,66,140,86,123,32,51), +(11,6,67,141,87,125,33,51), +(11,6,68,141,89,127,33,52), +(11,6,69,144,90,130,33,53), +(11,6,70,147,92,132,33,53), +(11,6,71,150,94,135,34,54), +(11,6,72,152,95,137,34,55), +(11,6,73,155,97,140,34,56), +(11,6,74,162,99,142,34,56), +(11,6,75,165,100,145,35,57), +(11,6,76,167,102,146,35,58), +(11,6,77,169,104,150,35,59), +(11,6,78,170,105,152,35,59), +(11,6,79,173,107,156,36,60), +(11,6,80,176,109,159,36,61), + +(11,7,1,22,17,20,22,24), +(11,7,2,23,17,21,23,25), +(11,7,3,24,18,22,24,26), +(11,7,4,25,18,23,25,27), +(11,7,5,25,19,24,26,28), +(11,7,6,26,19,25,27,29), +(11,7,7,27,20,26,28,30), +(11,7,8,28,20,27,28,31), +(11,7,9,29,21,28,29,32), +(11,7,10,30,21,29,30,33), +(11,7,11,31,22,30,31,35), +(11,7,12,32,22,31,32,36), +(11,7,13,33,23,32,33,37), +(11,7,14,34,23,33,34,38), +(11,7,15,34,24,35,35,39), +(11,7,16,35,24,36,36,40), +(11,7,17,36,25,37,38,42), +(11,7,18,37,25,38,39,43), +(11,7,19,38,26,39,40,44), +(11,7,20,39,26,40,41,45), +(11,7,21,40,27,41,42,46), +(11,7,22,41,27,43,43,48), +(11,7,23,43,28,44,44,49), +(11,7,24,44,28,45,45,50), +(11,7,25,45,29,46,46,51), +(11,7,26,46,30,47,48,53), +(11,7,27,47,30,49,49,54), +(11,7,28,48,31,50,50,55), +(11,7,29,49,31,51,51,57), +(11,7,30,50,32,53,52,58), +(11,7,31,51,33,54,53,59), +(11,7,32,52,33,55,55,61), +(11,7,33,53,34,56,56,62), +(11,7,34,55,34,58,57,64), +(11,7,35,56,35,59,58,65), +(11,7,36,57,36,60,60,66), +(11,7,37,58,36,62,61,68), +(11,7,38,59,37,63,62,69), +(11,7,39,61,38,65,63,71), +(11,7,40,62,38,66,65,72), +(11,7,41,63,39,67,66,74), +(11,7,42,64,40,69,67,75), +(11,7,43,65,40,70,69,77), +(11,7,44,67,41,72,70,78), +(11,7,45,68,42,73,71,80), +(11,7,46,69,42,75,73,81), +(11,7,47,71,43,76,74,83), +(11,7,48,72,44,78,76,84), +(11,7,49,73,45,79,77,86), +(11,7,50,74,45,81,78,88), +(11,7,51,76,46,82,80,89), +(11,7,52,77,47,84,81,91), +(11,7,53,78,47,85,83,92), +(11,7,54,80,48,87,84,94), +(11,7,55,81,49,88,86,96), +(11,7,56,83,50,90,87,97), +(11,7,57,84,50,91,89,99), +(11,7,58,85,51,93,90,101), +(11,7,59,87,52,95,92,102), +(11,7,60,88,53,96,93,104), +(11,7,61,90,54,98,95,106), +(11,7,62,91,54,99,96,108), +(11,7,63,93,55,101,98,109), +(11,7,64,94,56,103,99,111), +(11,7,65,95,57,104,101,113), +(11,7,66,97,58,106,103,115), +(11,7,67,98,58,108,104,117), +(11,7,68,100,59,110,106,118), +(11,7,69,101,60,111,107,120), +(11,7,70,103,61,113,109,122), +(11,7,71,104,62,115,122,124), +(11,7,72,106,63,117,124,127), +(11,7,73,108,64,119,126,129), +(11,7,74,110,65,122,128,131), +(11,7,75,112,66,124,130,133), +(11,7,76,114,67,126,133,136), +(11,7,77,115,68,128,135,138), +(11,7,78,117,69,130,137,140), +(11,7,79,119,70,133,139,143), +(11,7,80,121,71,135,141,145), + +(11,8,1,21,17,19,24,24), +(11,8,2,21,17,19,25,25), +(11,8,3,21,17,20,27,27), +(11,8,4,21,17,20,28,28), +(11,8,5,21,18,20,29,29), +(11,8,6,21,18,20,31,31), +(11,8,7,21,18,21,32,32), +(11,8,8,22,18,21,34,33), +(11,8,9,22,18,21,35,35), +(11,8,10,22,19,22,37,36), +(11,8,11,22,19,22,38,37), +(11,8,12,22,19,22,40,39), +(11,8,13,22,19,23,41,40), +(11,8,14,22,19,23,43,42), +(11,8,15,22,19,23,44,43), +(11,8,16,22,20,24,46,45), +(11,8,17,23,20,24,47,46), +(11,8,18,23,20,24,49,48), +(11,8,19,23,20,25,50,49), +(11,8,20,23,21,25,52,51), +(11,8,21,23,21,26,54,52), +(11,8,22,23,21,26,55,54), +(11,8,23,23,21,26,57,56), +(11,8,24,24,21,27,59,57), +(11,8,25,24,22,27,60,59), +(11,8,26,24,22,27,62,60), +(11,8,27,24,22,28,64,62), +(11,8,28,24,22,28,65,64), +(11,8,29,24,23,29,67,65), +(11,8,30,24,23,29,69,67), +(11,8,31,25,23,30,71,69), +(11,8,32,25,23,30,73,71), +(11,8,33,25,24,30,74,72), +(11,8,34,25,24,31,76,74), +(11,8,35,25,24,31,78,76), +(11,8,36,26,24,32,80,78), +(11,8,37,26,25,32,82,79), +(11,8,38,26,25,33,84,81), +(11,8,39,26,25,33,86,83), +(11,8,40,26,26,34,87,85), +(11,8,41,27,26,34,89,87), +(11,8,42,27,26,35,91,89), +(11,8,43,27,27,35,93,91), +(11,8,44,27,27,36,95,92), +(11,8,45,27,27,36,97,94), +(11,8,46,28,27,37,99,96), +(11,8,47,28,28,37,101,98), +(11,8,48,28,28,38,103,100), +(11,8,49,28,28,38,105,102), +(11,8,50,29,29,39,107,104), +(11,8,51,29,29,39,110,106), +(11,8,52,29,29,40,112,108), +(11,8,53,29,30,40,114,110), +(11,8,54,30,30,41,116,112), +(11,8,55,30,30,41,118,114), +(11,8,56,30,31,42,120,116), +(11,8,57,30,31,42,122,118), +(11,8,58,31,31,43,125,121), +(11,8,59,31,32,43,127,123), +(11,8,60,31,32,44,129,125), +(11,8,61,31,33,45,131,127), +(11,8,62,32,33,45,133,129), +(11,8,63,32,33,46,136,131), +(11,8,64,32,34,46,138,134), +(11,8,65,33,34,47,140,136), +(11,8,66,33,34,48,143,138), +(11,8,67,33,35,48,145,140), +(11,8,68,33,35,49,147,142), +(11,8,69,34,36,49,150,145), +(11,8,70,34,36,50,152,147), +(11,8,71,34,36,51,155,150), +(11,8,72,34,37,52,161,153), +(11,8,73,34,37,53,161,156), +(11,8,74,35,38,53,164,158), +(11,8,75,35,38,54,167,161), +(11,8,76,35,38,55,170,164), +(11,8,77,36,39,56,173,167), +(11,8,78,36,39,56,176,170), +(11,8,79,36,40,57,179,173), +(11,8,80,37,40,58,182,176); diff --git a/sql/updates/2008_12_22_13_mangos_item_template.sql b/sql/updates/2008_12_22_13_mangos_item_template.sql new file mode 100644 index 000000000..6b2d64f51 --- /dev/null +++ b/sql/updates/2008_12_22_13_mangos_item_template.sql @@ -0,0 +1,4 @@ +ALTER TABLE db_version CHANGE COLUMN required_2008_12_22_12_mangos_player_levelstats required_2008_12_22_13_mangos_item_template bit; + +ALTER TABLE `item_template` + CHANGE COLUMN `TotemCategory` `TotemCategory` mediumint(9) NOT NULL default '0'; diff --git a/sql/updates/2008_12_22_14_mangos_playercreateinfo.sql b/sql/updates/2008_12_22_14_mangos_playercreateinfo.sql new file mode 100644 index 000000000..f36d79652 --- /dev/null +++ b/sql/updates/2008_12_22_14_mangos_playercreateinfo.sql @@ -0,0 +1,14 @@ +ALTER TABLE db_version CHANGE COLUMN required_2008_12_22_13_mangos_item_template required_2008_12_22_14_mangos_playercreateinfo bit; + +DELETE FROM `playercreateinfo` WHERE class = 6; +INSERT INTO `playercreateinfo` VALUES +(1 ,6,609,4298,2355.84,-5664.77,426.028), +(2 ,6,609,4298,2358.44,-5666.9, 426.023), +(3 ,6,609,4298,2358.44,-5666.9, 426.023), +(4 ,6,609,4298,2356.21,-5662.21,426.026), +(5 ,6,609,4298,2356.21,-5662.21,426.026), +(6 ,6,609,4298,2358.17,-5663.21,426.027), +(7 ,6,609,4298,2355.05,-5661.7, 426.026), +(8 ,6,609,4298,2355.05,-5661.7, 426.026), +(10,6,609,4298,2355.84,-5664.77,426.028), +(11,6,609,4298,2358.17,-5663.21,426.027); diff --git a/sql/updates/2008_12_22_15_mangos_playercreateinfo_action.sql b/sql/updates/2008_12_22_15_mangos_playercreateinfo_action.sql new file mode 100644 index 000000000..54bcde291 --- /dev/null +++ b/sql/updates/2008_12_22_15_mangos_playercreateinfo_action.sql @@ -0,0 +1,80 @@ +ALTER TABLE db_version CHANGE COLUMN required_2008_12_22_14_mangos_playercreateinfo required_2008_12_22_15_mangos_playercreateinfo_action bit; + +DELETE FROM playercreateinfo_action WHERE class = 6; +INSERT INTO playercreateinfo_action VALUES +(1,6,0,6603,0,0), +(1,6,1,49576,0,0), +(1,6,2,45477,0,0), +(1,6,3,45462,0,0), +(1,6,4,45902,0,0), +(1,6,5,47541,0,0), +(1,6,11,59752,0,0), +(2,6,0,6603,0,0), +(2,6,1,49576,0,0), +(2,6,2,45477,0,0), +(2,6,3,45462,0,0), +(2,6,4,45902,0,0), +(2,6,5,47541,0,0), +(2,6,10,20572,0,0), +(3,6,0,6603,0,0), +(3,6,1,49576,0,0), +(3,6,2,45477,0,0), +(3,6,3,45462,0,0), +(3,6,4,45902,0,0), +(3,6,5,47541,0,0), +(3,6,10,2481,0,0), +(4,6,0,6603,0,0), +(4,6,1,49576,0,0), +(4,6,2,45477,0,0), +(4,6,3,45462,0,0), +(4,6,4,45902,0,0), +(4,6,5,47541,0,0), +(4,6,10,58984,0,0), +(4,6,83,58984,0,0), +(5,6,0,6603,0,0), +(5,6,1,49576,0,0), +(5,6,2,45477,0,0), +(5,6,3,45462,0,0), +(5,6,4,45902,0,0), +(5,6,5,47541,0,0), +(5,6,10,20577,0,0), +(6,6,0,6603,0,0), +(6,6,1,49576,0,0), +(6,6,2,45477,0,0), +(6,6,3,45462,0,0), +(6,6,4,45902,0,0), +(6,6,5,47541,0,0), +(6,6,10,20549,0,0), +(6,6,75,20549,0,0), +(7,6,0,6603,0,0), +(7,6,1,49576,0,0), +(7,6,2,45477,0,0), +(7,6,3,45462,0,0), +(7,6,4,45902,0,0), +(7,6,5,47541,0,0), +(7,6,10,20589,0,0), +(7,6,72,6603,0,0), +(7,6,83,117,128,0), +(7,6,84,6603,0,0), +(7,6,96,6603,0,0), +(7,6,108,6603,0,0), +(8,6,0,6603,0,0), +(8,6,1,49576,0,0), +(8,6,2,45477,0,0), +(8,6,3,45462,0,0), +(8,6,4,45902,0,0), +(8,6,5,47541,0,0), +(8,6,10,50621,0,0), +(10,6,0,6603,0,0), +(10,6,1,49576,0,0), +(10,6,2,45477,0,0), +(10,6,3,45462,0,0), +(10,6,4,45902,0,0), +(10,6,5,47541,0,0), +(10,6,6,50613,0,0), +(11,6,0,6603,0,0), +(11,6,1,49576,0,0), +(11,6,2,45477,0,0), +(11,6,3,45462,0,0), +(11,6,4,45902,0,0), +(11,6,5,47541,0,0); diff --git a/sql/updates/2008_12_22_16_mangos_playercreateinfo_spell.sql b/sql/updates/2008_12_22_16_mangos_playercreateinfo_spell.sql new file mode 100644 index 000000000..664ea0291 --- /dev/null +++ b/sql/updates/2008_12_22_16_mangos_playercreateinfo_spell.sql @@ -0,0 +1,686 @@ +ALTER TABLE db_version CHANGE COLUMN required_2008_12_22_15_mangos_playercreateinfo_action required_2008_12_22_16_mangos_playercreateinfo_spell bit; + +DELETE FROM `playercreateinfo_spell` WHERE `class` = 6; +INSERT INTO `playercreateinfo_spell` VALUES +(1,6,81,'Dodge',1), +(1,6,196,'One-Handed Axes',1), +(1,6,197,'Two-Handed Axes',1), +(1,6,200,'Polearms',1), +(1,6,201,'One-Handed Swords',1), +(1,6,202,'Two-Handed Swords',1), +(1,6,203,'Unarmed',1), +(1,6,204,'Defense',1), +(1,6,522,'SPELLDEFENSE (DND)',1), +(1,6,668,'Language Common',1), +(1,6,674,'Dual Wield',1), +(1,6,750,'Plate Mail',1), +(1,6,1843,'Disarm',1), +(1,6,2382,'Generic',1), +(1,6,2479,'Honorless Target',1), +(1,6,3050,'Detect',1), +(1,6,3127,'Parry',1), +(1,6,3275,'Linen Bandage',1), +(1,6,3276,'Heavy Linen Bandage',1), +(1,6,3277,'Wool Bandage',1), +(1,6,3278,'Heavy Wool Bandage',1), +(1,6,3365,'Opening',1), +(1,6,6233,'Closing',1), +(1,6,6246,'Closing',1), +(1,6,6247,'Opening',1), +(1,6,6477,'Opening',1), +(1,6,6478,'Opening',1), +(1,6,6603,'Attack',1), +(1,6,7266,'Duel',1), +(1,6,7267,'Grovel',1), +(1,6,7355,'Stuck',1), +(1,6,7928,'Silk Bandage',1), +(1,6,7929,'Heavy Silk Bandage',1), +(1,6,7934,'Anti-Venom',1), +(1,6,8386,'Attacking',1), +(1,6,8737,'Mail',1), +(1,6,9077,'Leather',1), +(1,6,9078,'Cloth',1), +(1,6,9125,'Generic',1), +(1,6,10840,'Mageweave Bandage',1), +(1,6,10841,'Heavy Mageweave Bandage',1), +(1,6,10846,'First Aid',1), +(1,6,18629,'Runecloth Bandage',1), +(1,6,18630,'Heavy Runecloth Bandage',1), +(1,6,20597,'Sword Specialization',1), +(1,6,20598,'The Human Spirit',1), +(1,6,20599,'Diplomacy',1), +(1,6,20864,'Mace Specialization',1), +(1,6,21651,'Opening',1), +(1,6,21652,'Closing',1), +(1,6,22027,'Remove Insignia',1), +(1,6,22810,'Opening - No Text',1), +(1,6,33391,'Journeyman Riding',1), +(1,6,45462,'Plague Strike',1), +(1,6,45477,'Icy Touch',1), +(1,6,45902,'Blood Strike',1), +(1,6,45903,'Offensive State (DND)',1), +(1,6,45927,'Summon Friend',1), +(1,6,47541,'Death Coil',1), +(1,6,48266,'Blood Presence',1), +(1,6,49410,'Forceful Deflection',1), +(1,6,49576,'Death Grip',1), +(1,6,52665,'Sigil',1), +(1,6,58985,'Perception',1), +(1,6,59752,'Every Man for Himself',1), +(1,6,59879,'Blood Plague',1), +(1,6,59921,'Frost Fever',1), +(1,6,61437,'Opening',1), +(1,6,61455,'Runic Focus',1), +(2,6,81,'Dodge',1), +(2,6,196,'One-Handed Axes',1), +(2,6,197,'Two-Handed Axes',1), +(2,6,200,'Polearms',1), +(2,6,201,'One-Handed Swords',1), +(2,6,202,'Two-Handed Swords',1), +(2,6,203,'Unarmed',1), +(2,6,204,'Defense',1), +(2,6,522,'SPELLDEFENSE (DND)',1), +(2,6,669,'Language Orcish',1), +(2,6,674,'Dual Wield',1), +(2,6,750,'Plate Mail',1), +(2,6,1843,'Disarm',1), +(2,6,2382,'Generic',1), +(2,6,2479,'Honorless Target',1), +(2,6,3050,'Detect',1), +(2,6,3127,'Parry',1), +(2,6,3275,'Linen Bandage',1), +(2,6,3276,'Heavy Linen Bandage',1), +(2,6,3277,'Wool Bandage',1), +(2,6,3278,'Heavy Wool Bandage',1), +(2,6,3365,'Opening',1), +(2,6,6233,'Closing',1), +(2,6,6246,'Closing',1), +(2,6,6247,'Opening',1), +(2,6,6477,'Opening',1), +(2,6,6478,'Opening',1), +(2,6,6603,'Attack',1), +(2,6,7266,'Duel',1), +(2,6,7267,'Grovel',1), +(2,6,7355,'Stuck',1), +(2,6,7928,'Silk Bandage',1), +(2,6,7929,'Heavy Silk Bandage',1), +(2,6,7934,'Anti-Venom',1), +(2,6,8386,'Attacking',1), +(2,6,8737,'Mail',1), +(2,6,9077,'Leather',1), +(2,6,9078,'Cloth',1), +(2,6,9125,'Generic',1), +(2,6,10840,'Mageweave Bandage',1), +(2,6,10841,'Heavy Mageweave Bandage',1), +(2,6,10846,'First Aid',1), +(2,6,18629,'Runecloth Bandage',1), +(2,6,18630,'Heavy Runecloth Bandage',1), +(2,6,20572,'Blood Fury',1), +(2,6,20573,'Hardiness',1), +(2,6,20574,'Axe Specialization',1), +(2,6,21651,'Opening',1), +(2,6,21652,'Closing',1), +(2,6,22027,'Remove Insignia',1), +(2,6,22810,'Opening - No Text',1), +(2,6,33391,'Journeyman Riding',1), +(2,6,45462,'Plague Strike',1), +(2,6,45477,'Icy Touch',1), +(2,6,45902,'Blood Strike',1), +(2,6,45903,'Offensive State (DND)',1), +(2,6,45927,'Summon Friend',1), +(2,6,47541,'Death Coil',1), +(2,6,48266,'Blood Presence',1), +(2,6,49410,'Forceful Deflection',1), +(2,6,49576,'Death Grip',1), +(2,6,52665,'Sigil',1), +(2,6,54562,'Command',1), +(2,6,59879,'Blood Plague',1), +(2,6,59921,'Frost Fever',1), +(2,6,61437,'Opening',1), +(2,6,61455,'Runic Focus',1), +(3,6,81,'Dodge',1), +(3,6,196,'One-Handed Axes',1), +(3,6,197,'Two-Handed Axes',1), +(3,6,200,'Polearms',1), +(3,6,201,'One-Handed Swords',1), +(3,6,202,'Two-Handed Swords',1), +(3,6,203,'Unarmed',1), +(3,6,204,'Defense',1), +(3,6,522,'SPELLDEFENSE (DND)',1), +(3,6,668,'Language Common',1), +(3,6,672,'Language Dwarven',1), +(3,6,674,'Dual Wield',1), +(3,6,750,'Plate Mail',1), +(3,6,1843,'Disarm',1), +(3,6,2382,'Generic',1), +(3,6,2479,'Honorless Target',1), +(3,6,2481,'Find Treasure',1), +(3,6,3050,'Detect',1), +(3,6,3127,'Parry',1), +(3,6,3275,'Linen Bandage',1), +(3,6,3276,'Heavy Linen Bandage',1), +(3,6,3277,'Wool Bandage',1), +(3,6,3278,'Heavy Wool Bandage',1), +(3,6,3365,'Opening',1), +(3,6,6233,'Closing',1), +(3,6,6246,'Closing',1), +(3,6,6247,'Opening',1), +(3,6,6477,'Opening',1), +(3,6,6478,'Opening',1), +(3,6,6603,'Attack',1), +(3,6,7266,'Duel',1), +(3,6,7267,'Grovel',1), +(3,6,7355,'Stuck',1), +(3,6,7928,'Silk Bandage',1), +(3,6,7929,'Heavy Silk Bandage',1), +(3,6,7934,'Anti-Venom',1), +(3,6,8386,'Attacking',1), +(3,6,8737,'Mail',1), +(3,6,9077,'Leather',1), +(3,6,9078,'Cloth',1), +(3,6,9125,'Generic',1), +(3,6,10840,'Mageweave Bandage',1), +(3,6,10841,'Heavy Mageweave Bandage',1), +(3,6,10846,'First Aid',1), +(3,6,18629,'Runecloth Bandage',1), +(3,6,18630,'Heavy Runecloth Bandage',1), +(3,6,20594,'Stoneform',1), +(3,6,20595,'Gun Specialization',1), +(3,6,20596,'Frost Resistance',1), +(3,6,21651,'Opening',1), +(3,6,21652,'Closing',1), +(3,6,22027,'Remove Insignia',1), +(3,6,22810,'Opening - No Text',1), +(3,6,33391,'Journeyman Riding',1), +(3,6,45462,'Plague Strike',1), +(3,6,45477,'Icy Touch',1), +(3,6,45902,'Blood Strike',1), +(3,6,45903,'Offensive State (DND)',1), +(3,6,45927,'Summon Friend',1), +(3,6,47541,'Death Coil',1), +(3,6,48266,'Blood Presence',1), +(3,6,49410,'Forceful Deflection',1), +(3,6,49576,'Death Grip',1), +(3,6,52665,'Sigil',1), +(3,6,59224,'Mace Specialization',1), +(3,6,59879,'Blood Plague',1), +(3,6,59921,'Frost Fever',1), +(3,6,61437,'Opening',1), +(3,6,61455,'Runic Focus',1), +(4,6,81,'Dodge',1), +(4,6,196,'One-Handed Axes',1), +(4,6,197,'Two-Handed Axes',1), +(4,6,200,'Polearms',1), +(4,6,201,'One-Handed Swords',1), +(4,6,202,'Two-Handed Swords',1), +(4,6,203,'Unarmed',1), +(4,6,204,'Defense',1), +(4,6,522,'SPELLDEFENSE (DND)',1), +(4,6,668,'Language Common',1), +(4,6,671,'Language Darnassian',1), +(4,6,674,'Dual Wield',1), +(4,6,750,'Plate Mail',1), +(4,6,1843,'Disarm',1), +(4,6,2382,'Generic',1), +(4,6,2479,'Honorless Target',1), +(4,6,3050,'Detect',1), +(4,6,3127,'Parry',1), +(4,6,3275,'Linen Bandage',1), +(4,6,3276,'Heavy Linen Bandage',1), +(4,6,3277,'Wool Bandage',1), +(4,6,3278,'Heavy Wool Bandage',1), +(4,6,3365,'Opening',1), +(4,6,6233,'Closing',1), +(4,6,6246,'Closing',1), +(4,6,6247,'Opening',1), +(4,6,6477,'Opening',1), +(4,6,6478,'Opening',1), +(4,6,6603,'Attack',1), +(4,6,7266,'Duel',1), +(4,6,7267,'Grovel',1), +(4,6,7355,'Stuck',1), +(4,6,7928,'Silk Bandage',1), +(4,6,7929,'Heavy Silk Bandage',1), +(4,6,7934,'Anti-Venom',1), +(4,6,8386,'Attacking',1), +(4,6,8737,'Mail',1), +(4,6,9077,'Leather',1), +(4,6,9078,'Cloth',1), +(4,6,9125,'Generic',1), +(4,6,10840,'Mageweave Bandage',1), +(4,6,10841,'Heavy Mageweave Bandage',1), +(4,6,10846,'First Aid',1), +(4,6,18629,'Runecloth Bandage',1), +(4,6,18630,'Heavy Runecloth Bandage',1), +(4,6,20582,'Quickness',1), +(4,6,20583,'Nature Resistance',1), +(4,6,20585,'Wisp Spirit',1), +(4,6,21651,'Opening',1), +(4,6,21652,'Closing',1), +(4,6,22027,'Remove Insignia',1), +(4,6,22810,'Opening - No Text',1), +(4,6,33391,'Journeyman Riding',1), +(4,6,45462,'Plague Strike',1), +(4,6,45477,'Icy Touch',1), +(4,6,45902,'Blood Strike',1), +(4,6,45903,'Offensive State (DND)',1), +(4,6,45927,'Summon Friend',1), +(4,6,47541,'Death Coil',1), +(4,6,48266,'Blood Presence',1), +(4,6,49410,'Forceful Deflection',1), +(4,6,49576,'Death Grip',1), +(4,6,52665,'Sigil',1), +(4,6,58984,'Shadowmeld',1), +(4,6,59879,'Blood Plague',1), +(4,6,59921,'Frost Fever',1), +(4,6,61437,'Opening',1), +(4,6,61455,'Runic Focus',1), +(5,6,81,'Dodge',1), +(5,6,196,'One-Handed Axes',1), +(5,6,197,'Two-Handed Axes',1), +(5,6,200,'Polearms',1), +(5,6,201,'One-Handed Swords',1), +(5,6,202,'Two-Handed Swords',1), +(5,6,203,'Unarmed',1), +(5,6,204,'Defense',1), +(5,6,522,'SPELLDEFENSE (DND)',1), +(5,6,669,'Language Orcish',1), +(5,6,674,'Dual Wield',1), +(5,6,750,'Plate Mail',1), +(5,6,1843,'Disarm',1), +(5,6,2382,'Generic',1), +(5,6,2479,'Honorless Target',1), +(5,6,3050,'Detect',1), +(5,6,3127,'Parry',1), +(5,6,3275,'Linen Bandage',1), +(5,6,3276,'Heavy Linen Bandage',1), +(5,6,3277,'Wool Bandage',1), +(5,6,3278,'Heavy Wool Bandage',1), +(5,6,3365,'Opening',1), +(5,6,5227,'Underwater Breathing',1), +(5,6,6233,'Closing',1), +(5,6,6246,'Closing',1), +(5,6,6247,'Opening',1), +(5,6,6477,'Opening',1), +(5,6,6478,'Opening',1), +(5,6,6603,'Attack',1), +(5,6,7266,'Duel',1), +(5,6,7267,'Grovel',1), +(5,6,7355,'Stuck',1), +(5,6,7744,'Will of the Forsaken',1), +(5,6,7928,'Silk Bandage',1), +(5,6,7929,'Heavy Silk Bandage',1), +(5,6,7934,'Anti-Venom',1), +(5,6,8386,'Attacking',1), +(5,6,8737,'Mail',1), +(5,6,9077,'Leather',1), +(5,6,9078,'Cloth',1), +(5,6,9125,'Generic',1), +(5,6,10840,'Mageweave Bandage',1), +(5,6,10841,'Heavy Mageweave Bandage',1), +(5,6,10846,'First Aid',1), +(5,6,17737,'Language Gutterspeak',1), +(5,6,18629,'Runecloth Bandage',1), +(5,6,18630,'Heavy Runecloth Bandage',1), +(5,6,20577,'Cannibalize',1), +(5,6,20579,'Shadow Resistance',1), +(5,6,21651,'Opening',1), +(5,6,21652,'Closing',1), +(5,6,22027,'Remove Insignia',1), +(5,6,22810,'Opening - No Text',1), +(5,6,33391,'Journeyman Riding',1), +(5,6,45462,'Plague Strike',1), +(5,6,45477,'Icy Touch',1), +(5,6,45902,'Blood Strike',1), +(5,6,45903,'Offensive State (DND)',1), +(5,6,45927,'Summon Friend',1), +(5,6,47541,'Death Coil',1), +(5,6,48266,'Blood Presence',1), +(5,6,49410,'Forceful Deflection',1), +(5,6,49576,'Death Grip',1), +(5,6,52665,'Sigil',1), +(5,6,59879,'Blood Plague',1), +(5,6,59921,'Frost Fever',1), +(5,6,61437,'Opening',1), +(5,6,61455,'Runic Focus',1), +(6,6,81,'Dodge',1), +(6,6,196,'One-Handed Axes',1), +(6,6,197,'Two-Handed Axes',1), +(6,6,200,'Polearms',1), +(6,6,201,'One-Handed Swords',1), +(6,6,202,'Two-Handed Swords',1), +(6,6,203,'Unarmed',1), +(6,6,204,'Defense',1), +(6,6,522,'SPELLDEFENSE (DND)',1), +(6,6,669,'Language Orcish',1), +(6,6,670,'Language Taurahe',1), +(6,6,674,'Dual Wield',1), +(6,6,750,'Plate Mail',1), +(6,6,1843,'Disarm',1), +(6,6,2382,'Generic',1), +(6,6,2479,'Honorless Target',1), +(6,6,3050,'Detect',1), +(6,6,3127,'Parry',1), +(6,6,3275,'Linen Bandage',1), +(6,6,3276,'Heavy Linen Bandage',1), +(6,6,3277,'Wool Bandage',1), +(6,6,3278,'Heavy Wool Bandage',1), +(6,6,3365,'Opening',1), +(6,6,6233,'Closing',1), +(6,6,6246,'Closing',1), +(6,6,6247,'Opening',1), +(6,6,6477,'Opening',1), +(6,6,6478,'Opening',1), +(6,6,6603,'Attack',1), +(6,6,7266,'Duel',1), +(6,6,7267,'Grovel',1), +(6,6,7355,'Stuck',1), +(6,6,7928,'Silk Bandage',1), +(6,6,7929,'Heavy Silk Bandage',1), +(6,6,7934,'Anti-Venom',1), +(6,6,8386,'Attacking',1), +(6,6,8737,'Mail',1), +(6,6,9077,'Leather',1), +(6,6,9078,'Cloth',1), +(6,6,9125,'Generic',1), +(6,6,10840,'Mageweave Bandage',1), +(6,6,10841,'Heavy Mageweave Bandage',1), +(6,6,10846,'First Aid',1), +(6,6,18629,'Runecloth Bandage',1), +(6,6,18630,'Heavy Runecloth Bandage',1), +(6,6,20549,'War Stomp',1), +(6,6,20550,'Endurance',1), +(6,6,20551,'Nature Resistance',1), +(6,6,20552,'Cultivation',1), +(6,6,21651,'Opening',1), +(6,6,21652,'Closing',1), +(6,6,22027,'Remove Insignia',1), +(6,6,22810,'Opening - No Text',1), +(6,6,33391,'Journeyman Riding',1), +(6,6,45462,'Plague Strike',1), +(6,6,45477,'Icy Touch',1), +(6,6,45902,'Blood Strike',1), +(6,6,45903,'Offensive State (DND)',1), +(6,6,45927,'Summon Friend',1), +(6,6,47541,'Death Coil',1), +(6,6,48266,'Blood Presence',1), +(6,6,49410,'Forceful Deflection',1), +(6,6,49576,'Death Grip',1), +(6,6,52665,'Sigil',1), +(6,6,59879,'Blood Plague',1), +(6,6,59921,'Frost Fever',1), +(6,6,61437,'Opening',1), +(6,6,61455,'Runic Focus',1), +(7,6,81,'Dodge',1), +(7,6,196,'One-Handed Axes',1), +(7,6,197,'Two-Handed Axes',1), +(7,6,200,'Polearms',1), +(7,6,201,'One-Handed Swords',1), +(7,6,202,'Two-Handed Swords',1), +(7,6,203,'Unarmed',1), +(7,6,204,'Defense',1), +(7,6,522,'SPELLDEFENSE (DND)',1), +(7,6,668,'Language Common',1), +(7,6,674,'Dual Wield',1), +(7,6,750,'Plate Mail',1), +(7,6,1843,'Disarm',1), +(7,6,2382,'Generic',1), +(7,6,2479,'Honorless Target',1), +(7,6,3050,'Detect',1), +(7,6,3127,'Parry',1), +(7,6,3275,'Linen Bandage',1), +(7,6,3276,'Heavy Linen Bandage',1), +(7,6,3277,'Wool Bandage',1), +(7,6,3278,'Heavy Wool Bandage',1), +(7,6,3365,'Opening',1), +(7,6,6233,'Closing',1), +(7,6,6246,'Closing',1), +(7,6,6247,'Opening',1), +(7,6,6477,'Opening',1), +(7,6,6478,'Opening',1), +(7,6,6603,'Attack',1), +(7,6,7266,'Duel',1), +(7,6,7267,'Grovel',1), +(7,6,7340,'Language Gnomish',1), +(7,6,7355,'Stuck',1), +(7,6,7928,'Silk Bandage',1), +(7,6,7929,'Heavy Silk Bandage',1), +(7,6,7934,'Anti-Venom',1), +(7,6,8386,'Attacking',1), +(7,6,8737,'Mail',1), +(7,6,9077,'Leather',1), +(7,6,9078,'Cloth',1), +(7,6,9125,'Generic',1), +(7,6,10840,'Mageweave Bandage',1), +(7,6,10841,'Heavy Mageweave Bandage',1), +(7,6,10846,'First Aid',1), +(7,6,18629,'Runecloth Bandage',1), +(7,6,18630,'Heavy Runecloth Bandage',1), +(7,6,20589,'Escape Artist',1), +(7,6,20591,'Expansive Mind',1), +(7,6,20592,'Arcane Resistance',1), +(7,6,20593,'Engineering Specialization',1), +(7,6,21651,'Opening',1), +(7,6,21652,'Closing',1), +(7,6,22027,'Remove Insignia',1), +(7,6,22810,'Opening - No Text',1), +(7,6,33391,'Journeyman Riding',1), +(7,6,45462,'Plague Strike',1), +(7,6,45477,'Icy Touch',1), +(7,6,45902,'Blood Strike',1), +(7,6,45903,'Offensive State (DND)',1), +(7,6,45927,'Summon Friend',1), +(7,6,47541,'Death Coil',1), +(7,6,48266,'Blood Presence',1), +(7,6,49410,'Forceful Deflection',1), +(7,6,49576,'Death Grip',1), +(7,6,52665,'Sigil',1), +(7,6,59879,'Blood Plague',1), +(7,6,59921,'Frost Fever',1), +(7,6,61437,'Opening',1), +(7,6,61455,'Runic Focus',1), +(8,6,81,'Dodge',1), +(8,6,196,'One-Handed Axes',1), +(8,6,197,'Two-Handed Axes',1), +(8,6,200,'Polearms',1), +(8,6,201,'One-Handed Swords',1), +(8,6,202,'Two-Handed Swords',1), +(8,6,203,'Unarmed',1), +(8,6,204,'Defense',1), +(8,6,522,'SPELLDEFENSE (DND)',1), +(8,6,669,'Language Orcish',1), +(8,6,674,'Dual Wield',1), +(8,6,750,'Plate Mail',1), +(8,6,1843,'Disarm',1), +(8,6,2382,'Generic',1), +(8,6,2479,'Honorless Target',1), +(8,6,3050,'Detect',1), +(8,6,3127,'Parry',1), +(8,6,3275,'Linen Bandage',1), +(8,6,3276,'Heavy Linen Bandage',1), +(8,6,3277,'Wool Bandage',1), +(8,6,3278,'Heavy Wool Bandage',1), +(8,6,3365,'Opening',1), +(8,6,6233,'Closing',1), +(8,6,6246,'Closing',1), +(8,6,6247,'Opening',1), +(8,6,6477,'Opening',1), +(8,6,6478,'Opening',1), +(8,6,6603,'Attack',1), +(8,6,7266,'Duel',1), +(8,6,7267,'Grovel',1), +(8,6,7341,'Language Troll',1), +(8,6,7355,'Stuck',1), +(8,6,7928,'Silk Bandage',1), +(8,6,7929,'Heavy Silk Bandage',1), +(8,6,7934,'Anti-Venom',1), +(8,6,8386,'Attacking',1), +(8,6,8737,'Mail',1), +(8,6,9077,'Leather',1), +(8,6,9078,'Cloth',1), +(8,6,9125,'Generic',1), +(8,6,10840,'Mageweave Bandage',1), +(8,6,10841,'Heavy Mageweave Bandage',1), +(8,6,10846,'First Aid',1), +(8,6,18629,'Runecloth Bandage',1), +(8,6,18630,'Heavy Runecloth Bandage',1), +(8,6,20555,'Regeneration',1), +(8,6,20557,'Beast Slaying',1), +(8,6,20558,'Throwing Specialization',1), +(8,6,21651,'Opening',1), +(8,6,21652,'Closing',1), +(8,6,22027,'Remove Insignia',1), +(8,6,22810,'Opening - No Text',1), +(8,6,26290,'Bow Specialization',1), +(8,6,33391,'Journeyman Riding',1), +(8,6,45462,'Plague Strike',1), +(8,6,45477,'Icy Touch',1), +(8,6,45902,'Blood Strike',1), +(8,6,45903,'Offensive State (DND)',1), +(8,6,45927,'Summon Friend',1), +(8,6,47541,'Death Coil',1), +(8,6,48266,'Blood Presence',1), +(8,6,49410,'Forceful Deflection',1), +(8,6,49576,'Death Grip',1), +(8,6,50621,'Berserking',1), +(8,6,52665,'Sigil',1), +(8,6,58943,'Da Voodoo Shuffle',1), +(8,6,59879,'Blood Plague',1), +(8,6,59921,'Frost Fever',1), +(8,6,61437,'Opening',1), +(8,6,61455,'Runic Focus',1), +(10,6,81,'Dodge',1), +(10,6,196,'One-Handed Axes',1), +(10,6,197,'Two-Handed Axes',1), +(10,6,200,'Polearms',1), +(10,6,201,'One-Handed Swords',1), +(10,6,202,'Two-Handed Swords',1), +(10,6,203,'Unarmed',1), +(10,6,204,'Defense',1), +(10,6,522,'SPELLDEFENSE (DND)',1), +(10,6,669,'Language Orcish',1), +(10,6,674,'Dual Wield',1), +(10,6,750,'Plate Mail',1), +(10,6,813,'Language Thalassian',1), +(10,6,822,'Magic Resistance',1), +(10,6,1843,'Disarm',1), +(10,6,2382,'Generic',1), +(10,6,2479,'Honorless Target',1), +(10,6,3050,'Detect',1), +(10,6,3127,'Parry',1), +(10,6,3275,'Linen Bandage',1), +(10,6,3276,'Heavy Linen Bandage',1), +(10,6,3277,'Wool Bandage',1), +(10,6,3278,'Heavy Wool Bandage',1), +(10,6,3365,'Opening',1), +(10,6,6233,'Closing',1), +(10,6,6246,'Closing',1), +(10,6,6247,'Opening',1), +(10,6,6477,'Opening',1), +(10,6,6478,'Opening',1), +(10,6,6603,'Attack',1), +(10,6,7266,'Duel',1), +(10,6,7267,'Grovel',1), +(10,6,7355,'Stuck',1), +(10,6,7928,'Silk Bandage',1), +(10,6,7929,'Heavy Silk Bandage',1), +(10,6,7934,'Anti-Venom',1), +(10,6,8386,'Attacking',1), +(10,6,8737,'Mail',1), +(10,6,9077,'Leather',1), +(10,6,9078,'Cloth',1), +(10,6,9125,'Generic',1), +(10,6,10840,'Mageweave Bandage',1), +(10,6,10841,'Heavy Mageweave Bandage',1), +(10,6,10846,'First Aid',1), +(10,6,18629,'Runecloth Bandage',1), +(10,6,18630,'Heavy Runecloth Bandage',1), +(10,6,21651,'Opening',1), +(10,6,21652,'Closing',1), +(10,6,22027,'Remove Insignia',1), +(10,6,22810,'Opening - No Text',1), +(10,6,28877,'Arcane Affinity',1), +(10,6,33391,'Journeyman Riding',1), +(10,6,45462,'Plague Strike',1), +(10,6,45477,'Icy Touch',1), +(10,6,45902,'Blood Strike',1), +(10,6,45903,'Offensive State (DND)',1), +(10,6,45927,'Summon Friend',1), +(10,6,47541,'Death Coil',1), +(10,6,48266,'Blood Presence',1), +(10,6,49410,'Forceful Deflection',1), +(10,6,49576,'Death Grip',1), +(10,6,50613,'Arcane Torrent',1), +(10,6,52665,'Sigil',1), +(10,6,59879,'Blood Plague',1), +(10,6,59921,'Frost Fever',1), +(10,6,61437,'Opening',1), +(10,6,61455,'Runic Focus',1), +(11,6,81,'Dodge',1), +(11,6,196,'One-Handed Axes',1), +(11,6,197,'Two-Handed Axes',1), +(11,6,200,'Polearms',1), +(11,6,201,'One-Handed Swords',1), +(11,6,202,'Two-Handed Swords',1), +(11,6,203,'Unarmed',1), +(11,6,204,'Defense',1), +(11,6,522,'SPELLDEFENSE (DND)',1), +(11,6,668,'Language Common',1), +(11,6,674,'Dual Wield',1), +(11,6,750,'Plate Mail',1), +(11,6,1843,'Disarm',1), +(11,6,2382,'Generic',1), +(11,6,2479,'Honorless Target',1), +(11,6,3050,'Detect',1), +(11,6,3127,'Parry',1), +(11,6,3275,'Linen Bandage',1), +(11,6,3276,'Heavy Linen Bandage',1), +(11,6,3277,'Wool Bandage',1), +(11,6,3278,'Heavy Wool Bandage',1), +(11,6,3365,'Opening',1), +(11,6,6233,'Closing',1), +(11,6,6246,'Closing',1), +(11,6,6247,'Opening',1), +(11,6,6477,'Opening',1), +(11,6,6478,'Opening',1), +(11,6,6562,'Heroic Presence',1), +(11,6,6603,'Attack',1), +(11,6,7266,'Duel',1), +(11,6,7267,'Grovel',1), +(11,6,7355,'Stuck',1), +(11,6,7928,'Silk Bandage',1), +(11,6,7929,'Heavy Silk Bandage',1), +(11,6,7934,'Anti-Venom',1), +(11,6,8386,'Attacking',1), +(11,6,8737,'Mail',1), +(11,6,9077,'Leather',1), +(11,6,9078,'Cloth',1), +(11,6,9125,'Generic',1), +(11,6,10840,'Mageweave Bandage',1), +(11,6,10841,'Heavy Mageweave Bandage',1), +(11,6,10846,'First Aid',1), +(11,6,18629,'Runecloth Bandage',1), +(11,6,18630,'Heavy Runecloth Bandage',1), +(11,6,21651,'Opening',1), +(11,6,21652,'Closing',1), +(11,6,22027,'Remove Insignia',1), +(11,6,22810,'Opening - No Text',1), +(11,6,28875,'Gemcutting',1), +(11,6,29932,'Language Draenei',1), +(11,6,33391,'Journeyman Riding',1), +(11,6,45462,'Plague Strike',1), +(11,6,45477,'Icy Touch',1), +(11,6,45902,'Blood Strike',1), +(11,6,45903,'Offensive State (DND)',1), +(11,6,45927,'Summon Friend',1), +(11,6,47541,'Death Coil',1), +(11,6,48266,'Blood Presence',1), +(11,6,49410,'Forceful Deflection',1), +(11,6,49576,'Death Grip',1), +(11,6,52665,'Sigil',1), +(11,6,59539,'Shadow Resistance',1), +(11,6,59545,'Gift of the Naaru',1), +(11,6,59879,'Blood Plague',1), +(11,6,59921,'Frost Fever',1), +(11,6,61437,'Opening',1), +(11,6,61455,'Runic Focus',1); diff --git a/sql/updates/2008_12_22_17_mangos_item_template.sql b/sql/updates/2008_12_22_17_mangos_item_template.sql new file mode 100644 index 000000000..9e2eafaf7 --- /dev/null +++ b/sql/updates/2008_12_22_17_mangos_item_template.sql @@ -0,0 +1,18 @@ +ALTER TABLE db_version CHANGE COLUMN required_2008_12_22_16_mangos_playercreateinfo_spell required_2008_12_22_17_mangos_item_template bit; + +DELETE FROM item_template WHERE entry IN (34648,34649,34650,34651,34652,34653,34655,34656,34657,34658,34659,38145,38147,41751); +INSERT INTO item_template VALUES +(34648,4,4,-1,'Acherus Knight\'s Greaves',51496,2,32768,1,51,10,8,-1,-1,60,55,0,0,0,0,0,0,0,0,1,0,3,4,10,7,12,3,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,392,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,-1,0,0,0,0,-1,0,-1,0,0,0,0,-1,0,-1,0,0,0,0,-1,0,-1,0,0,0,0,-1,0,-1,1,'',0,0,0,0,0,6,0,0,0,0,0,55,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,0,'',0,0,0,0), +(34649,4,4,-1,'Acherus Knight\'s Gauntlets',51498,2,32768,1,34,6,10,-1,-1,60,55,0,0,0,0,0,0,0,0,1,0,3,4,15,7,6,32,8,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,356,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,-1,0,0,0,0,-1,0,-1,0,0,0,0,-1,0,-1,0,0,0,0,-1,0,-1,0,0,0,0,-1,0,-1,1,'',0,0,0,0,0,6,0,0,0,0,0,40,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,0,'',0,0,0,0), +(34650,4,4,-1,'Acherus Knight\'s Tunic',51494,2,32768,1,69,13,5,-1,-1,60,55,0,0,0,0,0,0,0,0,1,0,3,4,20,7,11,32,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,570,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,-1,0,0,0,0,-1,0,-1,0,0,0,0,-1,0,-1,0,0,0,0,-1,0,-1,0,0,0,0,-1,0,-1,1,'',0,0,0,0,0,6,0,0,0,0,0,115,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,0,'',0,0,0,0), +(34651,4,4,-1,'Acherus Knight\'s Girdle',51497,2,32768,1,35,7,6,-1,-1,60,55,0,0,0,0,0,0,0,0,1,0,2,4,10,32,15,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,320,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,-1,0,0,0,0,-1,0,-1,0,0,0,0,-1,0,-1,0,0,0,0,-1,0,-1,0,0,0,0,-1,0,-1,1,'',0,0,0,0,0,6,0,0,0,0,0,40,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,0,'',0,0,0,0), +(34652,4,4,-1,'Acherus Knight\'s Hood',51495,2,32768,1,52,10,1,-1,-1,60,55,0,0,0,0,0,0,0,0,1,0,3,4,15,7,15,32,9,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,463,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,-1,0,0,0,0,-1,0,-1,0,0,0,0,-1,0,-1,0,0,0,0,-1,0,-1,0,0,0,0,-1,0,-1,1,'',0,0,0,0,0,6,0,0,0,0,0,70,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,0,'',0,0,0,0), +(34653,4,4,-1,'Acherus Knight\'s Wristguard',51500,2,32768,1,36,7,9,-1,-1,60,55,0,0,0,0,0,0,0,0,1,0,3,4,7,31,7,7,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,249,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,-1,0,0,0,0,-1,0,-1,0,0,0,0,-1,0,-1,0,0,0,0,-1,0,-1,0,0,0,0,-1,0,-1,1,'',0,0,0,0,0,6,0,0,0,0,0,40,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,0,'',0,0,0,0), +(34655,4,4,-1,'Acherus Knight\'s Pauldrons',51501,2,32768,1,54,10,3,-1,-1,60,55,0,0,0,0,0,0,0,0,1,0,3,4,11,3,9,7,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,427,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,-1,0,0,0,0,-1,0,-1,0,0,0,0,-1,0,-1,0,0,0,0,-1,0,-1,0,0,0,0,-1,0,-1,1,'',0,0,0,0,0,6,0,0,0,0,0,70,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,0,'',0,0,0,0), +(34656,4,4,-1,'Acherus Knight\'s Cover',51499,2,32768,1,73,14,7,-1,-1,60,55,0,0,0,0,0,0,0,0,1,0,3,4,13,3,10,7,15,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,499,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,-1,0,0,0,0,-1,0,-1,0,0,0,0,-1,0,-1,0,0,0,0,-1,0,-1,0,0,0,0,-1,0,-1,1,'',0,0,0,0,0,6,0,0,0,0,0,85,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,0,'',0,0,0,0), +(34657,4,0,-1,'Choker of Damnation',6539,2,32768,1,2303,575,2,-1,-1,60,55,0,0,0,0,0,0,0,0,1,0,3,4,9,7,8,31,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,-1,0,0,0,0,-1,0,-1,0,0,0,0,-1,0,-1,0,0,0,0,-1,0,-1,0,0,0,0,-1,0,-1,1,'',0,0,0,0,0,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,0,'',0,0,0,0), +(34658,4,0,-1,'Plague Band',963,2,32768,1,534,133,11,-1,-1,60,55,0,0,0,0,0,0,0,0,1,0,3,4,11,3,6,7,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,-1,0,0,0,0,-1,0,-1,0,0,0,0,-1,0,-1,0,0,0,0,-1,0,-1,0,0,0,0,-1,0,-1,1,'',0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,0,'',0,0,0,0), +(34659,4,1,-1,'Acherus Knight\'s Shroud',49738,2,32768,1,31,6,16,-1,-1,60,55,0,0,0,0,0,0,0,0,1,0,2,4,12,7,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,39,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,-1,0,0,0,0,-1,0,-1,0,0,0,0,-1,0,-1,0,0,0,0,-1,0,-1,0,0,0,0,-1,0,-1,1,'',0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,0,'',0,0,0,0), +(38145,1,0,-1,'Deathweave Bag',1282,1,32768,1,0,0,18,-1,-1,35,0,0,0,0,0,0,0,0,0,1,12,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,-1,0,0,0,0,-1,0,-1,0,0,0,0,-1,0,-1,0,0,0,0,-1,0,-1,0,0,0,0,-1,0,-1,1,'',0,0,0,0,0,8,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,0,'',0,0,0,0), +(38147,4,0,-1,'Corrupted Band',963,2,32768,1,534,133,11,-1,-1,60,55,0,0,0,0,0,0,0,0,1,0,3,4,11,3,6,32,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,-1,0,0,0,0,-1,0,-1,0,0,0,0,-1,0,-1,0,0,0,0,-1,0,-1,0,0,0,0,-1,0,-1,1,'',0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,0,'',0,0,0,0), +(41751,0,5,-1,'Black Mushroom',36728,1,0,1,100,5,0,-1,-1,65,55,0,0,0,0,0,0,0,0,20,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,27094,0,-1,0,0,11,1000,0,0,0,0,-1,0,-1,0,0,0,0,-1,0,-1,0,0,0,0,-1,0,-1,0,0,0,0,-1,0,-1,0,'',0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,0,'',0,0,0,0); diff --git a/sql/updates/2008_12_22_18_characters_characters.sql b/sql/updates/2008_12_22_18_characters_characters.sql new file mode 100644 index 000000000..21f25913a --- /dev/null +++ b/sql/updates/2008_12_22_18_characters_characters.sql @@ -0,0 +1,68 @@ +ALTER TABLE character_db_version CHANGE COLUMN required_2008_12_22_06_characters_character_achievement required_2008_12_22_18_characters_characters bit; + +UPDATE characters SET data = REPLACE(data,' ',' '); +UPDATE characters SET data = CONCAT(TRIM(data),' '); + + +UPDATE characters SET data = CONCAT( + SUBSTRING(data, 1, length(SUBSTRING_INDEX(data, ' ', 10))), " 0 0 ", + SUBSTRING(data, length(SUBSTRING_INDEX(data, ' ', 10))+2, length(SUBSTRING_INDEX(data, ' ', 18))- length(SUBSTRING_INDEX(data, ' ', 10)) - 1), " ", + SUBSTRING(data, length(SUBSTRING_INDEX(data, ' ', 20))+2, length(SUBSTRING_INDEX(data, ' ', 22))- length(SUBSTRING_INDEX(data, ' ', 20)) - 1), " ", + SUBSTRING(data, length(SUBSTRING_INDEX(data, ' ', 36))+2, length(SUBSTRING_INDEX(data, ' ', 37))- length(SUBSTRING_INDEX(data, ' ', 36)) - 1), " ", + SUBSTRING(data, length(SUBSTRING_INDEX(data, ' ', 22))+2, length(SUBSTRING_INDEX(data, ' ', 28))- length(SUBSTRING_INDEX(data, ' ', 22)) - 1), " 0 0 ", + SUBSTRING(data, length(SUBSTRING_INDEX(data, ' ', 28))+2, length(SUBSTRING_INDEX(data, ' ', 34))- length(SUBSTRING_INDEX(data, ' ', 28)) - 1), " 0 0 ", + SUBSTRING(data, length(SUBSTRING_INDEX(data, ' ', 1564))+2, length(SUBSTRING_INDEX(data, ' ', 1565))- length(SUBSTRING_INDEX(data, ' ', 1564)) - 1), " 0 0 0 0 0 0 ", + SUBSTRING(data, length(SUBSTRING_INDEX(data, ' ', 1565))+2, length(SUBSTRING_INDEX(data, ' ', 1566))- length(SUBSTRING_INDEX(data, ' ', 1565)) - 1), " 0 0 0 0 0 0 ", + SUBSTRING(data, length(SUBSTRING_INDEX(data, ' ', 34))+2, length(SUBSTRING_INDEX(data, ' ', 36))- length(SUBSTRING_INDEX(data, ' ', 34)) - 1), " 0 0 0 ", + SUBSTRING(data, length(SUBSTRING_INDEX(data, ' ', 46))+2, length(SUBSTRING_INDEX(data, ' ', 48))- length(SUBSTRING_INDEX(data, ' ', 46)) - 1), " ", + SUBSTRING(data, length(SUBSTRING_INDEX(data, ' ', 146))+2, length(SUBSTRING_INDEX(data, ' ', 170))- length(SUBSTRING_INDEX(data, ' ', 146)) - 1), " ", + SUBSTRING(data, length(SUBSTRING_INDEX(data, ' ', 171))+2, length(SUBSTRING_INDEX(data, ' ', 209))- length(SUBSTRING_INDEX(data, ' ', 171)) - 1), " ", + ((SUBSTRING(data, length(SUBSTRING_INDEX(data, ' ', 209))+2, length(SUBSTRING_INDEX(data, ' ', 210))- length(SUBSTRING_INDEX(data, ' ', 209)) - 1) & ~0x100) | ((SUBSTRING(data, length(SUBSTRING_INDEX(data, ' ', 46))+2, length(SUBSTRING_INDEX(data, ' ', 47))- length(SUBSTRING_INDEX(data, ' ', 46)) - 1) & 0x1000) >> 4)), " ", + SUBSTRING(data, length(SUBSTRING_INDEX(data, ' ', 210))+2, length(SUBSTRING_INDEX(data, ' ', 233))- length(SUBSTRING_INDEX(data, ' ', 210)) - 1), " 0 ", + SUBSTRING(data, length(SUBSTRING_INDEX(data, ' ', 233))+2, length(SUBSTRING_INDEX(data, ' ', 358))- length(SUBSTRING_INDEX(data, ' ', 233)) - 1), " 0 ", + SUBSTRING(data, length(SUBSTRING_INDEX(data, ' ', 358))+2, length(SUBSTRING_INDEX(data, ' ', 359))- length(SUBSTRING_INDEX(data, ' ', 358)) - 1), " 0 ", + SUBSTRING(data, length(SUBSTRING_INDEX(data, ' ', 359))+2, length(SUBSTRING_INDEX(data, ' ', 374))- length(SUBSTRING_INDEX(data, ' ', 359)) - 1), " 0 ", + SUBSTRING(data, length(SUBSTRING_INDEX(data, ' ', 374))+2, length(SUBSTRING_INDEX(data, ' ', 375))- length(SUBSTRING_INDEX(data, ' ', 374)) - 1), " 0 ", + SUBSTRING(data, length(SUBSTRING_INDEX(data, ' ', 375))+2, length(SUBSTRING_INDEX(data, ' ', 390))- length(SUBSTRING_INDEX(data, ' ', 375)) - 1), " 0 ", + SUBSTRING(data, length(SUBSTRING_INDEX(data, ' ', 390))+2, length(SUBSTRING_INDEX(data, ' ', 391))- length(SUBSTRING_INDEX(data, ' ', 390)) - 1), " 0 ", + SUBSTRING(data, length(SUBSTRING_INDEX(data, ' ', 391))+2, length(SUBSTRING_INDEX(data, ' ', 406))- length(SUBSTRING_INDEX(data, ' ', 391)) - 1), " 0 ", + SUBSTRING(data, length(SUBSTRING_INDEX(data, ' ', 406))+2, length(SUBSTRING_INDEX(data, ' ', 407))- length(SUBSTRING_INDEX(data, ' ', 406)) - 1), " 0 ", + SUBSTRING(data, length(SUBSTRING_INDEX(data, ' ', 407))+2, length(SUBSTRING_INDEX(data, ' ', 422))- length(SUBSTRING_INDEX(data, ' ', 407)) - 1), " 0 ", + SUBSTRING(data, length(SUBSTRING_INDEX(data, ' ', 422))+2, length(SUBSTRING_INDEX(data, ' ', 423))- length(SUBSTRING_INDEX(data, ' ', 422)) - 1), " 0 ", + SUBSTRING(data, length(SUBSTRING_INDEX(data, ' ', 423))+2, length(SUBSTRING_INDEX(data, ' ', 438))- length(SUBSTRING_INDEX(data, ' ', 423)) - 1), " 0 ", + SUBSTRING(data, length(SUBSTRING_INDEX(data, ' ', 438))+2, length(SUBSTRING_INDEX(data, ' ', 439))- length(SUBSTRING_INDEX(data, ' ', 438)) - 1), " 0 ", + SUBSTRING(data, length(SUBSTRING_INDEX(data, ' ', 439))+2, length(SUBSTRING_INDEX(data, ' ', 454))- length(SUBSTRING_INDEX(data, ' ', 439)) - 1), " 0 ", + SUBSTRING(data, length(SUBSTRING_INDEX(data, ' ', 454))+2, length(SUBSTRING_INDEX(data, ' ', 455))- length(SUBSTRING_INDEX(data, ' ', 454)) - 1), " 0 ", + SUBSTRING(data, length(SUBSTRING_INDEX(data, ' ', 455))+2, length(SUBSTRING_INDEX(data, ' ', 470))- length(SUBSTRING_INDEX(data, ' ', 455)) - 1), " 0 ", + SUBSTRING(data, length(SUBSTRING_INDEX(data, ' ', 470))+2, length(SUBSTRING_INDEX(data, ' ', 471))- length(SUBSTRING_INDEX(data, ' ', 470)) - 1), " 0 ", + SUBSTRING(data, length(SUBSTRING_INDEX(data, ' ', 471))+2, length(SUBSTRING_INDEX(data, ' ', 486))- length(SUBSTRING_INDEX(data, ' ', 471)) - 1), " 0 ", + SUBSTRING(data, length(SUBSTRING_INDEX(data, ' ', 486))+2, length(SUBSTRING_INDEX(data, ' ', 487))- length(SUBSTRING_INDEX(data, ' ', 486)) - 1), " 0 ", + SUBSTRING(data, length(SUBSTRING_INDEX(data, ' ', 487))+2, length(SUBSTRING_INDEX(data, ' ', 502))- length(SUBSTRING_INDEX(data, ' ', 487)) - 1), " 0 ", + SUBSTRING(data, length(SUBSTRING_INDEX(data, ' ', 502))+2, length(SUBSTRING_INDEX(data, ' ', 503))- length(SUBSTRING_INDEX(data, ' ', 502)) - 1), " 0 ", + SUBSTRING(data, length(SUBSTRING_INDEX(data, ' ', 503))+2, length(SUBSTRING_INDEX(data, ' ', 518))- length(SUBSTRING_INDEX(data, ' ', 503)) - 1), " 0 ", + SUBSTRING(data, length(SUBSTRING_INDEX(data, ' ', 518))+2, length(SUBSTRING_INDEX(data, ' ', 519))- length(SUBSTRING_INDEX(data, ' ', 518)) - 1), " 0 ", + SUBSTRING(data, length(SUBSTRING_INDEX(data, ' ', 519))+2, length(SUBSTRING_INDEX(data, ' ', 534))- length(SUBSTRING_INDEX(data, ' ', 519)) - 1), " 0 ", + SUBSTRING(data, length(SUBSTRING_INDEX(data, ' ', 534))+2, length(SUBSTRING_INDEX(data, ' ', 535))- length(SUBSTRING_INDEX(data, ' ', 534)) - 1), " 0 ", + SUBSTRING(data, length(SUBSTRING_INDEX(data, ' ', 535))+2, length(SUBSTRING_INDEX(data, ' ', 550))- length(SUBSTRING_INDEX(data, ' ', 535)) - 1), " 0 ", + SUBSTRING(data, length(SUBSTRING_INDEX(data, ' ', 550))+2, length(SUBSTRING_INDEX(data, ' ', 551))- length(SUBSTRING_INDEX(data, ' ', 550)) - 1), " 0 ", + SUBSTRING(data, length(SUBSTRING_INDEX(data, ' ', 551))+2, length(SUBSTRING_INDEX(data, ' ', 566))- length(SUBSTRING_INDEX(data, ' ', 551)) - 1), " 0 ", + SUBSTRING(data, length(SUBSTRING_INDEX(data, ' ', 566))+2, length(SUBSTRING_INDEX(data, ' ', 567))- length(SUBSTRING_INDEX(data, ' ', 566)) - 1), " 0 ", + SUBSTRING(data, length(SUBSTRING_INDEX(data, ' ', 567))+2, length(SUBSTRING_INDEX(data, ' ', 582))- length(SUBSTRING_INDEX(data, ' ', 567)) - 1), " 0 ", + SUBSTRING(data, length(SUBSTRING_INDEX(data, ' ', 582))+2, length(SUBSTRING_INDEX(data, ' ', 583))- length(SUBSTRING_INDEX(data, ' ', 582)) - 1), " 0 ", + SUBSTRING(data, length(SUBSTRING_INDEX(data, ' ', 583))+2, length(SUBSTRING_INDEX(data, ' ', 598))- length(SUBSTRING_INDEX(data, ' ', 583)) - 1), " 0 ", + SUBSTRING(data, length(SUBSTRING_INDEX(data, ' ', 598))+2, length(SUBSTRING_INDEX(data, ' ', 599))- length(SUBSTRING_INDEX(data, ' ', 598)) - 1), " 0 ", + SUBSTRING(data, length(SUBSTRING_INDEX(data, ' ', 599))+2, length(SUBSTRING_INDEX(data, ' ', 614))- length(SUBSTRING_INDEX(data, ' ', 599)) - 1), " 0 ", + SUBSTRING(data, length(SUBSTRING_INDEX(data, ' ', 614))+2, length(SUBSTRING_INDEX(data, ' ', 615))- length(SUBSTRING_INDEX(data, ' ', 614)) - 1), " 0 ", + SUBSTRING(data, length(SUBSTRING_INDEX(data, ' ', 615))+2, length(SUBSTRING_INDEX(data, ' ', 630))- length(SUBSTRING_INDEX(data, ' ', 615)) - 1), " 0 ", + SUBSTRING(data, length(SUBSTRING_INDEX(data, ' ', 630))+2, length(SUBSTRING_INDEX(data, ' ', 631))- length(SUBSTRING_INDEX(data, ' ', 630)) - 1), " 0 ", + SUBSTRING(data, length(SUBSTRING_INDEX(data, ' ', 631))+2, length(SUBSTRING_INDEX(data, ' ', 646))- length(SUBSTRING_INDEX(data, ' ', 631)) - 1), " 0 ", + SUBSTRING(data, length(SUBSTRING_INDEX(data, ' ', 646))+2, length(SUBSTRING_INDEX(data, ' ', 647))- length(SUBSTRING_INDEX(data, ' ', 646)) - 1), " 0 ", + SUBSTRING(data, length(SUBSTRING_INDEX(data, ' ', 647))+2, length(SUBSTRING_INDEX(data, ' ', 922))- length(SUBSTRING_INDEX(data, ' ', 647)) - 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 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ", + SUBSTRING(data, length(SUBSTRING_INDEX(data, ' ', 922))+2, length(SUBSTRING_INDEX(data, ' ', 926))- length(SUBSTRING_INDEX(data, ' ', 922)) - 1), " 0 0 0 0 ", + SUBSTRING(data, length(SUBSTRING_INDEX(data, ' ', 926))+2, length(SUBSTRING_INDEX(data, ' ', 1332))- length(SUBSTRING_INDEX(data, ' ', 926)) - 1), " 0 ", + SUBSTRING(data, length(SUBSTRING_INDEX(data, ' ', 1332))+2, length(SUBSTRING_INDEX(data, ' ', 1544))- length(SUBSTRING_INDEX(data, ' ', 1332)) - 1), " 0 ", + SUBSTRING(data, length(SUBSTRING_INDEX(data, ' ', 1544))+2, length(SUBSTRING_INDEX(data, ' ', 1564))- length(SUBSTRING_INDEX(data, ' ', 1544)) - 1), " ", + SUBSTRING(data, length(SUBSTRING_INDEX(data, ' ', 1566))+2, length(SUBSTRING_INDEX(data, ' ', 1592))- length(SUBSTRING_INDEX(data, ' ', 1566)) - 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 ") +WHERE length(SUBSTRING_INDEX(data, ' ', 1592)) < length(data) and length(SUBSTRING_INDEX(data, ' ', 1593)) >= length(data); \ No newline at end of file diff --git a/sql/updates/2008_12_22_19_characters_item_instance.sql b/sql/updates/2008_12_22_19_characters_item_instance.sql new file mode 100644 index 000000000..96f31ff47 --- /dev/null +++ b/sql/updates/2008_12_22_19_characters_item_instance.sql @@ -0,0 +1,15 @@ +ALTER TABLE character_db_version CHANGE COLUMN required_2008_12_22_18_characters_characters required_2008_12_22_19_characters_item_instance bit; + +UPDATE item_instance SET data = REPLACE(data,' ',' '); +UPDATE item_instance SET data = CONCAT(TRIM(data),' '); + +UPDATE item_instance SET data= CONCAT( + SUBSTRING_INDEX(SUBSTRING_INDEX(data,' ',30),' ',-30),' 0 0 0 ', + SUBSTRING_INDEX(SUBSTRING_INDEX(data,' ',60),' ',-60+30),' 0 ') +WHERE SUBSTRING_INDEX(data,' ',60) = data AND SUBSTRING_INDEX(data,' ',60-1) <> data; + +UPDATE item_instance SET data= CONCAT( + SUBSTRING_INDEX(SUBSTRING_INDEX(data,' ',30),' ',-30),' 0 0 0 ', + SUBSTRING_INDEX(SUBSTRING_INDEX(data,' ',60),' ',-60+30),' 0 ', + SUBSTRING_INDEX(SUBSTRING_INDEX(data,' ',134),' ',-134+60)) +WHERE SUBSTRING_INDEX(data,' ',134) = data AND SUBSTRING_INDEX(data,' ',134-1) <> data; diff --git a/sql/updates/Makefile.am b/sql/updates/Makefile.am index c4ca950f1..f0f5f2d09 100644 --- a/sql/updates/Makefile.am +++ b/sql/updates/Makefile.am @@ -25,73 +25,6 @@ pkgdatadir = $(datadir)/mangos/sql/updates ## Files to be installed # Install basic SQL files to datadir pkgdata_DATA = \ - 06360_characters_corpse.sql \ - 06360_characters_characters.sql \ - 06362_characters.sql \ - 06362_mangos_instance_template.sql \ - 06367_mangos_spell_proc_event.sql \ - 06369_mangos_spell_affect.sql \ - 06370_mangos_spell_affect.sql \ - 06381_mangos_command.sql \ - 06387_characters_character_ticket.sql \ - 06387_mangos_mangos_string.sql \ - 06397_mangos_creature_template.sql \ - 06398_mangos_creature_template.sql \ - 06412_characters_declinedname.sql \ - 06426_mangos_locales.sql \ - 06426_realmd_localization.sql \ - 06431_mangos_mangos_string.sql \ - 06439_mangos_command.sql \ - 06456_mangos_command.sql \ - 06472_realmd_account.sql \ - 06492_mangos_spell_chain.sql \ - 06496_mangos_spell_pet_auras.sql \ - 06506_mangos_spell_proc_event.sql \ - 06509_mangos_command.sql \ - 06509_mangos_mangos_string.sql \ - 06513_mangos_command.sql \ - 06515_mangos_spell_proc_event.sql \ - 06521_mangos_spell_proc_event.sql \ - 06523_mangos_spell_proc_event.sql \ - 06528_mangos_spell_affect.sql \ - 06528_mangos_spell_proc_event.sql \ - 06538_mangos_spell_proc_event.sql \ - 06540_mangos_spell_proc_event.sql \ - 06544_mangos_spell_proc_event.sql \ - 06545_mangos_command.sql \ - 06557_mangos_command.sql \ - 06574_mangos_spell_proc_event.sql \ - 06585_mangos_command.sql \ - 06588_mangos_spell_proc_event.sql \ - 06596_characters_arena_team.sql \ - 06598_character_spell.sql \ - 06609_mangos_mangos_string.sql \ - 06613_mangos_mangos_string.sql \ - 06627_mangos_creature_movement.sql \ - 06640_mangos_reference_loot_template.sql \ - 06642_characters_declinedname.sql \ - 06668_mangos_spell_proc_event.sql \ - 06676_mangos_spell_proc_event.sql \ - 06681_mangos_mangos_string.sql \ - 06691_mangos_spell_proc_event.sql \ - 06693_mangos_spell_affect.sql \ - 06693_mangos_spell_proc_event.sql \ - 06698_characters_character_tutorial.sql \ - 06701_mangos_command.sql \ - 06701_mangos_mangos_string.sql \ - 06708_mangos_mangos_string.sql \ - 06715_mangos_spell_affect.sql \ - 06728_mangos_quest_template.sql \ - 06730_mangos_mangos_string.sql \ - 06740_characters_characters.sql \ - 06740_mangos_command.sql \ - 06740_mangos_mangos_string.sql \ - 06742_mangos_command.sql \ - 06742_mangos_mangos_string.sql \ - 06748_mangos_mangos_string.sql \ - 06750_mangos_command.sql \ - 06751_realmd_account.sql \ - 06760_mangos_creature_template.sql \ 2008_10_18_01_characters_characters.sql \ 2008_10_18_02_mangos_spell_proc_event.sql \ 2008_10_19_01_mangos_spell_affect.sql \ @@ -141,79 +74,32 @@ pkgdata_DATA = \ 2008_11_29_01_mangos_spell_proc_event.sql \ 2008_11_29_02_mangos_spell_elixir.sql \ 2008_12_03_01_character_guild_member.sql \ + 2008_12_15_01_character_arenas.sql \ + 2008_12_15_01_mangos_arenas.sql \ + 2008_12_22_01_mangos_creature_equip_template.sql \ + 2008_12_22_02_characters_character_pet.sql \ + 2008_12_22_03_mangos_item_template.sql \ + 2008_12_22_04_mangos_item_template.sql \ + 2008_12_22_05_characters_account_data.sql \ + 2008_12_22_06_characters_character_achievement.sql \ + 2008_12_22_07_mangos_quest_template.sql \ + 2008_12_22_08_mangos_milling_loot_template.sql \ + 2008_12_22_09_mangos_spell_affect.sql \ + 2008_12_22_10_mangos_string.sql \ + 2008_12_22_11_mangos_player_classlevelstats.sql \ + 2008_12_22_12_mangos_player_levelstats.sql \ + 2008_12_22_13_mangos_item_template.sql \ + 2008_12_22_14_mangos_playercreateinfo.sql \ + 2008_12_22_15_mangos_playercreateinfo_action.sql \ + 2008_12_22_16_mangos_playercreateinfo_spell.sql \ + 2008_12_22_17_mangos_item_template.sql \ + 2008_12_22_18_characters_characters.sql \ + 2008_12_22_19_characters_item_instance.sql \ README ## Additional files to include when running 'make dist' # SQL update files, to upgrade database schema from older revisions EXTRA_DIST = \ - 06360_characters_corpse.sql \ - 06360_characters_characters.sql \ - 06362_characters.sql \ - 06362_mangos_instance_template.sql \ - 06367_mangos_spell_proc_event.sql \ - 06369_mangos_spell_affect.sql \ - 06370_mangos_spell_affect.sql \ - 06381_mangos_command.sql \ - 06387_characters_character_ticket.sql \ - 06387_mangos_mangos_string.sql \ - 06397_mangos_creature_template.sql \ - 06398_mangos_creature_template.sql \ - 06412_characters_declinedname.sql \ - 06426_mangos_locales.sql \ - 06426_realmd_localization.sql \ - 06431_mangos_mangos_string.sql \ - 06439_mangos_command.sql \ - 06456_mangos_command.sql \ - 06472_realmd_account.sql \ - 06492_mangos_spell_chain.sql \ - 06496_mangos_spell_pet_auras.sql \ - 06506_mangos_spell_proc_event.sql \ - 06509_mangos_command.sql \ - 06509_mangos_mangos_string.sql \ - 06513_mangos_command.sql \ - 06515_mangos_spell_proc_event.sql \ - 06521_mangos_spell_proc_event.sql \ - 06523_mangos_spell_proc_event.sql \ - 06528_mangos_spell_affect.sql \ - 06528_mangos_spell_proc_event.sql \ - 06538_mangos_spell_proc_event.sql \ - 06540_mangos_spell_proc_event.sql \ - 06544_mangos_spell_proc_event.sql \ - 06545_mangos_command.sql \ - 06557_mangos_command.sql \ - 06574_mangos_spell_proc_event.sql \ - 06585_mangos_command.sql \ - 06588_mangos_spell_proc_event.sql \ - 06596_characters_arena_team.sql \ - 06598_character_spell.sql \ - 06609_mangos_mangos_string.sql \ - 06613_mangos_mangos_string.sql \ - 06627_mangos_creature_movement.sql \ - 06640_mangos_reference_loot_template.sql \ - 06642_characters_declinedname.sql \ - 06668_mangos_spell_proc_event.sql \ - 06673_mangos_areatrigger_scripts.sql \ - 06676_mangos_spell_proc_event.sql \ - 06681_mangos_mangos_string.sql \ - 06691_mangos_spell_proc_event.sql \ - 06693_mangos_spell_affect.sql \ - 06693_mangos_spell_proc_event.sql \ - 06698_characters_character_tutorial.sql \ - 06701_mangos_command.sql \ - 06701_mangos_mangos_string.sql \ - 06708_mangos_mangos_string.sql \ - 06715_mangos_spell_affect.sql \ - 06728_mangos_quest_template.sql \ - 06730_mangos_mangos_string.sql \ - 06740_characters_characters.sql \ - 06740_mangos_command.sql \ - 06740_mangos_mangos_string.sql \ - 06742_mangos_command.sql \ - 06742_mangos_mangos_string.sql \ - 06748_mangos_mangos_string.sql \ - 06750_mangos_command.sql \ - 06751_realmd_account.sql \ - 06760_mangos_creature_template.sql \ 2008_10_18_01_characters_characters.sql \ 2008_10_18_02_mangos_spell_proc_event.sql \ 2008_10_19_01_mangos_spell_affect.sql \ @@ -263,4 +149,25 @@ EXTRA_DIST = \ 2008_11_29_01_mangos_spell_proc_event.sql \ 2008_11_29_02_mangos_spell_elixir.sql \ 2008_12_03_01_character_guild_member.sql \ + 2008_12_15_01_character_arenas.sql \ + 2008_12_15_01_mangos_arenas.sql \ + 2008_12_22_01_mangos_creature_equip_template.sql \ + 2008_12_22_02_characters_character_pet.sql \ + 2008_12_22_03_mangos_item_template.sql \ + 2008_12_22_04_mangos_item_template.sql \ + 2008_12_22_05_characters_account_data.sql \ + 2008_12_22_06_characters_character_achievement.sql \ + 2008_12_22_07_mangos_quest_template.sql \ + 2008_12_22_08_mangos_milling_loot_template.sql \ + 2008_12_22_09_mangos_spell_affect.sql \ + 2008_12_22_10_mangos_string.sql \ + 2008_12_22_11_mangos_player_classlevelstats.sql \ + 2008_12_22_12_mangos_player_levelstats.sql \ + 2008_12_22_13_mangos_item_template.sql \ + 2008_12_22_14_mangos_playercreateinfo.sql \ + 2008_12_22_15_mangos_playercreateinfo_action.sql \ + 2008_12_22_16_mangos_playercreateinfo_spell.sql \ + 2008_12_22_17_mangos_item_template.sql \ + 2008_12_22_18_characters_characters.sql \ + 2008_12_22_19_characters_item_instance.sql \ README diff --git a/src/bindings/universal/ScriptMgr.h b/src/bindings/universal/ScriptMgr.h index 0b4605b5e..415aa23cc 100644 --- a/src/bindings/universal/ScriptMgr.h +++ b/src/bindings/universal/ScriptMgr.h @@ -68,7 +68,7 @@ struct Script CreatureAI* (*GetAI)(Creature *_Creature); InstanceData* (*GetInstanceData)(Map*); // ----------------------------------------- - + void registerSelf(); }; diff --git a/src/bindings/universal/Scripts/sc_defines.cpp b/src/bindings/universal/Scripts/sc_defines.cpp index 67f03a6e2..f0c732cdd 100644 --- a/src/bindings/universal/Scripts/sc_defines.cpp +++ b/src/bindings/universal/Scripts/sc_defines.cpp @@ -25,114 +25,140 @@ uint32 GetSkillLevel(Player *player,uint32 trskill) // Returns the level of some tradetrskill known by player // Need to add missing spells - uint32 spell_apprentice = 0; - uint32 spell_journeyman = 0; - uint32 spell_expert = 0; - uint32 spell_artisan = 0; - uint32 spell_master = 0; + uint32 spell_apprentice = 0; + uint32 spell_journeyman = 0; + uint32 spell_expert = 0; + uint32 spell_artisan = 0; + uint32 spell_master = 0; + uint32 spell_grand_master = 0; switch(trskill) { case TRADESKILL_ALCHEMY: - spell_apprentice = 2259; - spell_journeyman = 3101; - spell_expert = 3464; - spell_artisan = 11611; - spell_master = 28596; // teached by 28597 + spell_apprentice = 2259; + spell_journeyman = 3101; + spell_expert = 3464; + spell_artisan = 11611; + spell_master = 28596; // teached by 28597 + spell_grand_master = 0; break; case TRADESKILL_BLACKSMITHING: - spell_apprentice = 2018; - spell_journeyman = 3100; - spell_expert = 8768; - spell_artisan = 11454; - spell_master = 29844; // teached by 29845 + spell_apprentice = 2018; + spell_journeyman = 3100; + spell_expert = 8768; + spell_artisan = 11454; + spell_master = 29844; // teached by 29845 + spell_grand_master = 0; break; case TRADESKILL_COOKING: - spell_apprentice = 2550; - spell_journeyman = 3102; - spell_expert = 3413; - spell_artisan = 18260; - spell_master = 33359; // teached by 33361 + spell_apprentice = 2550; + spell_journeyman = 3102; + spell_expert = 3413; + spell_artisan = 18260; + spell_master = 33359; // teached by 33361 + spell_grand_master = 0; break; case TRADESKILL_ENCHANTING: - spell_apprentice = 7411; - spell_journeyman = 7412; - spell_expert = 7413; - spell_artisan = 13920; - spell_master = 28029; // teached by 28030 + spell_apprentice = 7411; + spell_journeyman = 7412; + spell_expert = 7413; + spell_artisan = 13920; + spell_master = 28029; // teached by 28030 + spell_grand_master = 0; break; case TRADESKILL_ENGINEERING: - spell_apprentice = 4036; - spell_journeyman = 4037; - spell_expert = 4038; - spell_artisan = 12656; - spell_master = 30350; // teached by 30351 + spell_apprentice = 4036; + spell_journeyman = 4037; + spell_expert = 4038; + spell_artisan = 12656; + spell_master = 30350; // teached by 30351 + spell_grand_master = 0; break; case TRADESKILL_FIRSTAID: - spell_apprentice = 3273; - spell_journeyman = 3274; - spell_expert = 7924; - spell_artisan = 10846; - spell_master = 27028; // teached by 27029 + spell_apprentice = 3273; + spell_journeyman = 3274; + spell_expert = 7924; + spell_artisan = 10846; + spell_master = 27028; // teached by 27029 + spell_grand_master = 0; break; case TRADESKILL_HERBALISM: - spell_apprentice = 2372; - spell_journeyman = 2373; - spell_expert = 3571; - spell_artisan = 11994; - spell_master = 0; + spell_apprentice = 2372; + spell_journeyman = 2373; + spell_expert = 3571; + spell_artisan = 11994; + spell_master = 0; + spell_grand_master = 0; break; case TRADESKILL_LEATHERWORKING: - spell_apprentice = 2108; - spell_journeyman = 3104; - spell_expert = 20649; - spell_artisan = 10662; - spell_master = 32549; // teached by 32550 + spell_apprentice = 2108; + spell_journeyman = 3104; + spell_expert = 20649; + spell_artisan = 10662; + spell_master = 32549; // teached by 32550 + spell_grand_master = 0; break; case TRADESKILL_POISONS: - spell_apprentice = 0; - spell_journeyman = 0; - spell_expert = 0; - spell_artisan = 0; - spell_master = 0; + spell_apprentice = 0; + spell_journeyman = 0; + spell_expert = 0; + spell_artisan = 0; + spell_master = 0; + spell_grand_master = 0; break; case TRADESKILL_TAILORING: - spell_apprentice = 3908; - spell_journeyman = 3909; - spell_expert = 3910; - spell_artisan = 12180; - spell_master = 26790; // teached by 26791 + spell_apprentice = 3908; + spell_journeyman = 3909; + spell_expert = 3910; + spell_artisan = 12180; + spell_master = 26790; // teached by 26791 + spell_grand_master = 0; break; case TRADESKILL_MINING: - spell_apprentice = 2581; - spell_journeyman = 2582; - spell_expert = 3568; - spell_artisan = 10249; - spell_master = 29354; // teached by 29355 + spell_apprentice = 2581; + spell_journeyman = 2582; + spell_expert = 3568; + spell_artisan = 10249; + spell_master = 29354; // teached by 29355 + spell_grand_master = 0; break; case TRADESKILL_FISHING: - spell_apprentice = 7733; - spell_journeyman = 7734; - spell_expert = 7736; - spell_artisan = 18249; - spell_master = 33098; // teached by 33100 + spell_apprentice = 7733; + spell_journeyman = 7734; + spell_expert = 7736; + spell_artisan = 18249; + spell_master = 33098; // teached by 33100 + spell_grand_master = 0; break; case TRADESKILL_SKINNING: - spell_apprentice = 8615; - spell_journeyman = 8619; - spell_expert = 8620; - spell_artisan = 10769; - spell_master = 32679; // teached by 32678 + spell_apprentice = 8615; + spell_journeyman = 8619; + spell_expert = 8620; + spell_artisan = 10769; + spell_master = 32679; // teached by 32678 + spell_grand_master = 0; break; case TRADESKILL_JEWELCRAFTING: - spell_apprentice = 25229; // teached by 25245 - spell_journeyman = 25230; // teached by 25246 - spell_expert = 28894; // teached by 28896 - spell_artisan = 28895; // teached by 28899 - spell_master = 28897; // teached by 28901 + spell_apprentice = 25229; // teached by 25245 + spell_journeyman = 25230; // teached by 25246 + spell_expert = 28894; // teached by 28896 + spell_artisan = 28895; // teached by 28899 + spell_master = 28897; // teached by 28901 + spell_grand_master = 0; + break; + case TRADESKILL_INSCRIPTION: + spell_apprentice = 0; + spell_journeyman = 0; + spell_expert = 0; + spell_artisan = 0; + spell_master = 0; + spell_grand_master = 0; break; } + if (player->HasSpell(spell_grand_master)) + return TRADESKILL_LEVEL_GRAND_MASTER; + if (player->HasSpell(spell_master)) return TRADESKILL_LEVEL_MASTER; diff --git a/src/bindings/universal/Scripts/sc_defines.h b/src/bindings/universal/Scripts/sc_defines.h index bcab10d15..6343c02fb 100644 --- a/src/bindings/universal/Scripts/sc_defines.h +++ b/src/bindings/universal/Scripts/sc_defines.h @@ -37,6 +37,7 @@ #define TRADESKILL_FISHING 12 #define TRADESKILL_SKINNING 13 #define TRADESKILL_JEWELCRAFTING 14 +#define TRADESKILL_INSCRIPTION 15 #define TRADESKILL_LEVEL_NONE 0 #define TRADESKILL_LEVEL_APPRENTICE 1 @@ -44,6 +45,7 @@ #define TRADESKILL_LEVEL_EXPERT 3 #define TRADESKILL_LEVEL_ARTISAN 4 #define TRADESKILL_LEVEL_MASTER 5 +#define TRADESKILL_LEVEL_GRAND_MASTER 6 // Gossip defines diff --git a/src/game/AchievementMgr.cpp b/src/game/AchievementMgr.cpp new file mode 100644 index 000000000..e4e26dec1 --- /dev/null +++ b/src/game/AchievementMgr.cpp @@ -0,0 +1,910 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "AchievementMgr.h" +#include "Common.h" +#include "Player.h" +#include "WorldPacket.h" +#include "Database/DBCEnums.h" +#include "ObjectMgr.h" +#include "Guild.h" +#include "Database/DatabaseEnv.h" +#include "GameEvent.h" +#include "World.h" +#include "SpellMgr.h" + +const CriteriaCastSpellRequirement AchievementMgr::criteriaCastSpellRequirements[CRITERIA_CAST_SPELL_REQ_COUNT] = + { + {5272, 3057, 0, 0}, + {5273, 2784, 0, 0}, + {5752, 9099, 0, 0}, + {5753, 8403, 0, 0}, + {5772, 0, 0, RACE_GNOME}, + {5774, 0, 0, RACE_BLOODELF}, + {5775, 0, 0, RACE_DRAENEI}, + {5776, 0, 0, RACE_DWARF}, + {5777, 0, 0, RACE_HUMAN}, + {5778, 0, 0, RACE_NIGHTELF}, + {5779, 0, 0, RACE_ORC}, + {5780, 0, 0, RACE_TAUREN}, + {5781, 0, 0, RACE_TROLL}, + {5782, 0, 0, RACE_UNDEAD_PLAYER}, + {6225, 5661, 0, 0}, + {6226, 26044, 0, 0}, + {6228, 739, 0, 0}, + {6229, 927, 0, 0}, + {6230, 1444, 0, 0}, + {6231, 8140, 0, 0}, + {6232, 5489, 0, 0}, + {6233,12336, 0, 0}, + {6234, 1351, 0, 0}, + {6235, 5484, 0, 0}, + {6236, 1182, 0, 0}, + {6237, 0, CLASS_DEATH_KNIGHT, RACE_ORC}, + {6238, 0, CLASS_WARRIOR, RACE_HUMAN}, + {6239, 0, CLASS_SHAMAN, RACE_TAUREN}, + {6240, 0, CLASS_DRUID, RACE_NIGHTELF}, + {6241, 0, CLASS_ROGUE, RACE_UNDEAD_PLAYER}, + {6242, 0, CLASS_HUNTER, RACE_TROLL}, + {6243, 0, CLASS_MAGE, RACE_GNOME}, + {6244, 0, CLASS_PALADIN, RACE_DWARF}, + {6245, 0, CLASS_WARLOCK, RACE_BLOODELF}, + {6246, 0, CLASS_PRIEST, RACE_DRAENEI}, + {6312, 0, CLASS_WARLOCK, RACE_GNOME}, + {6313, 0, CLASS_DEATH_KNIGHT, RACE_HUMAN}, + {6314, 0, CLASS_PRIEST, RACE_NIGHTELF}, + {6315, 0, CLASS_SHAMAN, RACE_ORC}, + {6316, 0, CLASS_DRUID, RACE_TAUREN}, + {6317, 0, CLASS_ROGUE, RACE_TROLL}, + {6318, 0, CLASS_WARRIOR, RACE_UNDEAD_PLAYER}, + {6319, 0, CLASS_MAGE, RACE_BLOODELF}, + {6320, 0, CLASS_PALADIN, RACE_DRAENEI}, + {6321, 0, CLASS_HUNTER, RACE_DWARF}, + {6662, 31261, 0, 0} + }; + +const AchievementReward AchievementMgr::achievementRewards[ACHIEVEMENT_REWARD_COUNT] = + { + // achievementId, horde titleid, alliance titleid, itemid + {45, 0, 0, 43348}, + {46, 78, 78, 0}, + {230, 72, 72, 0}, + {456, 139, 139, 0}, + {614, 0, 0, 44223}, + {619, 0, 0, 44224}, + {714, 47, 47, 0}, + {762, 130, 130, 0}, + {870, 127, 126, 0}, + {871, 144, 144, 0}, + {876, 0, 0, 43349}, + {907, 48, 48, 0}, + {913, 74, 74, 0}, + {942, 79, 79, 0}, + {943, 79, 79, 0}, + {945, 131, 131, 0}, + {948, 130, 130, 0}, + {953, 132, 132, 0}, + {978, 81, 81, 0}, + {1015, 77, 77, 0}, + {1021, 0, 0, 40643}, + {1038, 75, 75, 0}, + {1039, 76, 76, 0}, + {1163, 128, 128, 0}, + {1174, 82, 82, 0}, + {1175, 72, 72, 0}, + {1250, 0, 0, 40653}, + {1400, 120, 120, 0}, + {1402, 122, 122, 0}, + {1516, 83, 83, 0}, + {1563, 84, 84, 0}, + {1656, 124, 124, 0}, + {1657, 124, 124, 0}, + {1658, 129, 129, 0}, + {1681, 125, 125, 43300}, + {1682, 125, 125, 43300}, + {1683, 133, 133, 0}, + {1684, 133, 133, 0}, + {1691, 134, 134, 0}, + {1692, 134, 134, 0}, + {1693, 135, 135, 0}, + {1707, 135, 135, 0}, + {1784, 84, 84, 0}, + {1793, 137, 137, 0}, + {1956, 0, 0, 43824}, + {2051, 140, 140, 0}, + {2054, 121, 121, 0}, + {2096, 0, 0, 44430}, + {2136, 0, 0, 0},// <- TODO: find item for spell 59961 + {2137, 0, 0, 0},// <- TODO: find item for spell 60021 + {2138, 0, 0, 0},// <- TODO: find item for spell 59976 + {2143, 0, 0, 44178}, + {2144, 0, 0, 0},// <- TODO: find item for spell 60024 + {2145, 0, 0, 0},// <- TODO: find item for spell 60024 + {2186, 141, 141, 0}, + {2187, 142, 142, 0}, + {2188, 143, 143, 0} + }; + +AchievementMgr::AchievementMgr(Player *player) +{ + m_player = player; +} + +AchievementMgr::~AchievementMgr() +{ +} + +void AchievementMgr::SaveToDB() +{ + if(!m_completedAchievements.empty()) + { + bool need_execute = false; + std::ostringstream ssdel; + std::ostringstream ssins; + for(CompletedAchievementMap::iterator iter = m_completedAchievements.begin(); iter!=m_completedAchievements.end(); iter++) + { + if(!iter->second.changed) + continue; + + /// first new/changed record prefix + if(!need_execute) + { + ssdel << "DELETE FROM character_achievement WHERE guid = " << GetPlayer()->GetGUIDLow() << " AND achievement IN ("; + ssins << "INSERT INTO character_achievement (guid, achievement, date) VALUES "; + need_execute = true; + } + /// next new/changed record prefix + else + { + ssdel << ", "; + ssins << ", "; + } + + // new/changed record data + ssdel << iter->first; + ssins << "("<GetGUIDLow() << ", " << iter->first << ", " << uint64(iter->second.date) << ")"; + + /// mark as saved in db + iter->second.changed = false; + } + + if(need_execute) + ssdel << ")"; + + if(need_execute) + { + CharacterDatabase.BeginTransaction (); + CharacterDatabase.Execute( ssdel.str().c_str() ); + CharacterDatabase.Execute( ssins.str().c_str() ); + CharacterDatabase.CommitTransaction (); + } + } + + if(!m_criteriaProgress.empty()) + { + /// prepare deleting and insert + bool need_execute = false; + std::ostringstream ssdel; + std::ostringstream ssins; + for(CriteriaProgressMap::iterator iter = m_criteriaProgress.begin(); iter!=m_criteriaProgress.end(); ++iter) + { + if(!iter->second.changed) + continue; + + /// first new/changed record prefix + if(!need_execute) + { + ssdel << "DELETE FROM character_achievement_progress WHERE guid = " << GetPlayer()->GetGUIDLow() << " AND criteria IN ("; + ssins << "INSERT INTO character_achievement_progress (guid, criteria, counter, date) VALUES "; + need_execute = true; + } + /// next new/changed record prefix + else + { + ssdel << ", "; + ssins << ", "; + } + + // new/changed record data + ssdel << iter->first; + ssins << "(" << GetPlayer()->GetGUIDLow() << ", " << iter->first << ", " << iter->second.counter << ", " << iter->second.date << ")"; + + /// mark as saved in db + iter->second.changed = false; + } + + if(need_execute) + ssdel << ")"; + + if(need_execute) + { + CharacterDatabase.BeginTransaction (); + CharacterDatabase.Execute( ssdel.str().c_str() ); + CharacterDatabase.Execute( ssins.str().c_str() ); + CharacterDatabase.CommitTransaction (); + } + } +} + +void AchievementMgr::LoadFromDB(QueryResult *achievementResult, QueryResult *criteriaResult) +{ + if(achievementResult) + { + do + { + Field *fields = achievementResult->Fetch(); + CompletedAchievementData& ca = m_completedAchievements[fields[0].GetUInt32()]; + ca.date = time_t(fields[1].GetUInt64()); + ca.changed = false; + } while(achievementResult->NextRow()); + delete achievementResult; + } + + if(criteriaResult) + { + do + { + Field *fields = criteriaResult->Fetch(); + + uint32 id = fields[0].GetUInt32(); + uint32 counter = fields[1].GetUInt32(); + time_t date = time_t(fields[2].GetUInt64()); + + AchievementCriteriaEntry const* criteria = sAchievementCriteriaStore.LookupEntry(id); + if(!criteria || criteria->timeLimit && date + criteria->timeLimit < time(NULL)) + continue; + + CriteriaProgress& progress = m_criteriaProgress[id]; + progress.counter = counter; + progress.date = date; + progress.changed = false; + } while(criteriaResult->NextRow()); + delete criteriaResult; + } + +} + +void AchievementMgr::SendAchievementEarned(AchievementEntry const* achievement) +{ + sLog.outString("AchievementMgr::SendAchievementEarned(%u)", achievement->ID); + + const char *msg = "|Hplayer:$N|h[$N]|h has earned the achievement $a!"; + if(Guild* guild = objmgr.GetGuildById(GetPlayer()->GetGuildId())) + { + WorldPacket data(SMSG_MESSAGECHAT, 200); + data << uint8(CHAT_MSG_ACHIEVEMENT); + data << uint8(CHAT_MSG_GUILD_ACHIEVEMENT); + data << uint32(LANG_UNIVERSAL); + data << uint64(GetPlayer()->GetGUID()); + data << uint32(5); + data << uint64(GetPlayer()->GetGUID()); + data << uint32(strlen(msg)+1); + data << msg; + data << uint8(0); + data << uint32(achievement->ID); + guild->BroadcastPacket(&data); + } + if(achievement->flags & (ACHIEVEMENT_FLAG_REALM_FIRST_KILL|ACHIEVEMENT_FLAG_REALM_FIRST_REACH)) + { + // broadcast realm first reached + WorldPacket data(SMSG_SERVER_FIRST_ACHIEVEMENT, strlen(GetPlayer()->GetName())+1+8+4+4); + data << GetPlayer()->GetName(); + data << uint64(GetPlayer()->GetGUID()); + data << uint32(achievement->ID); + data << uint32(0); // 1=link supplied string as player name, 0=display plain string + sWorld.SendGlobalMessage(&data); + } + else + { + WorldPacket data(SMSG_MESSAGECHAT, 200); + data << uint8(CHAT_MSG_ACHIEVEMENT); + data << uint32(LANG_UNIVERSAL); + data << uint64(GetPlayer()->GetGUID()); + data << uint32(5); + data << uint64(GetPlayer()->GetGUID()); + data << uint32(strlen(msg)+1); + data << msg; + data << uint8(0); + data << uint32(achievement->ID); + GetPlayer()->SendMessageToSet(&data, true); + + } + WorldPacket data(SMSG_ACHIEVEMENT_EARNED, 8+4+8); + data.append(GetPlayer()->GetPackGUID()); + data << uint32(achievement->ID); + data << uint32(secsToTimeBitFields(time(NULL))); + data << uint32(0); + GetPlayer()->SendMessageToSet(&data, true); +} + +void AchievementMgr::SendCriteriaUpdate(uint32 id, CriteriaProgress const* progress) +{ + WorldPacket data(SMSG_CRITERIA_UPDATE, 8+4+8); + data << uint32(id); + + // the counter is packed like a packed Guid + data.appendPackGUID(progress->counter); + + data.append(GetPlayer()->GetPackGUID()); + data << uint32(0); + data << uint32(secsToTimeBitFields(progress->date)); + data << uint32(0); // timer 1 + data << uint32(0); // timer 2 + GetPlayer()->SendMessageToSet(&data, true); +} + +/** + * called at player login. The player might have fulfilled some achievements when the achievement system wasn't working yet + */ +void AchievementMgr::CheckAllAchievementCriteria() +{ + // suppress sending packets + for(uint32 i=0; igroupFlag & ACHIEVEMENT_CRITERIA_GROUP_NOT_IN_GROUP && GetPlayer()->GetGroup()) + continue; + + AchievementEntry const *achievement = sAchievementStore.LookupEntry(achievementCriteria->referredAchievement); + if(!achievement) + continue; + + if(achievement->factionFlag == ACHIEVEMENT_FACTION_FLAG_HORDE && GetPlayer()->GetTeam() != HORDE || + achievement->factionFlag == ACHIEVEMENT_FACTION_FLAG_ALLIANCE && GetPlayer()->GetTeam() != ALLIANCE) + continue; + + switch (type) + { + case ACHIEVEMENT_CRITERIA_TYPE_REACH_LEVEL: + SetCriteriaProgress(achievementCriteria, GetPlayer()->getLevel()); + break; + case ACHIEVEMENT_CRITERIA_TYPE_BUY_BANK_SLOT: + SetCriteriaProgress(achievementCriteria, GetPlayer()->GetByteValue(PLAYER_BYTES_2, 2)+1); + break; + case ACHIEVEMENT_CRITERIA_TYPE_KILL_CREATURE: + // AchievementMgr::UpdateAchievementCriteria might also be called on login - skip in this case + if(!miscvalue1) + continue; + if(achievementCriteria->kill_creature.creatureID != miscvalue1) + continue; + SetCriteriaProgress(achievementCriteria, miscvalue2, true); + break; + case ACHIEVEMENT_CRITERIA_TYPE_REACH_SKILL_LEVEL: + if(uint32 skillvalue = GetPlayer()->GetBaseSkillValue(achievementCriteria->reach_skill_level.skillID)) + SetCriteriaProgress(achievementCriteria, skillvalue); + break; + case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_QUEST_COUNT: + { + uint32 counter =0; + for(QuestStatusMap::iterator itr = GetPlayer()->getQuestStatusMap().begin(); itr!=GetPlayer()->getQuestStatusMap().end(); itr++) + if(itr->second.m_rewarded) + counter++; + SetCriteriaProgress(achievementCriteria, counter); + break; + } + case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_QUESTS_IN_ZONE: + { + uint32 counter =0; + for(QuestStatusMap::iterator itr = GetPlayer()->getQuestStatusMap().begin(); itr!=GetPlayer()->getQuestStatusMap().end(); itr++) + { + Quest const* quest = objmgr.GetQuestTemplate(itr->first); + if(itr->second.m_rewarded && quest->GetZoneOrSort() == achievementCriteria->complete_quests_in_zone.zoneID) + counter++; + } + SetCriteriaProgress(achievementCriteria, counter); + break; + } + case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_DAILY_QUEST: + // AchievementMgr::UpdateAchievementCriteria might also be called on login - skip in this case + if(!miscvalue1) + continue; + SetCriteriaProgress(achievementCriteria, miscvalue1, true); + break; + case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_BATTLEGROUND: + // AchievementMgr::UpdateAchievementCriteria might also be called on login - skip in this case + if(!miscvalue1) + continue; + if(GetPlayer()->GetMapId() != achievementCriteria->complete_battleground.mapID) + continue; + SetCriteriaProgress(achievementCriteria, miscvalue1, true); + break; + case ACHIEVEMENT_CRITERIA_TYPE_LEARN_SPELL: + if(GetPlayer()->HasSpell(achievementCriteria->learn_spell.spellID)) + SetCriteriaProgress(achievementCriteria, 1); + break; + case ACHIEVEMENT_CRITERIA_TYPE_DEATH_AT_MAP: + // AchievementMgr::UpdateAchievementCriteria might also be called on login - skip in this case + if(!miscvalue1) + continue; + if(GetPlayer()->GetMapId() != achievementCriteria->death_at_map.mapID) + continue; + SetCriteriaProgress(achievementCriteria, 1, true); + break; + case ACHIEVEMENT_CRITERIA_TYPE_KILLED_BY_CREATURE: + // AchievementMgr::UpdateAchievementCriteria might also be called on login - skip in this case + if(!miscvalue1) + continue; + if(miscvalue1 != achievementCriteria->killed_by_creature.creatureEntry) + continue; + SetCriteriaProgress(achievementCriteria, 1, true); + break; + case ACHIEVEMENT_CRITERIA_TYPE_KILLED_BY_PLAYER: + // AchievementMgr::UpdateAchievementCriteria might also be called on login - skip in this case + if(!miscvalue1) + continue; + SetCriteriaProgress(achievementCriteria, 1, true); + break; + case ACHIEVEMENT_CRITERIA_TYPE_FALL_WITHOUT_DYING: + { + // AchievementMgr::UpdateAchievementCriteria might also be called on login - skip in this case + if(!miscvalue1) + continue; + if(achievement->ID == 1260) + { + if(Player::GetDrunkenstateByValue(GetPlayer()->GetDrunkValue()) != DRUNKEN_SMASHED) + continue; + // TODO: hardcoding eventid is bad, it can differ from DB to DB - maye implement something using HolidayNames.dbc? + if(!gameeventmgr.IsActiveEvent(26)) + continue; + } + // miscvalue1 is the ingame fallheight*100 as stored in dbc + SetCriteriaProgress(achievementCriteria, miscvalue1); + break; + } + case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_QUEST: + if(GetPlayer()->GetQuestRewardStatus(achievementCriteria->complete_quest.questID)) + SetCriteriaProgress(achievementCriteria, 1); + break; + case ACHIEVEMENT_CRITERIA_TYPE_USE_ITEM: + // AchievementMgr::UpdateAchievementCriteria might also be called on login - skip in this case + if(!miscvalue1) + continue; + if(achievementCriteria->use_item.itemID != miscvalue1) + continue; + SetCriteriaProgress(achievementCriteria, 1, true); + break; + case ACHIEVEMENT_CRITERIA_TYPE_OWN_ITEM: + // speedup for non-login case + if(miscvalue1 && achievementCriteria->own_item.itemID!=miscvalue1) + continue; + SetCriteriaProgress(achievementCriteria, GetPlayer()->GetItemCount(achievementCriteria->own_item.itemID, true)); + break; + case ACHIEVEMENT_CRITERIA_TYPE_LOOT_ITEM: + // You _have_ to loot that item, just owning it when logging in does _not_ count! + if(!miscvalue1) + continue; + if(miscvalue1 != achievementCriteria->own_item.itemID) + continue; + SetCriteriaProgress(achievementCriteria, miscvalue2, true); + break; + case ACHIEVEMENT_CRITERIA_TYPE_BE_SPELL_TARGET: + case ACHIEVEMENT_CRITERIA_TYPE_BE_SPELL_TARGET2: + if (!miscvalue1 || miscvalue1 != achievementCriteria->be_spell_target.spellID) + continue; + SetCriteriaProgress(achievementCriteria, 1, true); + break; + case ACHIEVEMENT_CRITERIA_TYPE_CAST_SPELL: + if (!miscvalue1 || miscvalue1 != achievementCriteria->cast_spell.spellID) + continue; + SetCriteriaProgress(achievementCriteria, 1, true); + break; + case ACHIEVEMENT_CRITERIA_TYPE_CAST_SPELL2: + { + if (!miscvalue1 || miscvalue1 != achievementCriteria->cast_spell.spellID) + continue; + // those requirements couldn't be found in the dbc + + const CriteriaCastSpellRequirement *requirement = NULL; + for (uint32 i=0; iID) + { + requirement = &criteriaCastSpellRequirements[i]; + break; + } + } + + if (requirement) + { + if (!unit) + continue; + + if (requirement->creatureEntry && unit->GetEntry() != requirement->creatureEntry) + continue; + + if (requirement->playerRace && (unit->GetTypeId() != TYPEID_PLAYER || unit->getRace()!=requirement->playerRace)) + continue; + + if (requirement->playerClass && (unit->GetTypeId() != TYPEID_PLAYER || unit->getClass()!=requirement->playerClass)) + continue; + } + SetCriteriaProgress(achievementCriteria, 1, true); + break; + } + case ACHIEVEMENT_CRITERIA_TYPE_LEARN_SKILLLINE_SPELLS: + { + uint32 spellCount = 0; + for (PlayerSpellMap::const_iterator spellIter = GetPlayer()->GetSpellMap().begin(); + spellIter != GetPlayer()->GetSpellMap().end(); + spellIter++) + { + for(SkillLineAbilityMap::const_iterator skillIter = spellmgr.GetBeginSkillLineAbilityMap(spellIter->first); + skillIter != spellmgr.GetEndSkillLineAbilityMap(spellIter->first); + skillIter++) + { + if(skillIter->second->skillId == achievementCriteria->learn_skilline_spell.skillLine) + spellCount++; + } + } + SetCriteriaProgress(achievementCriteria, spellCount); + break; + } + case ACHIEVEMENT_CRITERIA_TYPE_VISIT_BARBER_SHOP: + { + // skip for login case + if(!miscvalue1) + continue; + SetCriteriaProgress(achievementCriteria, 1); + break; + } + case ACHIEVEMENT_CRITERIA_TYPE_GAIN_REPUTATION: + { + int32 reputation = GetPlayer()->GetReputation(achievementCriteria->gain_reputation.factionID); + if (reputation > 0) + SetCriteriaProgress(achievementCriteria, reputation); + break; + } + case ACHIEVEMENT_CRITERIA_TYPE_GAIN_EXALTED_REPUTATION: + { + uint32 counter = 0; + const FactionStateList factionStateList = GetPlayer()->GetFactionStateList(); + for (FactionStateList::const_iterator iter = factionStateList.begin(); iter!= factionStateList.end(); iter++) + { + if(GetPlayer()->ReputationToRank(iter->second.Standing) >= REP_EXALTED) + ++counter; + } + SetCriteriaProgress(achievementCriteria, counter); + break; + } + case ACHIEVEMENT_CRITERIA_TYPE_EXPLORE_AREA: + { + WorldMapOverlayEntry const* worldOverlayEntry = sWorldMapOverlayStore.LookupEntry(achievementCriteria->explore_area.areaReference); + if(!worldOverlayEntry) + break; + + int32 exploreFlag = GetAreaFlagByAreaID(worldOverlayEntry->areatableID); + if(exploreFlag < 0) + break; + + uint32 playerIndexOffset = uint32(exploreFlag) / 32; + uint32 mask = 1<< (uint32(exploreFlag) % 32); + + if(GetPlayer()->GetUInt32Value(PLAYER_EXPLORED_ZONES_1 + playerIndexOffset) & mask) + SetCriteriaProgress(achievementCriteria, 1); + break; + } + + } + if(IsCompletedCriteria(achievementCriteria)) + CompletedCriteria(achievementCriteria); + } +} + +bool AchievementMgr::IsCompletedCriteria(AchievementCriteriaEntry const* achievementCriteria) +{ + AchievementEntry const* achievement = sAchievementStore.LookupEntry(achievementCriteria->referredAchievement); + if(!achievement) + return false; + + // counter can never complete + if(achievement->flags & ACHIEVEMENT_FLAG_COUNTER) + return false; + + if(achievement->flags & (ACHIEVEMENT_FLAG_REALM_FIRST_REACH | ACHIEVEMENT_FLAG_REALM_FIRST_KILL)) + { + // someone on this realm has already completed that achievement + if(objmgr.allCompletedAchievements.find(achievement->ID)!=objmgr.allCompletedAchievements.end()) + return false; + } + + CriteriaProgressMap::const_iterator itr = m_criteriaProgress.find(achievementCriteria->ID); + if(itr == m_criteriaProgress.end()) + return false; + + CriteriaProgress const* progress = &itr->second; + + switch(achievementCriteria->requiredType) + { + case ACHIEVEMENT_CRITERIA_TYPE_REACH_LEVEL: + if(achievement->ID == 467 && GetPlayer()->getClass() != CLASS_SHAMAN || + achievement->ID == 466 && GetPlayer()->getClass() != CLASS_DRUID || + achievement->ID == 465 && GetPlayer()->getClass() != CLASS_PALADIN || + achievement->ID == 464 && GetPlayer()->getClass() != CLASS_PRIEST || + achievement->ID == 463 && GetPlayer()->getClass() != CLASS_WARLOCK || + achievement->ID == 462 && GetPlayer()->getClass() != CLASS_HUNTER || + achievement->ID == 461 && GetPlayer()->getClass() != CLASS_DEATH_KNIGHT || + achievement->ID == 460 && GetPlayer()->getClass() != CLASS_MAGE || + achievement->ID == 459 && GetPlayer()->getClass() != CLASS_WARRIOR || + achievement->ID == 458 && GetPlayer()->getClass() != CLASS_ROGUE || + + achievement->ID == 1404 && GetPlayer()->getRace() != RACE_GNOME || + achievement->ID == 1405 && GetPlayer()->getRace() != RACE_BLOODELF || + achievement->ID == 1406 && GetPlayer()->getRace() != RACE_DRAENEI || + achievement->ID == 1407 && GetPlayer()->getRace() != RACE_DWARF || + achievement->ID == 1408 && GetPlayer()->getRace() != RACE_HUMAN || + achievement->ID == 1409 && GetPlayer()->getRace() != RACE_NIGHTELF || + achievement->ID == 1410 && GetPlayer()->getRace() != RACE_ORC || + achievement->ID == 1411 && GetPlayer()->getRace() != RACE_TAUREN || + achievement->ID == 1412 && GetPlayer()->getRace() != RACE_TROLL || + achievement->ID == 1413 && GetPlayer()->getRace() != RACE_UNDEAD_PLAYER ) + return false; + return progress->counter >= achievementCriteria->reach_level.level; + case ACHIEVEMENT_CRITERIA_TYPE_BUY_BANK_SLOT: + return progress->counter >= achievementCriteria->buy_bank_slot.numberOfSlots; + case ACHIEVEMENT_CRITERIA_TYPE_KILL_CREATURE: + return progress->counter >= achievementCriteria->kill_creature.creatureCount; + case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_ACHIEVEMENT: + return m_completedAchievements.find(achievementCriteria->complete_achievement.linkedAchievement) != m_completedAchievements.end(); + case ACHIEVEMENT_CRITERIA_TYPE_REACH_SKILL_LEVEL: + return progress->counter >= achievementCriteria->reach_skill_level.skillLevel; + case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_QUESTS_IN_ZONE: + return progress->counter >= achievementCriteria->complete_quests_in_zone.questCount; + case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_DAILY_QUEST: + return progress->counter >= achievementCriteria->complete_daily_quest.questCount; + case ACHIEVEMENT_CRITERIA_TYPE_LEARN_SPELL: + return progress->counter >= 1; + case ACHIEVEMENT_CRITERIA_TYPE_FALL_WITHOUT_DYING: + return progress->counter >= achievementCriteria->fall_without_dying.fallHeight; + case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_QUEST: + return progress->counter >= 1; + case ACHIEVEMENT_CRITERIA_TYPE_USE_ITEM: + return progress->counter >= achievementCriteria->use_item.itemCount; + case ACHIEVEMENT_CRITERIA_TYPE_OWN_ITEM: + return progress->counter >= achievementCriteria->own_item.itemCount; + case ACHIEVEMENT_CRITERIA_TYPE_LOOT_ITEM: + return progress->counter >= achievementCriteria->loot_item.itemCount; + case ACHIEVEMENT_CRITERIA_TYPE_BE_SPELL_TARGET: + case ACHIEVEMENT_CRITERIA_TYPE_BE_SPELL_TARGET2: + return progress->counter >= achievementCriteria->be_spell_target.spellCount; + case ACHIEVEMENT_CRITERIA_TYPE_CAST_SPELL: + case ACHIEVEMENT_CRITERIA_TYPE_CAST_SPELL2: + return progress->counter >= achievementCriteria->cast_spell.castCount; + case ACHIEVEMENT_CRITERIA_TYPE_LEARN_SKILLLINE_SPELLS: + return progress->counter >= achievementCriteria->learn_skilline_spell.spellCount; + case ACHIEVEMENT_CRITERIA_TYPE_VISIT_BARBER_SHOP: + return progress->counter >= achievementCriteria->visit_barber.numberOfVisits; + case ACHIEVEMENT_CRITERIA_TYPE_GAIN_REPUTATION: + return progress->counter >= achievementCriteria->gain_reputation.reputationAmount; + case ACHIEVEMENT_CRITERIA_TYPE_GAIN_EXALTED_REPUTATION: + return progress->counter >= achievementCriteria->gain_exalted_reputation.numberOfExaltedFactions; + case ACHIEVEMENT_CRITERIA_TYPE_EXPLORE_AREA: + return progress->counter >= 1; + + // handle all statistic-only criteria here + case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_BATTLEGROUND: + case ACHIEVEMENT_CRITERIA_TYPE_DEATH_AT_MAP: + case ACHIEVEMENT_CRITERIA_TYPE_KILLED_BY_CREATURE: + case ACHIEVEMENT_CRITERIA_TYPE_KILLED_BY_PLAYER: + return false; + } + return false; +} + +void AchievementMgr::CompletedCriteria(AchievementCriteriaEntry const* criteria) +{ + AchievementEntry const* achievement = sAchievementStore.LookupEntry(criteria->referredAchievement); + if(!achievement) + return; + // counter can never complete + if(achievement->flags & ACHIEVEMENT_FLAG_COUNTER) + return; + + if(criteria->completionFlag & ACHIEVEMENT_CRITERIA_COMPLETE_FLAG_ALL || GetAchievementCompletionState(achievement)==ACHIEVEMENT_COMPLETED_COMPLETED_NOT_STORED) + { + CompletedAchievement(achievement); + } +} + +// TODO: achievement 705 requires 4 criteria to be fulfilled +AchievementCompletionState AchievementMgr::GetAchievementCompletionState(AchievementEntry const* entry) +{ + if(m_completedAchievements.find(entry->ID)!=m_completedAchievements.end()) + return ACHIEVEMENT_COMPLETED_COMPLETED_STORED; + + bool foundOutstanding = false; + for (uint32 entryId = 0; entryIdreferredAchievement!= entry->ID) + continue; + + if(IsCompletedCriteria(criteria) && criteria->completionFlag & ACHIEVEMENT_CRITERIA_COMPLETE_FLAG_ALL) + return ACHIEVEMENT_COMPLETED_COMPLETED_NOT_STORED; + + // found an umcompleted criteria, but DONT return false yet - there might be a completed criteria with ACHIEVEMENT_CRITERIA_COMPLETE_FLAG_ALL + if(!IsCompletedCriteria(criteria)) + foundOutstanding = true; + } + if(foundOutstanding) + return ACHIEVEMENT_COMPLETED_NONE; + else + return ACHIEVEMENT_COMPLETED_COMPLETED_NOT_STORED; +} + +void AchievementMgr::SetCriteriaProgress(AchievementCriteriaEntry const* entry, uint32 newValue, bool relative) +{ + sLog.outString("AchievementMgr::SetCriteriaProgress(%u, %u)", entry->ID, newValue); + CriteriaProgress *progress = NULL; + + CriteriaProgressMap::iterator iter = m_criteriaProgress.find(entry->ID); + + if(iter == m_criteriaProgress.end()) + { + progress = &m_criteriaProgress[entry->ID]; + progress->counter = 0; + progress->date = time(NULL); + } + else + { + progress = &iter->second; + if(relative) + newValue += progress->counter; + if(progress->counter == newValue) + return; + progress->counter = newValue; + } + + progress->changed = true; + + if(entry->timeLimit) + { + time_t now = time(NULL); + if(progress->date + entry->timeLimit < now) + { + progress->counter = 1; + } + // also it seems illogical, the timeframe will be extended at every criteria update + progress->date = now; + } + SendCriteriaUpdate(entry->ID,progress); +} + +void AchievementMgr::CompletedAchievement(AchievementEntry const* achievement) +{ + sLog.outString("AchievementMgr::CompletedAchievement(%u)", achievement->ID); + if(achievement->flags & ACHIEVEMENT_FLAG_COUNTER || m_completedAchievements.find(achievement->ID)!=m_completedAchievements.end()) + return; + + SendAchievementEarned(achievement); + CompletedAchievementData& ca = m_completedAchievements[achievement->ID]; + ca.date = time(NULL); + ca.changed = true; + + // don't insert for ACHIEVEMENT_FLAG_REALM_FIRST_KILL since otherwise only the first group member would reach that achievement + // TODO: where do set this instead? + if(!(achievement->flags & ACHIEVEMENT_FLAG_REALM_FIRST_KILL)) + objmgr.allCompletedAchievements.insert(achievement->ID); + + UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_ACHIEVEMENT); + + // reward items and titles + AchievementReward const* reward = NULL; + for (uint32 i=0; iID) + { + reward = &achievementRewards[i]; + break; + } + } + + if (reward) + { + sLog.outString("achiev %u, title= %u, %u", reward->achievementId, reward->titleId[0], reward->titleId[1]); + uint32 titleId = reward->titleId[GetPlayer()->GetTeam() == HORDE?0:1]; + if(CharTitlesEntry const* titleEntry = sCharTitlesStore.LookupEntry(titleId)) + GetPlayer()->SetTitle(titleEntry); + + if (reward->itemId) + { + ItemPrototype const *pProto = objmgr.GetItemPrototype( reward->itemId ); + + if(!pProto) + { + GetPlayer()->SendEquipError( EQUIP_ERR_ITEM_NOT_FOUND, NULL, NULL ); + return; + } + + ItemPosCountVec dest; + uint32 no_space = 0; + uint8 msg = GetPlayer()->CanStoreNewItem( NULL_BAG, NULL_SLOT, dest, reward->itemId, 1, &no_space ); + + if( msg != EQUIP_ERR_OK ) + { + GetPlayer()->SendEquipError( msg, NULL, NULL ); + return; + } + Item* pItem = GetPlayer()->StoreNewItem( dest, reward->itemId, true); + + if(!pItem) + { + GetPlayer()->SendEquipError( EQUIP_ERR_ITEM_NOT_FOUND, NULL, NULL ); + return; + } + } + } +} + +void AchievementMgr::SendAllAchievementData() +{ + // since we don't know the exact size of the packed GUIDs this is just an approximation + WorldPacket data(SMSG_ALL_ACHIEVEMENT_DATA, 4*2+m_completedAchievements.size()*4*2+m_completedAchievements.size()*7*4); + BuildAllDataPacket(&data); + GetPlayer()->GetSession()->SendPacket(&data); +} + +void AchievementMgr::SendRespondInspectAchievements(Player* player) +{ + // since we don't know the exact size of the packed GUIDs this is just an approximation + WorldPacket data(SMSG_RESPOND_INSPECT_ACHIEVEMENTS, 4+4*2+m_completedAchievements.size()*4*2+m_completedAchievements.size()*7*4); + data.append(GetPlayer()->GetPackGUID()); + BuildAllDataPacket(&data); + player->GetSession()->SendPacket(&data); +} + +/** + * used by both SMSG_ALL_ACHIEVEMENT_DATA and SMSG_RESPOND_INSPECT_ACHIEVEMENT + */ +void AchievementMgr::BuildAllDataPacket(WorldPacket *data) +{ + for(CompletedAchievementMap::const_iterator iter = m_completedAchievements.begin(); iter!=m_completedAchievements.end(); ++iter) + { + *data << uint32(iter->first); + *data << uint32(secsToTimeBitFields(iter->second.date)); + } + *data << int32(-1); + + for(CriteriaProgressMap::const_iterator iter = m_criteriaProgress.begin(); iter!=m_criteriaProgress.end(); ++iter) + { + *data << uint32(iter->first); + data->appendPackGUID(iter->second.counter); + data->append(GetPlayer()->GetPackGUID()); + *data << uint32(0); + *data << uint32(secsToTimeBitFields(iter->second.date)); + *data << uint32(0); + *data << uint32(0); + } + + *data << int32(-1); +} diff --git a/src/game/AchievementMgr.h b/src/game/AchievementMgr.h new file mode 100644 index 000000000..6392a9fc6 --- /dev/null +++ b/src/game/AchievementMgr.h @@ -0,0 +1,101 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#ifndef __MANGOS_ACHIEVEMENTMGR_H +#define __MANGOS_ACHIEVEMENTMGR_H + +#include "Common.h" +#include "Database/DBCEnums.h" +#include "Database/DBCStores.h" +#include "Database/DatabaseEnv.h" + +#define CRITERIA_CAST_SPELL_REQ_COUNT 46 +#define ACHIEVEMENT_REWARD_COUNT 57 + +struct CriteriaProgress +{ + uint32 counter; + time_t date; + bool changed; +}; + +struct CriteriaCastSpellRequirement +{ + uint32 achievementCriteriaId; + uint32 creatureEntry; + uint8 playerClass; + uint8 playerRace; +}; + +struct AchievementReward +{ + uint32 achievementId; + uint32 titleId[2]; + uint32 itemId; +}; + +struct CompletedAchievementData +{ + time_t date; + bool changed; +}; + +typedef UNORDERED_MAP CriteriaProgressMap; +typedef UNORDERED_MAP CompletedAchievementMap; + +class Unit; +class Player; +class WorldPacket; + +enum AchievementCompletionState +{ + ACHIEVEMENT_COMPLETED_NONE, + ACHIEVEMENT_COMPLETED_COMPLETED_NOT_STORED, + ACHIEVEMENT_COMPLETED_COMPLETED_STORED, +}; + +class AchievementMgr +{ + public: + AchievementMgr(Player* pl); + ~AchievementMgr(); + + void LoadFromDB(QueryResult *achievementResult, QueryResult *criteriaResult); + void SaveToDB(); + void UpdateAchievementCriteria(AchievementCriteriaTypes type, uint32 miscvalue1=0, uint32 miscvalue2=0, Unit *unit=NULL, uint32 time=0); + void CheckAllAchievementCriteria(); + void SendAllAchievementData(); + void SendRespondInspectAchievements(Player* player); + Player* GetPlayer() { return m_player;} + + private: + void SendAchievementEarned(AchievementEntry const* achievement); + void SendCriteriaUpdate(uint32 id, CriteriaProgress const* progress); + void SetCriteriaProgress(AchievementCriteriaEntry const* entry, uint32 newValue, bool relative=false); + void CompletedCriteria(AchievementCriteriaEntry const* entry); + void CompletedAchievement(AchievementEntry const* entry); + bool IsCompletedCriteria(AchievementCriteriaEntry const* entry); + AchievementCompletionState GetAchievementCompletionState(AchievementEntry const* entry); + void BuildAllDataPacket(WorldPacket *data); + + Player* m_player; + CriteriaProgressMap m_criteriaProgress; + CompletedAchievementMap m_completedAchievements; + static const CriteriaCastSpellRequirement criteriaCastSpellRequirements[]; + static const AchievementReward achievementRewards[]; +}; +#endif diff --git a/src/game/ArenaTeam.cpp b/src/game/ArenaTeam.cpp index 72ed8d679..5f1dfdb93 100644 --- a/src/game/ArenaTeam.cpp +++ b/src/game/ArenaTeam.cpp @@ -44,7 +44,7 @@ ArenaTeam::~ArenaTeam() } -bool ArenaTeam::create(uint64 captainGuid, uint32 type, std::string ArenaTeamName) +bool ArenaTeam::Create(uint64 captainGuid, uint32 type, std::string ArenaTeamName) { if(!objmgr.GetPlayer(captainGuid)) // player not exist return false; @@ -67,9 +67,9 @@ bool ArenaTeam::create(uint64 captainGuid, uint32 type, std::string ArenaTeamNam CharacterDatabase.PExecute("DELETE FROM arena_team_member WHERE arenateamid='%u'", Id); CharacterDatabase.PExecute("INSERT INTO arena_team (arenateamid,name,captainguid,type,BackgroundColor,EmblemStyle,EmblemColor,BorderStyle,BorderColor) " "VALUES('%u','%s','%u','%u','%u','%u','%u','%u','%u')", - Id, ArenaTeamName.c_str(), GUID_LOPART(CaptainGuid), Type, BackgroundColor,EmblemStyle,EmblemColor,BorderStyle,BorderColor); + Id, ArenaTeamName.c_str(), GUID_LOPART(CaptainGuid), Type, BackgroundColor, EmblemStyle, EmblemColor, BorderStyle, BorderColor); CharacterDatabase.PExecute("INSERT INTO arena_team_stats (arenateamid, rating, games, wins, played, wins2, rank) VALUES " - "('%u', '%u', '%u', '%u', '%u', '%u', '%u')", Id,stats.rating,stats.games_week,stats.wins_week,stats.games_season,stats.wins_season,stats.rank); + "('%u', '%u', '%u', '%u', '%u', '%u', '%u')", Id, stats.rating, stats.games_week, stats.wins_week, stats.games_season, stats.wins_season, stats.rank); CharacterDatabase.CommitTransaction(); @@ -77,7 +77,7 @@ bool ArenaTeam::create(uint64 captainGuid, uint32 type, std::string ArenaTeamNam return true; } -bool ArenaTeam::AddMember(uint64 PlayerGuid) +bool ArenaTeam::AddMember(const uint64& PlayerGuid) { std::string plName; uint8 plClass; @@ -132,39 +132,23 @@ bool ArenaTeam::AddMember(uint64 PlayerGuid) newmember.personal_rating = 1500; members.push_back(newmember); - CharacterDatabase.PExecute("INSERT INTO arena_team_member (arenateamid,guid) VALUES ('%u', '%u')", Id, GUID_LOPART(newmember.guid)); + CharacterDatabase.PExecute("INSERT INTO arena_team_member (arenateamid, guid, personal_rating) VALUES ('%u', '%u', '%u')", Id, GUID_LOPART(newmember.guid), newmember.personal_rating ); if(pl) { pl->SetInArenaTeam(Id, GetSlot()); pl->SetArenaTeamIdInvited(0); + pl->SetUInt32Value(PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + (GetSlot()*6) + 5, newmember.personal_rating ); // hide promote/remove buttons if(CaptainGuid != PlayerGuid) - pl->SetUInt32Value(PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + 1 + (GetSlot() * 6), 1); - } - else - { - Tokens tokens; - if(Player::LoadValuesArrayFromDB(tokens,PlayerGuid)) - { - Player::SetUInt32ValueInArray(tokens,PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + (GetSlot() * 6), Id); - // hide promote/remove buttons - if(CaptainGuid != PlayerGuid) - Player::SetUInt32ValueInArray(tokens,PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + 1 + (GetSlot() * 6), 1); - - Player::SaveValuesArrayInDB(tokens,PlayerGuid); - } + pl->SetUInt32Value(PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + (GetSlot() * 6) + 1, 1); } return true; } bool ArenaTeam::LoadArenaTeamFromDB(uint32 ArenaTeamId) { - LoadStatsFromDB(ArenaTeamId); - LoadMembersFromDB(ArenaTeamId); - - // 0 1 2 3 4 5 6 7 8 QueryResult *result = CharacterDatabase.PQuery("SELECT arenateamid,name,captainguid,type,BackgroundColor,EmblemStyle,EmblemColor,BorderStyle,BorderColor FROM arena_team WHERE arenateamid = '%u'", ArenaTeamId); if(!result) @@ -184,6 +168,21 @@ bool ArenaTeam::LoadArenaTeamFromDB(uint32 ArenaTeamId) delete result; + // only load here, so additional checks can be made + LoadStatsFromDB(ArenaTeamId); + LoadMembersFromDB(ArenaTeamId); + + if(Empty()) + { + // arena team is empty, delete from db + CharacterDatabase.BeginTransaction(); + CharacterDatabase.PExecute("DELETE FROM arena_team WHERE arenateamid = '%u'", ArenaTeamId); + CharacterDatabase.PExecute("DELETE FROM arena_team_member WHERE arenateamid = '%u'", ArenaTeamId); + CharacterDatabase.PExecute("DELETE FROM arena_team_stats WHERE arenateamid = '%u'", ArenaTeamId); + CharacterDatabase.CommitTransaction(); + return false; + } + return true; } @@ -209,49 +208,37 @@ void ArenaTeam::LoadStatsFromDB(uint32 ArenaTeamId) void ArenaTeam::LoadMembersFromDB(uint32 ArenaTeamId) { - Field *fields; - - QueryResult *result = CharacterDatabase.PQuery("SELECT guid,played_week,wons_week,played_season,wons_season FROM arena_team_member WHERE arenateamid = '%u'", ArenaTeamId); + // 0 1 2 3 4 5 6 7 + QueryResult *result = CharacterDatabase.PQuery("SELECT member.guid,played_week,wons_week,played_season,wons_season,personal_rating,name,class " + "FROM arena_team_member member " + "INNER JOIN characters chars on member.guid = chars.guid " + "WHERE member.arenateamid = '%u'", ArenaTeamId); if(!result) return; do { - fields = result->Fetch(); + Field *fields = result->Fetch(); ArenaTeamMember newmember; newmember.guid = MAKE_NEW_GUID(fields[0].GetUInt32(), 0, HIGHGUID_PLAYER); - LoadPlayerStats(&newmember); newmember.games_week = fields[1].GetUInt32(); newmember.wins_week = fields[2].GetUInt32(); newmember.games_season = fields[3].GetUInt32(); newmember.wins_season = fields[4].GetUInt32(); + newmember.personal_rating = fields[5].GetUInt32(); + newmember.name = fields[6].GetCppString(); + newmember.Class = fields[7].GetUInt8(); members.push_back(newmember); }while( result->NextRow() ); delete result; } -void ArenaTeam::LoadPlayerStats(ArenaTeamMember *member) -{ - Field *fields; - - QueryResult *result = CharacterDatabase.PQuery("SELECT name,class FROM characters WHERE guid = '%u'", GUID_LOPART(member->guid)); - if(!result) - return; - fields = result->Fetch(); - member->name = fields[0].GetCppString(); - member->Class = fields[1].GetUInt8(); - - delete result; -} - -void ArenaTeam::SetCaptain(uint64 guid) +void ArenaTeam::SetCaptain(const uint64& guid) { // disable remove/promote buttons Player *oldcaptain = objmgr.GetPlayer(GetCaptain()); if(oldcaptain) oldcaptain->SetUInt32Value(PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + 1 + (GetSlot() * 6), 1); - else - Player::SetUInt32ValueInDB(PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + 1 + (GetSlot() * 6), 1, GetCaptain()); // set new captain CaptainGuid = guid; @@ -263,14 +250,11 @@ void ArenaTeam::SetCaptain(uint64 guid) Player *newcaptain = objmgr.GetPlayer(guid); if(newcaptain) newcaptain->SetUInt32Value(PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + 1 + (GetSlot() * 6), 0); - else - Player::SetUInt32ValueInDB(PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + 1 + (GetSlot() * 6), 0, guid); } void ArenaTeam::DelMember(uint64 guid) { - MemberList::iterator itr; - for (itr = members.begin(); itr != members.end(); itr++) + for (MemberList::iterator itr = members.begin(); itr != members.end(); ++itr) { if (itr->guid == guid) { @@ -280,17 +264,19 @@ void ArenaTeam::DelMember(uint64 guid) } Player *player = objmgr.GetPlayer(guid); + if(player) { player->SetInArenaTeam(0, GetSlot()); player->GetSession()->SendArenaTeamCommandResult(ERR_ARENA_TEAM_QUIT_S, GetName(), "", 0); - } - else - { - Player::SetUInt32ValueInDB(PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + (GetSlot() * 6), 0, guid); + // delete all info regarding this team + for(int i = 0; i < 6; ++i) + { + player->SetUInt32Value(PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + (GetSlot() * 6) + i, 0); + } } - CharacterDatabase.PExecute("DELETE FROM arena_team_member WHERE guid = '%u'", GUID_LOPART(guid)); + CharacterDatabase.PExecute("DELETE FROM arena_team_member WHERE arenateamid = '%u' AND guid = '%u'", GetId(), GUID_LOPART(guid)); } void ArenaTeam::Disband(WorldSession *session) @@ -300,23 +286,15 @@ void ArenaTeam::Disband(WorldSession *session) session->BuildArenaTeamEventPacket(&data, ERR_ARENA_TEAM_DISBANDED_S, 2, session->GetPlayerName(), GetName(), ""); BroadcastPacket(&data); - uint32 count = members.size(); - uint64 *memberGuids = new uint64[count]; - - MemberList::iterator itr; - uint32 i=0; - for(itr = members.begin(); itr != members.end(); itr++) + while (!members.empty()) { - memberGuids[i] = itr->guid; - ++i; + // Removing from members is done in DelMember. + DelMember(members.front().guid); } - for(uint32 j = 0; j < count; j++) - DelMember(memberGuids[j]); - delete[] memberGuids; - CharacterDatabase.BeginTransaction(); CharacterDatabase.PExecute("DELETE FROM arena_team WHERE arenateamid = '%u'", Id); + CharacterDatabase.PExecute("DELETE FROM arena_team_member WHERE arenateamid = '%u'", Id); //< this should be alredy done by calling DelMember(memberGuids[j]); for each member CharacterDatabase.PExecute("DELETE FROM arena_team_stats WHERE arenateamid = '%u'", Id); CharacterDatabase.CommitTransaction(); objmgr.RemoveArenaTeam(this); @@ -334,34 +312,18 @@ void ArenaTeam::Roster(WorldSession *session) for (MemberList::iterator itr = members.begin(); itr != members.end(); ++itr) { pl = objmgr.GetPlayer(itr->guid); - if(pl) - { - data << uint64(pl->GetGUID()); // guid - data << uint8(1); // online flag - data << pl->GetName(); // member name - data << uint32(itr->guid == GetCaptain() ? 0 : 1);// unknown - data << uint8(pl->getLevel()); // unknown, probably level - data << uint8(pl->getClass()); // class - data << uint32(itr->games_week); // played this week - data << uint32(itr->wins_week); // wins this week - data << uint32(itr->games_season); // played this season - data << uint32(itr->wins_season); // wins this season - data << uint32(itr->personal_rating); // personal rating - } - else - { - data << uint64(itr->guid); // guid - data << uint8(0); // online flag - data << itr->name; // member name - data << uint32(itr->guid == GetCaptain() ? 0 : 1);// unknown - data << uint8(0); // unknown, level? - data << uint8(itr->Class); // class - data << uint32(itr->games_week); // played this week - data << uint32(itr->wins_week); // wins this week - data << uint32(itr->games_season); // played this season - data << uint32(itr->wins_season); // wins this season - data << uint32(itr->personal_rating); // personal rating - } + + data << uint64(itr->guid); // guid + data << uint8((pl ? 1 : 0)); // online flag + data << itr->name; // member name + data << uint32((itr->guid == GetCaptain() ? 0 : 1));// captain flag 0 captain 1 member + data << uint8((pl ? pl->getLevel() : 0)); // unknown, level? + data << uint8(itr->Class); // class + data << uint32(itr->games_week); // played this week + data << uint32(itr->wins_week); // wins this week + data << uint32(itr->games_season); // played this season + data << uint32(itr->wins_season); // wins this season + data << uint32(itr->personal_rating); // personal rating } session->SendPacket(&data); sLog.outDebug("WORLD: Sent SMSG_ARENA_TEAM_ROSTER"); @@ -395,6 +357,18 @@ void ArenaTeam::Stats(WorldSession *session) session->SendPacket(&data); } +void ArenaTeam::NotifyStatsChanged() +{ + // this is called after a rated match ended + // updates arena team stats for every member of the team (not only the ones who participated!) + for(MemberList::iterator itr = members.begin(); itr != members.end(); ++itr) + { + Player * plr = objmgr.GetPlayer(itr->guid); + if(plr) + Stats(plr->GetSession()); + } +} + void ArenaTeam::InspectStats(WorldSession *session, uint64 guid) { ArenaTeamMember* member = GetMember(guid); @@ -408,8 +382,8 @@ void ArenaTeam::InspectStats(WorldSession *session, uint64 guid) data << uint32(stats.rating); // rating data << uint32(stats.games_season); // season played data << uint32(stats.wins_season); // season wins - data << member->games_season; // played (count of all games, that the inspected member participated...) - data << member->personal_rating; // personal rating + data << uint32(member->games_season); // played (count of all games, that the inspected member participated...) + data << uint32(member->personal_rating); // personal rating session->SendPacket(&data); } @@ -458,18 +432,6 @@ void ArenaTeam::SetStats(uint32 stat_type, uint32 value) } } -uint8 ArenaTeam::GetSlot() const -{ - uint8 slot = GetSlotByType(GetType()); - if(slot >= MAX_ARENA_SLOT) - { - sLog.outError("Unknown arena team type %u for arena team %u", uint32(GetType()), GetId()); - return 0; // better return existed slot to prevent untelated data curruption - } - - return slot; -} - void ArenaTeam::BroadcastPacket(WorldPacket *packet) { for (MemberList::iterator itr = members.begin(); itr != members.end(); ++itr) @@ -490,18 +452,184 @@ uint8 ArenaTeam::GetSlotByType( uint32 type ) default: break; } + sLog.outError("FATAL: Unknown arena team type %u for some arena team", type); return 0xFF; } -bool ArenaTeam::HaveMember( uint64 guid ) const +bool ArenaTeam::HaveMember( const uint64& guid ) const { for (MemberList::const_iterator itr = members.begin(); itr != members.end(); ++itr) - if(itr->guid==guid) + if(itr->guid == guid) return true; return false; } +uint32 ArenaTeam::GetPoints(uint32 MemberRating) +{ + // returns how many points would be awarded with this team type with this rating + float points; + + uint32 rating = MemberRating + 150 < stats.rating ? MemberRating : stats.rating; + + if(rating<=1500) + points = (float)rating * 0.22f + 14.0f; + else + points = 1511.26f / (1.0f + 1639.28f * exp(-0.00412f * (float)rating)); + + // type penalties for <5v5 teams + if(Type == ARENA_TEAM_2v2) + points *= 0.76f; + else if(Type == ARENA_TEAM_3v3) + points *= 0.88f; + + return (uint32) points; +} + +float ArenaTeam::GetChanceAgainst(uint32 own_rating, uint32 enemy_rating) +{ + // returns the chance to win against a team with the given rating, used in the rating adjustment calculation + // ELO system + return 1.0f/(1.0f+exp(log(10.0f)*(float)((float)enemy_rating - (float)own_rating)/400.0f)); +} + +int32 ArenaTeam::WonAgainst(uint32 againstRating) +{ + // called when the team has won + //'chance' calculation - to beat the opponent + float chance = GetChanceAgainst(stats.rating,againstRating); + // calculate the rating modification (ELO system with k=32) + int32 mod = (int32)floor(32.0f * (1.0f - chance)); + // modify the team stats accordingly + stats.rating += mod; + stats.games_week += 1; + stats.wins_week += 1; + stats.games_season += 1; + stats.wins_season += 1; + //update team's rank + stats.rank = 1; + ObjectMgr::ArenaTeamMap::iterator i = objmgr.GetArenaTeamMapBegin(); + for ( ; i != objmgr.GetArenaTeamMapEnd(); ++i) + { + if (i->second->GetType() == this->Type && i->second->GetStats().rating > stats.rating) + ++stats.rank; + } + + // return the rating change, used to display it on the results screen + return mod; +} + +int32 ArenaTeam::LostAgainst(uint32 againstRating) +{ + // called when the team has lost + //'chance' calculation - to loose to the opponent + float chance = GetChanceAgainst(stats.rating,againstRating); + // calculate the rating modification (ELO system with k=32) + int32 mod = (int32)ceil(32.0f * (0.0f - chance)); + // modify the team stats accordingly + stats.rating += mod; + stats.games_week += 1; + stats.games_season += 1; + //update team's rank + + stats.rank = 1; + ObjectMgr::ArenaTeamMap::iterator i = objmgr.GetArenaTeamMapBegin(); + for ( ; i != objmgr.GetArenaTeamMapEnd(); ++i) + { + if (i->second->GetType() == this->Type && i->second->GetStats().rating > stats.rating) + ++stats.rank; + } + + // return the rating change, used to display it on the results screen + return mod; +} + +void ArenaTeam::MemberLost(Player * plr, uint32 againstRating) +{ + // called for each participant of a match after losing + for(MemberList::iterator itr = members.begin(); itr != members.end(); ++itr) + { + if(itr->guid == plr->GetGUID()) + { + // update personal rating + float chance = GetChanceAgainst(itr->personal_rating, againstRating); + int32 mod = (int32)ceil(32.0f * (0.0f - chance)); + itr->ModifyPersonalRating(plr, mod, GetSlot()); + // update personal played stats + itr->games_week +=1; + itr->games_season +=1; + // update the unit fields + plr->SetUInt32Value(PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + 6 * GetSlot() + 2, itr->games_week); + plr->SetUInt32Value(PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + 6 * GetSlot() + 3, itr->games_season); + return; + } + } +} + +void ArenaTeam::MemberWon(Player * plr, uint32 againstRating) +{ + // called for each participant after winning a match + for(MemberList::iterator itr = members.begin(); itr != members.end(); ++itr) + { + if(itr->guid == plr->GetGUID()) + { + // update personal rating + float chance = GetChanceAgainst(itr->personal_rating, againstRating); + int32 mod = (int32)floor(32.0f * (1.0f - chance)); + itr->ModifyPersonalRating(plr, mod, GetSlot()); + // update personal stats + itr->games_week +=1; + itr->games_season +=1; + itr->wins_season += 1; + itr->wins_week += 1; + // update unit fields + plr->SetUInt32Value(PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + 6 * GetSlot() + 2, itr->games_week); + plr->SetUInt32Value(PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + 6 * GetSlot() + 3, itr->games_season); + return; + } + } +} + +void ArenaTeam::UpdateArenaPointsHelper(std::map& PlayerPoints) +{ + // called after a match has ended and the stats are already modified + // helper function for arena point distribution (this way, when distributing, no actual calculation is required, just a few comparisons) + // 10 played games per week is a minimum + if (stats.games_week < 10) + return; + // to get points, a player has to participate in at least 30% of the matches + uint32 min_plays = (uint32) ceil(stats.games_week * 0.3); + for(MemberList::iterator itr = members.begin(); itr != members.end(); ++itr) + { + // the player participated in enough games, update his points + uint32 points_to_add = 0; + if (itr->games_week >= min_plays) + points_to_add = GetPoints(itr->personal_rating); + // OBSOLETE : CharacterDatabase.PExecute("UPDATE arena_team_member SET points_to_add = '%u' WHERE arenateamid = '%u' AND guid = '%u'", points_to_add, Id, itr->guid); + + std::map::iterator plr_itr = PlayerPoints.find(GUID_LOPART(itr->guid)); + if (plr_itr != PlayerPoints.end()) + { + //check if there is already more points + if (plr_itr->second < points_to_add) + PlayerPoints[GUID_LOPART(itr->guid)] = points_to_add; + } + else + PlayerPoints[GUID_LOPART(itr->guid)] = points_to_add; + } +} + +void ArenaTeam::SaveToDB() +{ + // save team and member stats to db + // called after a match has ended, or when calculating arena_points + CharacterDatabase.PExecute("UPDATE arena_team_stats SET rating = '%u',games = '%u',played = '%u',rank = '%u',wins = '%u',wins2 = '%u' WHERE arenateamid = '%u'", stats.rating, stats.games_week, stats.games_season, stats.rank, stats.wins_week, stats.wins_season, GetId()); + for(MemberList::iterator itr = members.begin(); itr != members.end(); ++itr) + { + CharacterDatabase.PExecute("UPDATE arena_team_member SET played_week = '%u', wons_week = '%u', played_season = '%u', wons_season = '%u', personal_rating = '%u' WHERE arenateamid = '%u' AND guid = '%u'", itr->games_week, itr->wins_week, itr->games_season, itr->wins_season, itr->personal_rating, Id, itr->guid); + } +} + void ArenaTeam::FinishWeek() { stats.games_week = 0; // played this week @@ -519,18 +647,18 @@ arenateam fields (id from 2.3.3 client): 1415 - 0=captain, 1=member 1416 - played this week 1417 - played this season -1418 - unk +1418 - unk - rank? 1419 - personal arena rating 1420 - arena team id 3v3 1421 - 0=captain, 1=member 1422 - played this week 1423 - played this season -1424 - unk +1424 - unk - rank? 1425 - personal arena rating 1426 - arena team id 5v5 1427 - 0=captain, 1=member 1428 - played this week 1429 - played this season -1430 - unk +1430 - unk - rank? 1431 - personal arena rating */ diff --git a/src/game/ArenaTeam.h b/src/game/ArenaTeam.h index 43adca888..ba19c53f9 100644 --- a/src/game/ArenaTeam.h +++ b/src/game/ArenaTeam.h @@ -43,7 +43,9 @@ enum ArenaTeamCommandErrors ERR_ARENA_TEAM_PLAYER_NOT_IN_TEAM = 0x09, ERR_ARENA_TEAM_PLAYER_NOT_IN_TEAM_SS = 0x0A, ERR_ARENA_TEAM_PLAYER_NOT_FOUND_S = 0x0B, - ERR_ARENA_TEAM_NOT_ALLIED = 0x0C + ERR_ARENA_TEAM_NOT_ALLIED = 0x0C, + ERR_ARENA_TEAM_PLAYER_TO_LOW = 0x15, + ERR_ARENA_TEAM_FULL = 0x16 }; enum ArenaTeamEvents @@ -85,14 +87,22 @@ struct ArenaTeamMember { uint64 guid; std::string name; - //uint32 unk2; - //uint8 unk1; uint8 Class; uint32 games_week; uint32 wins_week; uint32 games_season; uint32 wins_season; uint32 personal_rating; + + void ModifyPersonalRating(Player* plr, int32 mod, uint32 slot) + { + if (personal_rating + mod < 0) + personal_rating = 0; + else + personal_rating += mod; + if(plr) + plr->SetUInt32Value(PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + (slot*6) + 5, personal_rating); + } }; struct ArenaTeamStats @@ -113,58 +123,78 @@ class ArenaTeam ArenaTeam(); ~ArenaTeam(); - bool create(uint64 CaptainGuid, uint32 type, std::string ArenaTeamName); + bool Create(uint64 CaptainGuid, uint32 type, std::string ArenaTeamName); void Disband(WorldSession *session); typedef std::list MemberList; - uint32 GetId() const { return Id; } - uint32 GetType() const { return Type; } - uint8 GetSlot() const; + uint32 GetId() const { return Id; } + uint32 GetType() const { return Type; } + uint8 GetSlot() const { return GetSlotByType(GetType()); } static uint8 GetSlotByType(uint32 type); - const uint64& GetCaptain() const { return CaptainGuid; } - std::string GetName() const { return Name; } + const uint64& GetCaptain() const { return CaptainGuid; } + std::string GetName() const { return Name; } const ArenaTeamStats& GetStats() const { return stats; } void SetStats(uint32 stat_type, uint32 value); - uint32 GetRating() const { return stats.rating; } + uint32 GetRating() const { return stats.rating; } - uint32 GetEmblemStyle() const { return EmblemStyle; } - uint32 GetEmblemColor() const { return EmblemColor; } - uint32 GetBorderStyle() const { return BorderStyle; } - uint32 GetBorderColor() const { return BorderColor; } + uint32 GetEmblemStyle() const { return EmblemStyle; } + uint32 GetEmblemColor() const { return EmblemColor; } + uint32 GetBorderStyle() const { return BorderStyle; } + uint32 GetBorderColor() const { return BorderColor; } uint32 GetBackgroundColor() const { return BackgroundColor; } - void SetCaptain(uint64 guid); - bool AddMember(uint64 PlayerGuid); + void SetCaptain(const uint64& guid); + bool AddMember(const uint64& PlayerGuid); + + // Shouldn't be const uint64& ed, because than can reference guid from members on Disband + // and this method removes given record from list. So invalid reference can happen. void DelMember(uint64 guid); void SetEmblem(uint32 backgroundColor, uint32 emblemStyle, uint32 emblemColor, uint32 borderStyle, uint32 borderColor); - uint32 GetMembersSize() const { return members.size(); } - MemberList::iterator membersbegin(){ return members.begin(); } - MemberList::iterator membersEnd(){ return members.end(); } - bool HaveMember(uint64 guid) const; - ArenaTeamMember* GetMember(uint64 guid) + size_t GetMembersSize() const { return members.size(); } + bool Empty() const { return members.empty(); } + MemberList::iterator membersBegin() { return members.begin(); } + MemberList::iterator membersEnd() { return members.end(); } + bool HaveMember(const uint64& guid) const; + + ArenaTeamMember* GetMember(const uint64& guid) { for (MemberList::iterator itr = members.begin(); itr != members.end(); ++itr) - if(itr->guid==guid) + if(itr->guid == guid) return &(*itr); return NULL; } - ArenaTeamMember* GetMember(std::string& name) + + ArenaTeamMember* GetMember(const std::string& name) { for (MemberList::iterator itr = members.begin(); itr != members.end(); ++itr) - if(itr->name==name) + if(itr->name == name) return &(*itr); return NULL; } + bool IsFighting() const + { + for (MemberList::const_iterator itr = members.begin(); itr != members.end(); ++itr) + { + if (Player *p = objmgr.GetPlayer(itr->guid)) + { + if (p->GetMap()->IsBattleArena()) + return true; + } + } + return false; + } + bool LoadArenaTeamFromDB(uint32 ArenaTeamId); void LoadMembersFromDB(uint32 ArenaTeamId); void LoadStatsFromDB(uint32 ArenaTeamId); - void LoadPlayerStats(ArenaTeamMember* member); + + void SaveToDB(); void BroadcastPacket(WorldPacket *packet); @@ -173,6 +203,17 @@ class ArenaTeam void Stats(WorldSession *session); void InspectStats(WorldSession *session, uint64 guid); + uint32 GetPoints(uint32 MemberRating); + float GetChanceAgainst(uint32 own_rating, uint32 enemy_rating); + int32 WonAgainst(uint32 againstRating); + void MemberWon(Player * plr, uint32 againstRating); + int32 LostAgainst(uint32 againstRating); + void MemberLost(Player * plr, uint32 againstRating); + + void UpdateArenaPointsHelper(std::map & PlayerPoints); + + void NotifyStatsChanged(); + void FinishWeek(); protected: diff --git a/src/game/ArenaTeamHandler.cpp b/src/game/ArenaTeamHandler.cpp index 7cab8d085..d0e095237 100644 --- a/src/game/ArenaTeamHandler.cpp +++ b/src/game/ArenaTeamHandler.cpp @@ -30,7 +30,6 @@ void WorldSession::HandleInspectArenaStatsOpcode(WorldPacket & recv_data) { sLog.outDebug("MSG_INSPECT_ARENA_TEAMS"); - //recv_data.hexlike(); CHECK_PACKET_SIZE(recv_data, 8); @@ -54,7 +53,6 @@ void WorldSession::HandleInspectArenaStatsOpcode(WorldPacket & recv_data) void WorldSession::HandleArenaTeamQueryOpcode(WorldPacket & recv_data) { sLog.outDebug( "WORLD: Received CMSG_ARENA_TEAM_QUERY" ); - //recv_data.hexlike(); CHECK_PACKET_SIZE(recv_data, 4); @@ -72,7 +70,6 @@ void WorldSession::HandleArenaTeamQueryOpcode(WorldPacket & recv_data) void WorldSession::HandleArenaTeamRosterOpcode(WorldPacket & recv_data) { sLog.outDebug( "WORLD: Received CMSG_ARENA_TEAM_ROSTER" ); - //recv_data.hexlike(); CHECK_PACKET_SIZE(recv_data, 4); @@ -89,7 +86,6 @@ void WorldSession::HandleArenaTeamRosterOpcode(WorldPacket & recv_data) void WorldSession::HandleArenaTeamAddMemberOpcode(WorldPacket & recv_data) { sLog.outDebug("CMSG_ARENA_TEAM_ADD_MEMBER"); - //recv_data.hexlike(); CHECK_PACKET_SIZE(recv_data, 4+1); @@ -110,15 +106,13 @@ void WorldSession::HandleArenaTeamAddMemberOpcode(WorldPacket & recv_data) if(!player) { - SendArenaTeamCommandResult(ERR_ARENA_TEAM_INVITE_SS, "", Invitedname, ERR_ARENA_TEAM_PLAYER_NOT_FOUND_S); + SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, "", Invitedname, ERR_ARENA_TEAM_PLAYER_NOT_FOUND_S); return; } if(player->getLevel() < sWorld.getConfig(CONFIG_MAX_PLAYER_LEVEL)) { - //SendArenaTeamCommandResult(ARENA_TEAM_INVITE_SS,"",Invitedname,ARENA_TEAM_PLAYER_NOT_FOUND_S); - // can't find related opcode - SendNotification(LANG_HIS_ARENA_LEVEL_REQ_ERROR, player->GetName()); + SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, "", player->GetName(), ERR_ARENA_TEAM_PLAYER_TO_LOW); return; } @@ -141,21 +135,19 @@ void WorldSession::HandleArenaTeamAddMemberOpcode(WorldPacket & recv_data) if(player->GetArenaTeamId(arenateam->GetSlot())) { - SendArenaTeamCommandResult(ERR_ARENA_TEAM_INVITE_SS, player->GetName(), "", ERR_ALREADY_IN_ARENA_TEAM_S); + SendArenaTeamCommandResult(ERR_ARENA_TEAM_INVITE_SS, "", player->GetName(), ERR_ALREADY_IN_ARENA_TEAM_S); return; } if(player->GetArenaTeamIdInvited()) { - SendArenaTeamCommandResult(ERR_ARENA_TEAM_INVITE_SS, player->GetName(), "", ERR_ALREADY_INVITED_TO_ARENA_TEAM_S); + SendArenaTeamCommandResult(ERR_ARENA_TEAM_INVITE_SS, "", player->GetName(), ERR_ALREADY_INVITED_TO_ARENA_TEAM_S); return; } if(arenateam->GetMembersSize() >= arenateam->GetType() * 2) { - // should send an "arena team is full" or the likes message, I just don't know the proper values so... ERR_INTERNAL -// SendArenaTeamCommandResult(ERR_ARENA_TEAM_INVITE_SS, "", "", ERR_ARENA_TEAM_INTERNAL); - SendNotification(LANG_YOUR_ARENA_TEAM_FULL, player->GetName()); + SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S,arenateam->GetName(),"",ERR_ARENA_TEAM_FULL); return; } @@ -177,23 +169,25 @@ void WorldSession::HandleArenaTeamInviteAcceptOpcode(WorldPacket & /*recv_data*/ ArenaTeam *at = objmgr.GetArenaTeamById(_player->GetArenaTeamIdInvited()); if(!at) + return; + + if(_player->GetArenaTeamIdFromDB(_player->GetGUIDLow(), at->GetType())) { - // arena team not exist + SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S,"","",ERR_ALREADY_IN_ARENA_TEAM); // already in arena team that size return; } - if(_player->GetArenaTeamId(at->GetSlot())) - { - // already in arena team that size - return; - } - - // not let enemies sign petition if (!sWorld.getConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_GUILD) && _player->GetTeam() != objmgr.GetPlayerTeamByGUID(at->GetCaptain())) + { + SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S,"","",ERR_ARENA_TEAM_NOT_ALLIED);// not let enemies sign petition return; + } if(!at->AddMember(_player->GetGUID())) + { + SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S,"","",ERR_ARENA_TEAM_INTERNAL);// arena team not found return; + } // event WorldPacket data; @@ -211,7 +205,6 @@ void WorldSession::HandleArenaTeamInviteDeclineOpcode(WorldPacket & /*recv_data* void WorldSession::HandleArenaTeamLeaveOpcode(WorldPacket & recv_data) { sLog.outDebug("CMSG_ARENA_TEAM_LEAVE"); - //recv_data.hexlike(); CHECK_PACKET_SIZE(recv_data, 4); @@ -220,10 +213,7 @@ void WorldSession::HandleArenaTeamLeaveOpcode(WorldPacket & recv_data) ArenaTeam *at = objmgr.GetArenaTeamById(ArenaTeamId); if(!at) - { - // send command result return; - } if(_player->GetGUID() == at->GetCaptain() && at->GetMembersSize() > 1) { // check for correctness @@ -245,13 +235,13 @@ void WorldSession::HandleArenaTeamLeaveOpcode(WorldPacket & recv_data) BuildArenaTeamEventPacket(&data, ERR_ARENA_TEAM_LEAVE_SS, 2, _player->GetName(), at->GetName(), ""); at->BroadcastPacket(&data); - //SendArenaTeamCommandResult(ERR_ARENA_TEAM_QUIT_S, at->GetName(), "", 0); + //send you are no longer member of team + SendArenaTeamCommandResult(ERR_ARENA_TEAM_QUIT_S, at->GetName(), "", 0); } void WorldSession::HandleArenaTeamDisbandOpcode(WorldPacket & recv_data) { sLog.outDebug("CMSG_ARENA_TEAM_DISBAND"); - //recv_data.hexlike(); CHECK_PACKET_SIZE(recv_data, 4); @@ -260,16 +250,13 @@ void WorldSession::HandleArenaTeamDisbandOpcode(WorldPacket & recv_data) ArenaTeam *at = objmgr.GetArenaTeamById(ArenaTeamId); if(!at) - { - // arena team not found return; - } if(at->GetCaptain() != _player->GetGUID()) - { - SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, "", "", ERR_ARENA_TEAM_PERMISSIONS); return; - } + + if (at->IsFighting()) + return; at->Disband(this); delete at; @@ -278,7 +265,6 @@ void WorldSession::HandleArenaTeamDisbandOpcode(WorldPacket & recv_data) void WorldSession::HandleArenaTeamRemoveFromTeamOpcode(WorldPacket & recv_data) { sLog.outDebug("CMSG_ARENA_TEAM_REMOVE_FROM_TEAM"); - //recv_data.hexlike(); CHECK_PACKET_SIZE(recv_data, 4+1); @@ -303,11 +289,14 @@ void WorldSession::HandleArenaTeamRemoveFromTeamOpcode(WorldPacket & recv_data) ArenaTeamMember* member = at->GetMember(name); if(!member) // member not found + { + SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, "", name, ERR_ARENA_TEAM_PLAYER_NOT_FOUND_S); return; + } if(at->GetCaptain() == member->guid) { - SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, "", "", ERR_ARENA_TEAM_LEADER_LEAVE_S); + SendArenaTeamCommandResult(ERR_ARENA_TEAM_QUIT_S, "", "", ERR_ARENA_TEAM_LEADER_LEAVE_S); return; } @@ -322,7 +311,6 @@ void WorldSession::HandleArenaTeamRemoveFromTeamOpcode(WorldPacket & recv_data) void WorldSession::HandleArenaTeamPromoteToCaptainOpcode(WorldPacket & recv_data) { sLog.outDebug("CMSG_ARENA_TEAM_PROMOTE_TO_CAPTAIN"); - //recv_data.hexlike(); CHECK_PACKET_SIZE(recv_data, 4+1); @@ -347,7 +335,10 @@ void WorldSession::HandleArenaTeamPromoteToCaptainOpcode(WorldPacket & recv_data ArenaTeamMember* member = at->GetMember(name); if(!member) // member not found + { + SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, "", name, ERR_ARENA_TEAM_PLAYER_NOT_FOUND_S); return; + } if(at->GetCaptain() == member->guid) // target player already captain return; @@ -360,17 +351,17 @@ void WorldSession::HandleArenaTeamPromoteToCaptainOpcode(WorldPacket & recv_data at->BroadcastPacket(&data); } -void WorldSession::SendArenaTeamCommandResult(uint32 unk1, std::string str1, std::string str2, uint32 unk3) +void WorldSession::SendArenaTeamCommandResult(uint32 team_action, const std::string& team, const std::string& player, uint32 error_id) { - WorldPacket data(SMSG_ARENA_TEAM_COMMAND_RESULT, 4+str1.length()+1+str2.length()+1+4); - data << unk1; - data << str1; - data << str2; - data << unk3; + WorldPacket data(SMSG_ARENA_TEAM_COMMAND_RESULT, 4+team.length()+1+player.length()+1+4); + data << team_action; + data << team; + data << player; + data << error_id; SendPacket(&data); } -void WorldSession::BuildArenaTeamEventPacket(WorldPacket *data, uint8 eventid, uint8 str_count, std::string str1, std::string str2, std::string str3) +void WorldSession::BuildArenaTeamEventPacket(WorldPacket *data, uint8 eventid, uint8 str_count, const std::string& str1, const std::string& str2, const std::string& str3) { data->Initialize(SMSG_ARENA_TEAM_EVENT, 1+1+1); *data << eventid; diff --git a/src/game/AuctionHouse.cpp b/src/game/AuctionHouse.cpp index a674aefb8..8ec7d402d 100644 --- a/src/game/AuctionHouse.cpp +++ b/src/game/AuctionHouse.cpp @@ -365,10 +365,15 @@ void WorldSession::HandleAuctionPlaceBid( WorldPacket & recv_data ) return; } - if (price < (auction->bid + objmgr.GetAuctionOutBid(auction->bid))) + // cheating + if(price <= auction->bid) + return; + + // price too low for next bid if not buyout + if ((price < auction->buyout || auction->buyout == 0) && + price < auction->bid + objmgr.GetAuctionOutBid(auction->bid)) { //auction has already higher bid, client tests it! - //SendAuctionCommandResult(auction->auctionId, AUCTION_PLACE_BID, ???); return; } @@ -745,3 +750,23 @@ void WorldSession::HandleAuctionListItems( WorldPacket & recv_data ) data << (uint32) 300; // unk 2.3.0 const? SendPacket(&data); } + +void WorldSession::HandleAuctionListPendingSales( WorldPacket & recv_data ) +{ + sLog.outDebug("CMSG_AUCTION_LIST_PENDING_SALES"); + recv_data.hexlike(); + + uint32 count = 0; + + WorldPacket data(SMSG_AUCTION_LIST_PENDING_SALES, 4); + data << uint32(count); // count + /*for(uint32 i = 0; i < count; ++i) + { + data << ""; // string + data << ""; // string + data << uint32(0); + data << uint32(0); + data << float(0); + }*/ + SendPacket(&data); +} diff --git a/src/game/Bag.cpp b/src/game/Bag.cpp index cd6c4d69a..e0919ce36 100644 --- a/src/game/Bag.cpp +++ b/src/game/Bag.cpp @@ -32,7 +32,7 @@ Bag::Bag( ): Item() m_valuesCount = CONTAINER_END; - memset(m_bagslot, 0, sizeof(Item *) * MAX_BAG_SIZE); // Maximum 20 Slots + memset(m_bagslot, 0, sizeof(Item *) * MAX_BAG_SIZE); } Bag::~Bag() diff --git a/src/game/BattleGround.cpp b/src/game/BattleGround.cpp index 1a3d70fb6..ebb95536e 100644 --- a/src/game/BattleGround.cpp +++ b/src/game/BattleGround.cpp @@ -24,6 +24,7 @@ #include "Language.h" #include "Chat.h" #include "SpellAuras.h" +#include "ArenaTeam.h" #include "World.h" #include "Util.h" @@ -47,6 +48,8 @@ BattleGround::BattleGround() m_Name = ""; m_LevelMin = 0; m_LevelMax = 0; + m_InBGFreeSlotQueue = false; + m_SetDeleteThis = false; m_MaxPlayersPerTeam = 0; m_MaxPlayers = 0; @@ -67,21 +70,54 @@ BattleGround::BattleGround() m_TeamStartLocO[BG_TEAM_ALLIANCE] = 0; m_TeamStartLocO[BG_TEAM_HORDE] = 0; + m_ArenaTeamIds[BG_TEAM_ALLIANCE] = 0; + m_ArenaTeamIds[BG_TEAM_HORDE] = 0; + + m_ArenaTeamRatingChanges[BG_TEAM_ALLIANCE] = 0; + m_ArenaTeamRatingChanges[BG_TEAM_HORDE] = 0; + m_BgRaids[BG_TEAM_ALLIANCE] = NULL; m_BgRaids[BG_TEAM_HORDE] = NULL; m_PlayersCount[BG_TEAM_ALLIANCE] = 0; m_PlayersCount[BG_TEAM_HORDE] = 0; + + m_PrematureCountDown = false; + m_PrematureCountDown = 0; } BattleGround::~BattleGround() { + // remove objects and creatures + // (this is done automatically in mapmanager update, when the instance is reset after the reset time) + int size = m_BgCreatures.size(); + for(int i = 0; i < size; ++i) + { + DelCreature(i); + } + size = m_BgObjects.size(); + for(int i = 0; i < size; ++i) + { + DelObject(i); + } + // delete creature and go respawn times + WorldDatabase.PExecute("DELETE FROM creature_respawn WHERE instance = '%u'",GetInstanceID()); + WorldDatabase.PExecute("DELETE FROM gameobject_respawn WHERE instance = '%u'",GetInstanceID()); + // delete instance from db + CharacterDatabase.PExecute("DELETE FROM instance WHERE id = '%u'",GetInstanceID()); + // remove from battlegrounds + sBattleGroundMgr.RemoveBattleGround(GetInstanceID()); + // unload map + if(Map * map = MapManager::Instance().FindMap(GetMapId(), GetInstanceID())) + if(map->IsBattleGroundOrArena()) + ((BattleGroundMap*)map)->SetUnload(); + // remove from bg free slot queue + this->RemoveFromBGFreeSlotQueue(); } void BattleGround::Update(time_t diff) { - if(!GetPlayersSize() && !GetRemovedPlayersSize() && !GetReviveQueueSize()) //BG is empty return; @@ -188,6 +224,33 @@ void BattleGround::Update(time_t diff) m_ResurrectQueue.clear(); } + // if less then minimum players are in on one side, then start premature finish timer + if(GetStatus() == STATUS_IN_PROGRESS && !isArena() && sBattleGroundMgr.GetPrematureFinishTime() && (GetPlayersCountByTeam(ALLIANCE) < GetMinPlayersPerTeam() || GetPlayersCountByTeam(HORDE) < GetMinPlayersPerTeam())) + { + if(!m_PrematureCountDown) + { + m_PrematureCountDown = true; + m_PrematureCountDownTimer = sBattleGroundMgr.GetPrematureFinishTime(); + SendMessageToAll(LANG_BATTLEGROUND_PREMATURE_FINISH_WARNING); + } + else if(m_PrematureCountDownTimer < diff) + { + // time's up! + EndBattleGround(0); // noone wins + m_PrematureCountDown = false; + } + else + { + uint32 newtime = m_PrematureCountDownTimer - diff; + // announce every minute + if(m_PrematureCountDownTimer != sBattleGroundMgr.GetPrematureFinishTime() && newtime / 60000 != m_PrematureCountDownTimer / 60000) + SendMessageToAll(LANG_BATTLEGROUND_PREMATURE_FINISH_WARNING); + m_PrematureCountDownTimer = newtime; + } + } + else if (m_PrematureCountDown) + m_PrematureCountDown = false; + if(GetStatus() == STATUS_WAIT_LEAVE) { // remove all players from battleground after 2 minutes @@ -239,7 +302,10 @@ void BattleGround::SendPacketToTeam(uint32 TeamID, WorldPacket *packet, Player * if(!self && sender == plr) continue; - if(plr->GetTeam() == TeamID) + uint32 team = itr->second.Team;//GetPlayerTeam(plr->GetGUID()); + if(!team) team = plr->GetTeam(); + + if(team == TeamID) plr->GetSession()->SendPacket(packet); } } @@ -265,7 +331,10 @@ void BattleGround::PlaySoundToTeam(uint32 SoundID, uint32 TeamID) continue; } - if(plr->GetTeam() == TeamID) + uint32 team = itr->second.Team;//GetPlayerTeam(plr->GetGUID()); + if(!team) team = plr->GetTeam(); + + if(team == TeamID) { sBattleGroundMgr.BuildPlaySoundPacket(&data, SoundID); plr->GetSession()->SendPacket(&data); @@ -285,7 +354,10 @@ void BattleGround::CastSpellOnTeam(uint32 SpellID, uint32 TeamID) continue; } - if(plr->GetTeam() == TeamID) + uint32 team = itr->second.Team;//GetPlayerTeam(plr->GetGUID()); + if(!team) team = plr->GetTeam(); + + if(team == TeamID) plr->CastSpell(plr, SpellID, true); } } @@ -302,7 +374,10 @@ void BattleGround::RewardHonorToTeam(uint32 Honor, uint32 TeamID) continue; } - if(plr->GetTeam() == TeamID) + uint32 team = itr->second.Team;//GetPlayerTeam(plr->GetGUID()); + if(!team) team = plr->GetTeam(); + + if(team == TeamID) UpdatePlayerScore(plr, SCORE_BONUS_HONOR, Honor); } } @@ -324,7 +399,10 @@ void BattleGround::RewardReputationToTeam(uint32 faction_id, uint32 Reputation, continue; } - if(plr->GetTeam() == TeamID) + uint32 team = itr->second.Team;//GetPlayerTeam(plr->GetGUID()); + if(!team) team = plr->GetTeam(); + + if(team == TeamID) plr->ModifyFactionReputation(factionEntry, Reputation); } } @@ -345,30 +423,84 @@ void BattleGround::UpdateWorldStateForPlayer(uint32 Field, uint32 Value, Player void BattleGround::EndBattleGround(uint32 winner) { + this->RemoveFromBGFreeSlotQueue(); + + ArenaTeam * winner_arena_team = NULL; + ArenaTeam * loser_arena_team = NULL; + uint32 loser_rating = 0; + uint32 winner_rating = 0; WorldPacket data; Player *Source = NULL; const char *winmsg = ""; if(winner == ALLIANCE) { - winmsg = GetMangosString(LANG_BG_A_WINS); + if(isBattleGround()) + winmsg = GetMangosString(LANG_BG_A_WINS); + else + winmsg = GetMangosString(LANG_ARENA_GOLD_WINS); PlaySoundToAll(SOUND_ALLIANCE_WINS); // alliance wins sound SetWinner(WINNER_ALLIANCE); } - else + else if(winner == HORDE) { - winmsg = GetMangosString(LANG_BG_H_WINS); + if(isBattleGround()) + winmsg = GetMangosString(LANG_BG_H_WINS); + else + winmsg = GetMangosString(LANG_ARENA_GREEN_WINS); PlaySoundToAll(SOUND_HORDE_WINS); // horde wins sound SetWinner(WINNER_HORDE); } + else + { + SetWinner(3); + } SetStatus(STATUS_WAIT_LEAVE); m_EndTime = 0; + // arena rating calculation + if(isArena() && isRated()) + { + if(winner == ALLIANCE) + { + winner_arena_team = objmgr.GetArenaTeamById(GetArenaTeamIdForTeam(ALLIANCE)); + loser_arena_team = objmgr.GetArenaTeamById(GetArenaTeamIdForTeam(HORDE)); + } + else if(winner == HORDE) + { + winner_arena_team = objmgr.GetArenaTeamById(GetArenaTeamIdForTeam(HORDE)); + loser_arena_team = objmgr.GetArenaTeamById(GetArenaTeamIdForTeam(ALLIANCE)); + } + if(winner_arena_team && loser_arena_team) + { + loser_rating = loser_arena_team->GetStats().rating; + winner_rating = winner_arena_team->GetStats().rating; + int32 winner_change = winner_arena_team->WonAgainst(loser_rating); + int32 loser_change = loser_arena_team->LostAgainst(winner_rating); + sLog.outDebug("--- Winner rating: %u, Loser rating: %u, Winner change: %u, Losser change: %u ---", winner_rating, loser_rating, winner_change, loser_change); + if(winner == ALLIANCE) + { + SetArenaTeamRatingChangeForTeam(ALLIANCE, winner_change); + SetArenaTeamRatingChangeForTeam(HORDE, loser_change); + } + else + { + SetArenaTeamRatingChangeForTeam(HORDE, winner_change); + SetArenaTeamRatingChangeForTeam(ALLIANCE, loser_change); + } + } + else + { + SetArenaTeamRatingChangeForTeam(ALLIANCE, 0); + SetArenaTeamRatingChangeForTeam(HORDE, 0); + } + } + for(std::map::iterator itr = m_Players.begin(); itr != m_Players.end(); ++itr) { Player *plr = objmgr.GetPlayer(itr->first); @@ -378,13 +510,29 @@ void BattleGround::EndBattleGround(uint32 winner) continue; } + // should remove spirit of redemption + if(plr->HasAuraType(SPELL_AURA_SPIRIT_OF_REDEMPTION)) + plr->RemoveSpellsCausingAura(SPELL_AURA_MOD_SHAPESHIFT); + if(!plr->isAlive()) { plr->ResurrectPlayer(1.0f); plr->SpawnCorpseBones(); } - if(plr->GetTeam() == winner) + uint32 team = itr->second.Team; + if(!team) team = plr->GetTeam(); + + // per player calculation + if(isArena() && isRated() && winner_arena_team && loser_arena_team) + { + if(team == winner) + winner_arena_team->MemberWon(plr,loser_rating); + else + loser_arena_team->MemberLost(plr,winner_rating); + } + + if(team == winner) { if(!Source) Source = plr; @@ -404,10 +552,29 @@ void BattleGround::EndBattleGround(uint32 winner) sBattleGroundMgr.BuildPvpLogDataPacket(&data, this); plr->GetSession()->SendPacket(&data); - sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, this, plr->GetTeam(), plr->GetBattleGroundQueueIndex(m_TypeID), STATUS_IN_PROGRESS, TIME_TO_AUTOREMOVE, GetStartTime()); + uint32 bgQueueTypeId = sBattleGroundMgr.BGQueueTypeId(GetTypeID(), GetArenaType()); + sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, this, plr->GetTeam(), plr->GetBattleGroundQueueIndex(bgQueueTypeId), STATUS_IN_PROGRESS, TIME_TO_AUTOREMOVE, GetStartTime()); plr->GetSession()->SendPacket(&data); + plr->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_BATTLEGROUND, 1); } + if(isArena() && isRated() && winner_arena_team && loser_arena_team) + { + // update arena points only after increasing the player's match count! + //obsolete: winner_arena_team->UpdateArenaPointsHelper(); + //obsolete: loser_arena_team->UpdateArenaPointsHelper(); + // save the stat changes + winner_arena_team->SaveToDB(); + loser_arena_team->SaveToDB(); + // send updated arena team stats to players + // this way all arena team members will get notified, not only the ones who participated in this match + winner_arena_team->NotifyStatsChanged(); + loser_arena_team->NotifyStatsChanged(); + } + + // inform invited players about the removal + sBattleGroundMgr.m_BattleGroundQueues[sBattleGroundMgr.BGQueueTypeId(GetTypeID(), GetArenaType())].BGEndedRemoveInvites(this); + if(Source) { ChatHandler(Source).FillMessageData(&data, CHAT_MSG_BG_SYSTEM_NEUTRAL, LANG_UNIVERSAL, Source->GetGUID(), winmsg); @@ -558,12 +725,16 @@ void BattleGround::BlockMovement(Player *plr) void BattleGround::RemovePlayerAtLeave(uint64 guid, bool Transport, bool SendPacket) { + uint32 team = GetPlayerTeam(guid); + bool participant = false; // Remove from lists/maps std::map::iterator itr = m_Players.find(guid); if(itr != m_Players.end()) { - UpdatePlayersCountByTeam(itr->second.Team, true); // -1 player + UpdatePlayersCountByTeam(team, true); // -1 player m_Players.erase(itr); + // check if the player was a participant of the match, or only entered through gm command (goname) + participant = true; } std::map::iterator itr2 = m_PlayerScores.find(guid); @@ -577,6 +748,10 @@ void BattleGround::RemovePlayerAtLeave(uint64 guid, bool Transport, bool SendPac Player *plr = objmgr.GetPlayer(guid); + // should remove spirit of redemption + if(plr && plr->HasAuraType(SPELL_AURA_SPIRIT_OF_REDEMPTION)) + plr->RemoveSpellsCausingAura(SPELL_AURA_MOD_SHAPESHIFT); + if(plr && !plr->isAlive()) // resurrect on exit { plr->ResurrectPlayer(1.0f); @@ -589,66 +764,106 @@ void BattleGround::RemovePlayerAtLeave(uint64 guid, bool Transport, bool SendPac { plr->ClearAfkReports(); - if(isArena()) + if(participant) // if the player was a match participant, remove auras, calc rating, update queue { - if(!sWorld.IsFFAPvPRealm()) - plr->RemoveFlag(PLAYER_FLAGS, PLAYER_FLAGS_FFA_PVP); - } + if(!team) team = plr->GetTeam(); - WorldPacket data; - if(SendPacket) - { - sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, this, plr->GetTeam(), plr->GetBattleGroundQueueIndex(m_TypeID), STATUS_NONE, 0, 0); - plr->GetSession()->SendPacket(&data); - } - - // this call is important, because player, when joins to battleground, this method is not called, so it must be called when leaving bg - plr->RemoveBattleGroundQueueId(m_TypeID); - - DecreaseInvitedCount(plr->GetTeam()); - //we should update battleground queue, but only if bg isn't ending - if (GetQueueType() < MAX_BATTLEGROUND_QUEUES) - sBattleGroundMgr.m_BattleGroundQueues[GetTypeID()].Update(GetTypeID(), GetQueueType()); - - if(!plr->GetBattleGroundId()) - return; - - Group * group = plr->GetGroup(); - - // remove from raid group if exist - if(group && group == GetBgRaid(plr->GetTeam())) - { - if(!group->RemoveMember(guid, 0)) // group was disbanded + uint32 bgTypeId = GetTypeID(); + uint32 bgQueueTypeId = sBattleGroundMgr.BGQueueTypeId(GetTypeID(), GetArenaType()); + // if arena, remove the specific arena auras + if(isArena()) { - SetBgRaid(plr->GetTeam(), NULL); - delete group; + plr->RemoveArenaAuras(true); // removes debuffs / dots etc., we don't want the player to die after porting out + bgTypeId=BATTLEGROUND_AA; // set the bg type to all arenas (it will be used for queue refreshing) + + // summon old pet if there was one and there isn't a current pet + if(!plr->GetPet() && plr->GetTemporaryUnsummonedPetNumber()) + { + Pet* NewPet = new Pet; + if(!NewPet->LoadPetFromDB(plr, 0, (plr)->GetTemporaryUnsummonedPetNumber(), true)) + delete NewPet; + + (plr)->SetTemporaryUnsummonedPetNumber(0); + } + + if(isRated() && GetStatus() == STATUS_IN_PROGRESS) + { + //left a rated match while the encounter was in progress, consider as loser + ArenaTeam * winner_arena_team = 0; + ArenaTeam * loser_arena_team = 0; + if(team == HORDE) + { + winner_arena_team = objmgr.GetArenaTeamById(GetArenaTeamIdForTeam(ALLIANCE)); + loser_arena_team = objmgr.GetArenaTeamById(GetArenaTeamIdForTeam(HORDE)); + } + else + { + winner_arena_team = objmgr.GetArenaTeamById(GetArenaTeamIdForTeam(HORDE)); + loser_arena_team = objmgr.GetArenaTeamById(GetArenaTeamIdForTeam(ALLIANCE)); + } + if(winner_arena_team && loser_arena_team) + { + loser_arena_team->MemberLost(plr,winner_arena_team->GetRating()); + } + } } + + WorldPacket data; + if(SendPacket) + { + sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, this, team, plr->GetBattleGroundQueueIndex(bgQueueTypeId), STATUS_NONE, 0, 0); + plr->GetSession()->SendPacket(&data); + } + + // this call is important, because player, when joins to battleground, this method is not called, so it must be called when leaving bg + plr->RemoveBattleGroundQueueId(bgQueueTypeId); + + DecreaseInvitedCount(team); + //we should update battleground queue, but only if bg isn't ending + if (GetQueueType() < MAX_BATTLEGROUND_QUEUES) + sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].Update(bgTypeId, GetQueueType()); + + Group * group = plr->GetGroup(); + // remove from raid group if exist + if(group && group == GetBgRaid(team)) + { + if(!group->RemoveMember(guid, 0)) // group was disbanded + { + SetBgRaid(team, NULL); + delete group; + } + } + + // Let others know + sBattleGroundMgr.BuildPlayerLeftBattleGroundPacket(&data, plr); + SendPacketToTeam(team, &data, plr, false); } // Do next only if found in battleground plr->SetBattleGroundId(0); // We're not in BG. - - // Let others know - sBattleGroundMgr.BuildPlayerLeftBattleGroundPacket(&data, plr); - SendPacketToTeam(plr->GetTeam(), &data, plr, false); + // reset destination bg team + plr->SetBGTeam(0); if(Transport) { plr->TeleportTo(plr->GetBattleGroundEntryPointMap(), plr->GetBattleGroundEntryPointX(), plr->GetBattleGroundEntryPointY(), plr->GetBattleGroundEntryPointZ(), plr->GetBattleGroundEntryPointO()); - //sLog.outDetail("BATTLEGROUND: Sending %s to %f,%f,%f,%f", pl->GetName(), x,y,z,O); } // Log sLog.outDetail("BATTLEGROUND: Removed player %s from BattleGround.", plr->GetName()); } - /// there will be code which will add battleground to BGFreeSlotQueue , when battleground instance will exist - // we always should check if BG is in that queue before adding.. - - if(!GetPlayersSize()) + if(!GetPlayersSize() && !GetInvitedCount(HORDE) && !GetInvitedCount(ALLIANCE)) { - Reset(); + // if no players left AND no invitees left, set this bg to delete in next update + // direct deletion could cause crashes + m_SetDeleteThis = true; + // return to prevent addition to freeslotqueue + return; } + + // a player exited the battleground, so there are free slots. add to queue + this->AddToBGFreeSlotQueue(); } // this method is called when no players remains in battleground @@ -660,6 +875,8 @@ void BattleGround::Reset() SetStartTime(0); SetEndTime(0); SetLastResurrectTime(0); + SetArenaType(0); + SetRated(false); m_Events = 0; @@ -668,6 +885,7 @@ void BattleGround::Reset() m_InvitedAlliance = 0; m_InvitedHorde = 0; + m_InBGFreeSlotQueue = false; m_Players.clear(); m_PlayerScores.clear(); @@ -704,10 +922,11 @@ void BattleGround::AddPlayer(Player *plr) sBattleGroundMgr.BuildPlayerJoinedBattleGroundPacket(&data, plr); SendPacketToTeam(team, &data, plr, false); + // add arena specific auras if(isArena()) { plr->RemoveArenaSpellCooldowns(); - //plr->RemoveArenaAuras(); + plr->RemoveArenaAuras(); plr->RemoveAllEnchantments(TEMP_ENCHANTMENT_SLOT); if(team == ALLIANCE) // gold { @@ -726,6 +945,19 @@ void BattleGround::AddPlayer(Player *plr) plr->DestroyConjuredItems(true); + Pet* pet = plr->GetPet(); + if(pet) + { + if(pet->getPetType() == SUMMON_PET || pet->getPetType() == HUNTER_PET) + { + (plr)->SetTemporaryUnsummonedPetNumber(pet->GetCharmInfo()->GetPetNumber()); + (plr)->SetOldPetSpell(pet->GetUInt32Value(UNIT_CREATED_BY_SPELL)); + } + (plr)->RemovePet(NULL,PET_SAVE_NOT_IN_SLOT); + } + else + (plr)->SetTemporaryUnsummonedPetNumber(0); + if(GetStatus() == STATUS_WAIT_JOIN) // not started yet { plr->CastSpell(plr, SPELL_ARENA_PREPARATION, true); @@ -740,9 +972,6 @@ void BattleGround::AddPlayer(Player *plr) plr->CastSpell(plr, SPELL_PREPARATION, true); // reduces all mana cost of spells. } - if(isArena()) - plr->SetFlag(PLAYER_FLAGS, PLAYER_FLAGS_FFA_PVP); - // Log sLog.outDetail("BATTLEGROUND: Player %s joined the battle.", plr->GetName()); } @@ -750,13 +979,20 @@ void BattleGround::AddPlayer(Player *plr) /* This method should be called only once ... it adds pointer to queue */ void BattleGround::AddToBGFreeSlotQueue() { - sBattleGroundMgr.BGFreeSlotQueue[m_TypeID].push_front(this); + // make sure to add only once + if(!m_InBGFreeSlotQueue) + { + sBattleGroundMgr.BGFreeSlotQueue[m_TypeID].push_front(this); + m_InBGFreeSlotQueue = true; + } } /* This method removes this battleground from free queue - it must be called when deleting battleground - not used now*/ void BattleGround::RemoveFromBGFreeSlotQueue() { - /* uncomment this code when battlegrounds will work like instances + // set to be able to re-add if needed + m_InBGFreeSlotQueue = false; + // uncomment this code when battlegrounds will work like instances for (std::deque::iterator itr = sBattleGroundMgr.BGFreeSlotQueue[m_TypeID].begin(); itr != sBattleGroundMgr.BGFreeSlotQueue[m_TypeID].end(); ++itr) { if ((*itr)->GetInstanceID() == m_InstanceID) @@ -764,30 +1000,69 @@ void BattleGround::RemoveFromBGFreeSlotQueue() sBattleGroundMgr.BGFreeSlotQueue[m_TypeID].erase(itr); return; } - }*/ + } } -/* -this method should decide, if we can invite new player of certain team to BG, it is based on BATTLEGROUND_STATUS -*/ -bool BattleGround::HasFreeSlotsForTeam(uint32 Team) const +// get the number of free slots for team +// works in similar way that HasFreeSlotsForTeam did, but this is needed for join as group +uint32 BattleGround::GetFreeSlotsForTeam(uint32 Team) const { - //if BG is starting ... invite anyone: + //if BG is starting ... invite anyone if (GetStatus() == STATUS_WAIT_JOIN) - return GetInvitedCount(Team) < GetMaxPlayersPerTeam(); + return (GetInvitedCount(Team) < GetMaxPlayersPerTeam()) ? GetMaxPlayersPerTeam() - GetInvitedCount(Team) : 0; //if BG is already started .. do not allow to join too much players of one faction uint32 otherTeam; + uint32 otherIn; if (Team == ALLIANCE) + { otherTeam = GetInvitedCount(HORDE); + otherIn = GetPlayersCountByTeam(HORDE); + } else + { otherTeam = GetInvitedCount(ALLIANCE); + otherIn = GetPlayersCountByTeam(ALLIANCE); + } if (GetStatus() == STATUS_IN_PROGRESS) - return (GetInvitedCount(Team) <= otherTeam && GetInvitedCount(Team) < GetMaxPlayersPerTeam()); + { + // difference based on ppl invited (not necessarily entered battle) + // default: allow 0 + uint32 diff = 0; + // allow join one person if the sides are equal (to fill up bg to minplayersperteam) + if (otherTeam == GetInvitedCount(Team)) + diff = 1; + // allow join more ppl if the other side has more players + else if(otherTeam > GetInvitedCount(Team)) + diff = otherTeam - GetInvitedCount(Team); - return false; + // difference based on max players per team (don't allow inviting more) + uint32 diff2 = (GetInvitedCount(Team) < GetMaxPlayersPerTeam()) ? GetMaxPlayersPerTeam() - GetInvitedCount(Team) : 0; + + // difference based on players who already entered + // default: allow 0 + uint32 diff3 = 0; + // allow join one person if the sides are equal (to fill up bg minplayersperteam) + if (otherIn == GetPlayersCountByTeam(Team)) + diff3 = 1; + // allow join more ppl if the other side has more players + else if (otherIn > GetPlayersCountByTeam(Team)) + diff3 = otherIn - GetPlayersCountByTeam(Team); + // or other side has less than minPlayersPerTeam + else if (GetInvitedCount(Team) <= GetMinPlayersPerTeam()) + diff3 = GetMinPlayersPerTeam() - GetInvitedCount(Team) + 1; + + // return the minimum of the 3 differences + + // min of diff and diff 2 + diff = diff < diff2 ? diff : diff2; + + // min of diff, diff2 and diff3 + return diff < diff3 ? diff : diff3 ; + } + + return 0; } -/* this method isn't called already, it will be useful when more battlegrounds of one type will be available */ bool BattleGround::HasFreeSlots() const { return GetPlayersSize() < GetMaxPlayers(); @@ -813,9 +1088,13 @@ void BattleGround::UpdatePlayerScore(Player *Source, uint32 type, uint32 value) itr->second->HonorableKills += value; break; case SCORE_BONUS_HONOR: // Honor bonus - // reward honor instantly - if(Source->RewardHonor(NULL, 1, value)) - itr->second->BonusHonor += value; + // do not add honor in arenas + if(isBattleGround()) + { + // reward honor instantly + if(Source->RewardHonor(NULL, 1, value)) + itr->second->BonusHonor += value; + } break; //used only in EY, but in MSG_PVP_LOG_DATA opcode case SCORE_DAMAGE_DONE: // Damage Done @@ -871,15 +1150,26 @@ void BattleGround::RemovePlayerFromResurrectQueue(uint64 player_guid) bool BattleGround::AddObject(uint32 type, uint32 entry, float x, float y, float z, float o, float rotation0, float rotation1, float rotation2, float rotation3, uint32 respawnTime) { - GameObjectInfo const* goinfo = objmgr.GetGameObjectInfo(entry); - if(!goinfo) + Map * map = MapManager::Instance().FindMap(GetMapId(),GetInstanceID()); + if(!map) + return false; + + // must be created this way, adding to godatamap would add it to the base map of the instance + // and when loading it (in go::LoadFromDB()), a new guid would be assigned to the object, and a new object would be created + // so we must create it specific for this instance + GameObject * go = new GameObject; + if(!go->Create(objmgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT),entry, map,x,y,z,o,rotation0,rotation1,rotation2,rotation3,100,1)) { sLog.outErrorDb("Gameobject template %u not found in database! BattleGround not created!", entry); + sLog.outError("Cannot create gameobject template %u! BattleGround not created!", entry); + delete go; return false; } +/* + uint32 guid = go->GetGUIDLow(); - uint32 guid = objmgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT); - + // without this, UseButtonOrDoor caused the crash, since it tried to get go info from godata + // iirc that was changed, so adding to go data map is no longer required if that was the only function using godata from GameObject without checking if it existed GameObjectData& data = objmgr.NewGOData(guid); data.id = entry; @@ -893,13 +1183,13 @@ bool BattleGround::AddObject(uint32 type, uint32 entry, float x, float y, float data.rotation2 = rotation2; data.rotation3 = rotation3; data.spawntimesecs = respawnTime; + data.spawnMask = 1; data.animprogress = 100; data.go_state = 1; - data.spawnMask = 1; - objmgr.AddGameobjectToGrid(guid, &data); - - m_BgObjects[type] = MAKE_NEW_GUID(guid, entry, HIGHGUID_GAMEOBJECT); - +*/ + // add to world, so it can be later looked up from HashMapHolder + go->AddToWorld(); + m_BgObjects[type] = go->GetGUID(); return true; } @@ -941,6 +1231,9 @@ void BattleGround::DoorOpen(uint32 type) void BattleGround::SpawnBGObject(uint32 type, uint32 respawntime) { + Map * map = MapManager::Instance().FindMap(GetMapId(),GetInstanceID()); + if(!map) + return; if( respawntime == 0 ) { GameObject *obj = HashMapHolder::Find(m_BgObjects[type]); @@ -949,30 +1242,27 @@ void BattleGround::SpawnBGObject(uint32 type, uint32 respawntime) //we need to change state from GO_JUST_DEACTIVATED to GO_READY in case battleground is starting again if( obj->getLootState() == GO_JUST_DEACTIVATED ) obj->SetLootState(GO_READY); - obj->Respawn(); + obj->SetRespawnTime(0); + map->Add(obj); } - else - objmgr.SaveGORespawnTime(GUID_LOPART(m_BgObjects[type]), 0, 0); } else { GameObject *obj = HashMapHolder::Find(m_BgObjects[type]); if(obj) { + map->Add(obj); obj->SetRespawnTime(respawntime); obj->SetLootState(GO_JUST_DEACTIVATED); } - else - objmgr.SaveGORespawnTime(GUID_LOPART(m_BgObjects[type]), 0, time(NULL) + respawntime); } } -Creature* BattleGround::AddCreature(uint32 entry, uint32 type, uint32 teamval, float x, float y, float z, float o) +Creature* BattleGround::AddCreature(uint32 entry, uint32 type, uint32 teamval, float x, float y, float z, float o, uint32 respawntime) { - // note: this should normally be FindMap - // but it's a hack to allow the battlegrounds to initialize at server startup - Map * map = MapManager::Instance().GetMap(GetMapId(), 0); - if(!map) return NULL; + Map * map = MapManager::Instance().FindMap(GetMapId(),GetInstanceID()); + if(!map) + return NULL; Creature* pCreature = new Creature; if (!pCreature->Create(objmgr.GenerateLowGuid(HIGHGUID_UNIT), map, entry, teamval)) @@ -996,9 +1286,39 @@ Creature* BattleGround::AddCreature(uint32 entry, uint32 type, uint32 teamval, f map->Add(pCreature); m_BgCreatures[type] = pCreature->GetGUID(); + return pCreature; } +/* +void BattleGround::SpawnBGCreature(uint32 type, uint32 respawntime) +{ + Map * map = MapManager::Instance().FindMap(GetMapId(),GetInstanceId()); + if(!map) + return false; + if(respawntime == 0) + { + Creature *obj = HashMapHolder::Find(m_BgCreatures[type]); + if(obj) + { + //obj->Respawn(); // bugged + obj->SetRespawnTime(0); + objmgr.SaveCreatureRespawnTime(obj->GetGUIDLow(), GetInstanceID(), 0); + map->Add(obj); + } + } + else + { + Creature *obj = HashMapHolder::Find(m_BgCreatures[type]); + if(obj) + { + obj->setDeathState(DEAD); + obj->SetRespawnTime(respawntime); + map->Add(obj); + } + } +} +*/ bool BattleGround::DelCreature(uint32 type) { Creature *cr = HashMapHolder::Find(m_BgCreatures[type]); @@ -1048,10 +1368,10 @@ bool BattleGround::AddSpiritGuide(uint32 type, float x, float y, float z, float pCreature->SetUInt64Value(UNIT_FIELD_CHANNEL_OBJECT, pCreature->GetGUID()); // aura - pCreature->SetUInt32Value(UNIT_FIELD_AURA, SPELL_SPIRIT_HEAL_CHANNEL); - pCreature->SetUInt32Value(UNIT_FIELD_AURAFLAGS, 0x00000009); - pCreature->SetUInt32Value(UNIT_FIELD_AURALEVELS, 0x0000003C); - pCreature->SetUInt32Value(UNIT_FIELD_AURAAPPLICATIONS, 0x000000FF); + pCreature->SetVisibleAura(0, SPELL_SPIRIT_HEAL_CHANNEL); + //pCreature->SetUInt32Value(UNIT_FIELD_AURAFLAGS, 0x00000009); + //pCreature->SetUInt32Value(UNIT_FIELD_AURALEVELS, 0x0000003C); + //pCreature->SetUInt32Value(UNIT_FIELD_AURAAPPLICATIONS, 0x000000FF); // casting visual effect pCreature->SetUInt32Value(UNIT_CHANNEL_SPELL, SPELL_SPIRIT_HEAL_CHANNEL); // correct cast speed @@ -1079,8 +1399,11 @@ void BattleGround::SendMessageToAll(int32 entry) void BattleGround::EndNow() { + RemoveFromBGFreeSlotQueue(); SetStatus(STATUS_WAIT_LEAVE); SetEndTime(TIME_TO_AUTOREMOVE); + // inform invited players about the removal + sBattleGroundMgr.m_BattleGroundQueues[sBattleGroundMgr.BGQueueTypeId(GetTypeID(), GetArenaType())].BGEndedRemoveInvites(this); } // Battleground messages are localized using the dbc lang, they are not client language dependent @@ -1158,3 +1481,28 @@ void BattleGround::HandleKillPlayer( Player *player, Player *killer ) // to be able to remove insignia player->SetFlag( UNIT_FIELD_FLAGS, UNIT_FLAG_SKINNABLE ); } + +// return the player's team based on battlegroundplayer info +// used in same faction arena matches mainly +uint32 BattleGround::GetPlayerTeam(uint64 guid) +{ + std::map::const_iterator itr = m_Players.find(guid); + if(itr!=m_Players.end()) + return itr->second.Team; + return 0; +} + +uint32 BattleGround::GetAlivePlayersCountByTeam(uint32 Team) const +{ + int count = 0; + for(std::map::const_iterator itr = m_Players.begin(); itr != m_Players.end(); ++itr) + { + if(itr->second.Team == Team) + { + Player * pl = objmgr.GetPlayer(itr->first); + if(pl && pl->isAlive()) + ++count; + } + } + return count; +} diff --git a/src/game/BattleGround.h b/src/game/BattleGround.h index 9e41e661b..1e92dfaea 100644 --- a/src/game/BattleGround.h +++ b/src/game/BattleGround.h @@ -83,7 +83,7 @@ enum BattleGroundTimeIntervals { RESURRECTION_INTERVAL = 30000, // ms REMIND_INTERVAL = 30000, // ms - INVITE_ACCEPT_WAIT_TIME = 120000, // ms + INVITE_ACCEPT_WAIT_TIME = 80000, // ms TIME_TO_AUTOREMOVE = 120000, // ms MAX_OFFLINE_TIME = 300000, // ms START_DELAY0 = 120000, // ms @@ -129,8 +129,6 @@ struct BattleGroundObjectInfo uint32 spellid; }; -#define MAX_QUEUED_PLAYERS_MAP 7 - enum BattleGroundTypeId { BATTLEGROUND_AV = 1, @@ -140,7 +138,22 @@ enum BattleGroundTypeId BATTLEGROUND_BE = 5, BATTLEGROUND_AA = 6, BATTLEGROUND_EY = 7, - BATTLEGROUND_RL = 8 + BATTLEGROUND_RL = 8, + BATTLEGROUND_SA = 9, + BATTLEGROUND_DS = 10, + BATTLEGROUND_RV = 11 +}; + +// handle the queue types and bg types separately to enable joining queue for different sized arenas at the same time +enum BattleGroundQueueTypeId +{ + BATTLEGROUND_QUEUE_AV = 1, + BATTLEGROUND_QUEUE_WS = 2, + BATTLEGROUND_QUEUE_AB = 3, + BATTLEGROUND_QUEUE_EY = 4, + BATTLEGROUND_QUEUE_2v2 = 5, + BATTLEGROUND_QUEUE_3v3 = 6, + BATTLEGROUND_QUEUE_5v5 = 7, }; enum ScoreType @@ -195,6 +208,20 @@ enum BattleGroundTeamId BG_TEAM_HORDE = 1 }; +enum BattleGroundJoinError +{ + BG_JOIN_ERR_OK = 0, + BG_JOIN_ERR_OFFLINE_MEMBER = 1, + BG_JOIN_ERR_GROUP_TOO_MANY = 2, + BG_JOIN_ERR_MIXED_FACTION = 3, + BG_JOIN_ERR_MIXED_LEVELS = 4, + BG_JOIN_ERR_MIXED_ARENATEAM = 5, + BG_JOIN_ERR_GROUP_MEMBER_ALREADY_IN_QUEUE = 6, + BG_JOIN_ERR_GROUP_DESERTER = 7, + BG_JOIN_ERR_ALL_QUEUES_USED = 8, + BG_JOIN_ERR_GROUP_NOT_ENOUGH = 9 +}; + class BattleGroundScore { public: @@ -224,6 +251,7 @@ class BattleGround public: /* Construction */ BattleGround(); + /*BattleGround(const BattleGround& bg);*/ virtual ~BattleGround(); virtual void Update(time_t diff); // must be implemented in BG subclass of BG specific update code, but must in begginning call parent version virtual bool SetupBattleGround() // must be implemented in BG subclass @@ -296,6 +324,7 @@ class BattleGround } bool HasFreeSlotsForTeam(uint32 Team) const; bool HasFreeSlots() const; + uint32 GetFreeSlotsForTeam(uint32 Team) const; bool isArena() const { return m_IsArena; } bool isBattleGround() const { return !m_IsArena; } @@ -366,6 +395,7 @@ class BattleGround uint8 GetTeamIndexByTeamId(uint32 Team) const { return Team == ALLIANCE ? BG_TEAM_ALLIANCE : BG_TEAM_HORDE; } uint32 GetPlayersCountByTeam(uint32 Team) const { return m_PlayersCount[GetTeamIndexByTeamId(Team)]; } + uint32 GetAlivePlayersCountByTeam(uint32 Team) const; // used in arenas to correctly handle death in spirit of redemption / last stand etc. (killer = killed) cases void UpdatePlayersCountByTeam(uint32 Team, bool remove) { if(remove) @@ -374,6 +404,12 @@ class BattleGround ++m_PlayersCount[GetTeamIndexByTeamId(Team)]; } + // used for rated arena battles + void SetArenaTeamIdForTeam(uint32 Team, uint32 ArenaTeamId) { m_ArenaTeamIds[GetTeamIndexByTeamId(Team)] = ArenaTeamId; } + uint32 GetArenaTeamIdForTeam(uint32 Team) const { return m_ArenaTeamIds[GetTeamIndexByTeamId(Team)]; } + void SetArenaTeamRatingChangeForTeam(uint32 Team, int32 RatingChange) { m_ArenaTeamRatingChanges[GetTeamIndexByTeamId(Team)] = RatingChange; } + int32 GetArenaTeamRatingChangeForTeam(uint32 Team) const { return m_ArenaTeamRatingChanges[GetTeamIndexByTeamId(Team)]; } + /* Triggers handle */ // must be implemented in BG subclass virtual void HandleAreaTrigger(Player* /*Source*/, uint32 /*Trigger*/) {} @@ -390,6 +426,7 @@ class BattleGround virtual WorldSafeLocsEntry const* GetClosestGraveYard(float /*x*/, float /*y*/, float /*z*/, uint32 /*team*/) { return NULL; } virtual void AddPlayer(Player *plr); // must be implemented in BG subclass + virtual void RemovePlayerAtLeave(uint64 guid, bool Transport, bool SendPacket); // can be extended in in BG subclass @@ -402,7 +439,8 @@ class BattleGround BGCreatures m_BgCreatures; void SpawnBGObject(uint32 type, uint32 respawntime); bool AddObject(uint32 type, uint32 entry, float x, float y, float z, float o, float rotation0, float rotation1, float rotation2, float rotation3, uint32 respawnTime = 0); - Creature* AddCreature(uint32 entry, uint32 type, uint32 teamval, float x, float y, float z, float o); +// void SpawnBGCreature(uint32 type, uint32 respawntime); + Creature* AddCreature(uint32 entry, uint32 type, uint32 teamval, float x, float y, float z, float o, uint32 respawntime = 0); bool DelCreature(uint32 type); bool DelObject(uint32 type); bool AddSpiritGuide(uint32 type, float x, float y, float z, float o, uint32 team); @@ -411,6 +449,13 @@ class BattleGround void DoorClose(uint32 type); const char *GetMangosString(int32 entry); + virtual bool HandlePlayerUnderMap(Player * plr) {return false;} + + // since arenas can be AvA or Hvh, we have to get the "temporary" team of a player + uint32 GetPlayerTeam(uint64 guid); + + void SetDeleteThis() {m_SetDeleteThis = true;} + protected: //this method is called, when BG cannot spawn its own spirit guide, or something is wrong, It correctly ends BattleGround void EndNow(); @@ -443,6 +488,8 @@ class BattleGround uint32 m_LastResurrectTime; uint32 m_Queue_type; uint8 m_ArenaType; // 2=2v2, 3=3v3, 5=5v5 + bool m_InBGFreeSlotQueue; // used to make sure that BG is only once inserted into the BattleGroundMgr.BGFreeSlotQueue[bgTypeId] deque + bool m_SetDeleteThis; // used for safe deletion of the bg after end / all players leave // this variable is not used .... it can be found in many other ways... but to store it in BG object instance is useless //uint8 m_BattleGroundType; // 3=BG, 4=arena //instead of uint8 (in previous line) is bool used @@ -450,6 +497,8 @@ class BattleGround uint8 m_Winner; // 0=alliance, 1=horde, 2=none int32 m_StartDelayTime; bool m_IsRated; // is this battle rated? + bool m_PrematureCountDown; + uint32 m_PrematureCountDownTimer; char const *m_Name; /* Player lists */ @@ -468,6 +517,11 @@ class BattleGround /* Players count by team */ uint32 m_PlayersCount[2]; + /* Arena team ids by team */ + uint32 m_ArenaTeamIds[2]; + + int32 m_ArenaTeamRatingChanges[2]; + /* Limits */ uint32 m_LevelMin; uint32 m_LevelMax; diff --git a/src/game/BattleGroundAB.cpp b/src/game/BattleGroundAB.cpp index dcf23ccff..5200a3f5f 100644 --- a/src/game/BattleGroundAB.cpp +++ b/src/game/BattleGroundAB.cpp @@ -50,6 +50,13 @@ void BattleGroundAB::Update(time_t diff) { m_Events |= 0x01; + // setup here, only when at least one player has ported to the map + if(!SetupBattleGround()) + { + EndNow(); + return; + } + sLog.outDebug("Arathi Basin: entering state STATUS_WAIT_JOIN ..."); // despawn banners, auras and buffs @@ -377,6 +384,7 @@ void BattleGroundAB::_NodeOccupied(uint8 node,Team team) { if( !AddSpiritGuide(node, BG_AB_SpiritGuidePos[node][0], BG_AB_SpiritGuidePos[node][1], BG_AB_SpiritGuidePos[node][2], BG_AB_SpiritGuidePos[node][3], team) ) sLog.outError("Failed to spawn spirit guide! point: %u, team: %u,", node, team); +// SpawnBGCreature(node,RESPAWN_IMMEDIATELY); uint8 capturedNodes = 0; for (uint8 i = 0; i < BG_AB_DYNAMIC_NODES_COUNT; ++i) diff --git a/src/game/BattleGroundBE.cpp b/src/game/BattleGroundBE.cpp index 4ad71988e..81e47c721 100644 --- a/src/game/BattleGroundBE.cpp +++ b/src/game/BattleGroundBE.cpp @@ -47,6 +47,12 @@ void BattleGroundBE::Update(time_t diff) if (!(m_Events & 0x01)) { m_Events |= 0x01; + // setup here, only when at least one player has ported to the map + if(!SetupBattleGround()) + { + EndNow(); + return; + } for(uint32 i = BG_BE_OBJECT_DOOR_1; i <= BG_BE_OBJECT_DOOR_4; i++) SpawnBGObject(i, RESPAWN_IMMEDIATELY); @@ -86,6 +92,11 @@ void BattleGroundBE::Update(time_t diff) for(BattleGroundPlayerMap::const_iterator itr = GetPlayers().begin(); itr != GetPlayers().end(); ++itr) if(Player *plr = objmgr.GetPlayer(itr->first)) plr->RemoveAurasDueToSpell(SPELL_ARENA_PREPARATION); + + if(!GetPlayersCountByTeam(ALLIANCE) && GetPlayersCountByTeam(HORDE)) + EndBattleGround(HORDE); + else if(GetPlayersCountByTeam(ALLIANCE) && !GetPlayersCountByTeam(HORDE)) + EndBattleGround(ALLIANCE); } } @@ -102,11 +113,23 @@ void BattleGroundBE::AddPlayer(Player *plr) BattleGroundBEScore* sc = new BattleGroundBEScore; m_PlayerScores[plr->GetGUID()] = sc; + + UpdateWorldState(0x9f1, GetAlivePlayersCountByTeam(ALLIANCE)); + UpdateWorldState(0x9f0, GetAlivePlayersCountByTeam(HORDE)); } void BattleGroundBE::RemovePlayer(Player* /*plr*/, uint64 /*guid*/) { + if(GetStatus() == STATUS_WAIT_LEAVE) + return; + UpdateWorldState(0x9f1, GetAlivePlayersCountByTeam(ALLIANCE)); + UpdateWorldState(0x9f0, GetAlivePlayersCountByTeam(HORDE)); + + if(!GetAlivePlayersCountByTeam(ALLIANCE) && GetPlayersCountByTeam(HORDE)) + EndBattleGround(HORDE); + else if(GetPlayersCountByTeam(ALLIANCE) && !GetAlivePlayersCountByTeam(HORDE)) + EndBattleGround(ALLIANCE); } void BattleGroundBE::HandleKillPlayer(Player *player, Player *killer) @@ -120,17 +143,27 @@ void BattleGroundBE::HandleKillPlayer(Player *player, Player *killer) return; } - BattleGround::HandleKillPlayer(player, killer); + BattleGround::HandleKillPlayer(player,killer); - uint32 killer_team_index = GetTeamIndexByTeamId(killer->GetTeam()); + UpdateWorldState(0x9f1, GetAlivePlayersCountByTeam(ALLIANCE)); + UpdateWorldState(0x9f0, GetAlivePlayersCountByTeam(HORDE)); - ++m_TeamKills[killer_team_index]; // add kills to killer's team - - if(m_TeamKills[killer_team_index] >= GetPlayersCountByTeam(player->GetTeam())) + if(!GetAlivePlayersCountByTeam(ALLIANCE)) { // all opponents killed - EndBattleGround(killer->GetTeam()); + EndBattleGround(HORDE); } + else if(!GetAlivePlayersCountByTeam(HORDE)) + { + // all opponents killed + EndBattleGround(ALLIANCE); + } +} + +bool BattleGroundBE::HandlePlayerUnderMap(Player *player) +{ + player->TeleportTo(GetMapId(),6238.930176,262.963470,0.889519,player->GetOrientation(),false); + return true; } void BattleGroundBE::HandleAreaTrigger(Player *Source, uint32 Trigger) @@ -159,10 +192,16 @@ void BattleGroundBE::HandleAreaTrigger(Player *Source, uint32 Trigger) // HandleTriggerBuff(buff_guid,Source); } +void BattleGroundBE::FillInitialWorldStates(WorldPacket &data) +{ + data << uint32(0x9f1) << uint32(GetAlivePlayersCountByTeam(ALLIANCE)); // 7 + data << uint32(0x9f0) << uint32(GetAlivePlayersCountByTeam(HORDE)); // 8 + data << uint32(0x9f3) << uint32(1); // 9 +} + void BattleGroundBE::ResetBGSubclass() { - m_TeamKills[BG_TEAM_ALLIANCE] = 0; - m_TeamKills[BG_TEAM_HORDE] = 0; + } bool BattleGroundBE::SetupBattleGround() diff --git a/src/game/BattleGroundBE.h b/src/game/BattleGroundBE.h index f74f0a648..df46efbfd 100644 --- a/src/game/BattleGroundBE.h +++ b/src/game/BattleGroundBE.h @@ -64,12 +64,11 @@ class BattleGroundBE : public BattleGround void HandleAreaTrigger(Player *Source, uint32 Trigger); bool SetupBattleGround(); void ResetBGSubclass(); + virtual void FillInitialWorldStates(WorldPacket &d); void HandleKillPlayer(Player* player, Player *killer); + bool HandlePlayerUnderMap(Player * plr); /* Scorekeeping */ void UpdatePlayerScore(Player *Source, uint32 type, uint32 value); - - private: - uint32 m_TeamKills[2]; // count of kills for each team }; #endif diff --git a/src/game/BattleGroundEY.cpp b/src/game/BattleGroundEY.cpp index 241ad5b98..279816b34 100644 --- a/src/game/BattleGroundEY.cpp +++ b/src/game/BattleGroundEY.cpp @@ -54,9 +54,18 @@ void BattleGroundEY::Update(time_t diff) { m_Events |= 0x01; + // setup here, only when at least one player has ported to the map + if(!SetupBattleGround()) + { + EndNow(); + return; + } + SpawnBGObject(BG_EY_OBJECT_DOOR_A, RESPAWN_IMMEDIATELY); SpawnBGObject(BG_EY_OBJECT_DOOR_H, RESPAWN_IMMEDIATELY); +// SpawnBGCreature(EY_SPIRIT_MAIN_ALLIANCE, RESPAWN_IMMEDIATELY); +// SpawnBGCreature(EY_SPIRIT_MAIN_HORDE, RESPAWN_IMMEDIATELY); for(uint32 i = BG_EY_OBJECT_A_BANNER_FEL_REALVER_CENTER; i < BG_EY_OBJECT_MAX; ++i) SpawnBGObject(i, RESPAWN_ONE_DAY); @@ -572,7 +581,17 @@ void BattleGroundEY::HandleKillPlayer(Player *player, Player *killer) void BattleGroundEY::EventPlayerDroppedFlag(Player *Source) { - // Drop allowed in any BG state + if(GetStatus() != STATUS_IN_PROGRESS) + { + // if not running, do not cast things at the dropper player, neither send unnecessary messages + // just take off the aura + if(IsFlagPickedup() && GetFlagPickerGUID() == Source->GetGUID()) + { + SetFlagPicker(0); + Source->RemoveAurasDueToSpell(BG_EY_NETHERSTORM_FLAG_SPELL); + } + return; + } if(!IsFlagPickedup()) return; @@ -744,6 +763,8 @@ void BattleGroundEY::EventTeamCapturedPoint(Player *Source, uint32 Point) sLog.outError("BatteGroundEY: Failed to spawn spirit guide! point: %u, team: %u, graveyard_id: %u", Point, Team, m_CapturingPointTypes[Point].GraveYardId); +// SpawnBGCreature(Point,RESPAWN_IMMEDIATELY); + UpdatePointsIcons(Team, Point); UpdatePointsCount(Team); } diff --git a/src/game/BattleGroundHandler.cpp b/src/game/BattleGroundHandler.cpp index 3b744f043..13fd1d539 100644 --- a/src/game/BattleGroundHandler.cpp +++ b/src/game/BattleGroundHandler.cpp @@ -26,9 +26,11 @@ #include "MapManager.h" #include "ObjectAccessor.h" #include "Object.h" +#include "Chat.h" #include "BattleGroundMgr.h" #include "BattleGroundWS.h" #include "BattleGround.h" +#include "ArenaTeam.h" #include "Language.h" void WorldSession::HandleBattleGroundHelloOpcode( WorldPacket & recv_data ) @@ -76,18 +78,25 @@ void WorldSession::HandleBattleGroundJoinOpcode( WorldPacket & recv_data ) uint32 bgTypeId; uint32 instanceId; uint8 joinAsGroup; + Group * grp; recv_data >> guid; // battlemaster guid recv_data >> bgTypeId; // battleground type id (DBC id) recv_data >> instanceId; // instance id, 0 if First Available selected recv_data >> joinAsGroup; // join as group - sLog.outDebug( "WORLD: Recvd CMSG_BATTLEMASTER_JOIN Message from: " I64FMT " for BG (Type: %u)", guid, bgTypeId); - - if(bgTypeId >= MAX_BATTLEGROUND_TYPES) // cheating? + if(bgTypeId >= MAX_BATTLEGROUND_TYPES) + { + sLog.outError("Battleground: invalid bgtype received. possible cheater? player guid %u",_player->GetGUIDLow()); return; + } - // ignore if we already in BG or BG queue + sLog.outDebug( "WORLD: Recvd CMSG_BATTLEMASTER_JOIN Message from: " I64FMT, guid); + + // can do this, since it's battleground, not arena + uint32 bgQueueTypeId = sBattleGroundMgr.BGQueueTypeId(bgTypeId, 0); + + // ignore if player is already in BG if(_player->InBattleGround()) return; @@ -98,74 +107,82 @@ void WorldSession::HandleBattleGroundJoinOpcode( WorldPacket & recv_data ) if(!unit->isBattleMaster()) // it's not battlemaster return; - // check Deserter debuff - if( !_player->CanJoinToBattleground() ) + // get bg instance or bg template if instance not found + BattleGround * bg = 0; + if(instanceId) + BattleGround *bg = sBattleGroundMgr.GetBattleGround(instanceId); + + if(!bg && !(bg = sBattleGroundMgr.GetBattleGroundTemplate(bgTypeId))) { - WorldPacket data(SMSG_GROUP_JOINED_BATTLEGROUND, 4); - data << (uint32) 0xFFFFFFFE; - _player->GetSession()->SendPacket(&data); + sLog.outError("Battleground: no available bg / template found"); return; } - // check existence - BattleGround *bg = sBattleGroundMgr.GetBattleGround(bgTypeId); - if(!bg) - return; - - if(joinAsGroup && _player->GetGroup()) + // check queueing conditions + if(!joinAsGroup) { - Group *grp = _player->GetGroup(); + // check Deserter debuff + if( !_player->CanJoinToBattleground() ) + { + WorldPacket data(SMSG_GROUP_JOINED_BATTLEGROUND, 4); + data << (uint32) 0xFFFFFFFE; + _player->GetSession()->SendPacket(&data); + return; + } + // check if already in queue + if (_player->GetBattleGroundQueueIndex(bgQueueTypeId) < PLAYER_MAX_BATTLEGROUND_QUEUES) + //player is already in this queue + return; + // check if has free queue slots + if(!_player->HasFreeBattleGroundQueueId()) + return; + } + else + { + grp = _player->GetGroup(); + // no group found, error + if(!grp) + return; + uint32 err = grp->CanJoinBattleGroundQueue(bgTypeId, bgQueueTypeId, 0, bg->GetMaxPlayersPerTeam(), false, 0); + if (err != BG_JOIN_ERR_OK) + { + SendBattleGroundOrArenaJoinError(err); + return; + } + } + // if we're here, then the conditions to join a bg are met. We can proceed in joining. + + // _player->GetGroup() was already checked, grp is already initialized + if(joinAsGroup /* && _player->GetGroup()*/) + { + sLog.outDebug("Battleground: the following players are joining as group:"); + GroupQueueInfo * ginfo = sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].AddGroup(_player, bgTypeId, 0, false, 0); for(GroupReference *itr = grp->GetFirstMember(); itr != NULL; itr = itr->next()) { Player *member = itr->getSource(); - if(!member) continue; + if(!member) continue; // this should never happen - if( !member->CanJoinToBattleground() ) - { - WorldPacket data(SMSG_GROUP_JOINED_BATTLEGROUND, 4); - data << (uint32) 0xFFFFFFFE; - _player->GetSession()->SendPacket(&data); - continue; - } - if (member->InBattleGroundQueueForBattleGroundType(bgTypeId)) - //player is already in this queue - continue; - - WorldPacket data; - // add to queue - uint32 queueSlot = member->AddBattleGroundQueueId(bgTypeId); - if (queueSlot == PLAYER_MAX_BATTLEGROUND_QUEUES) - { - // fill data packet - //member->GetSession()->SendPacket(data); - continue; - } + uint32 queueSlot = member->AddBattleGroundQueueId(bgQueueTypeId); // add to queue // store entry point coords (same as leader entry point) member->SetBattleGroundEntryPoint(_player->GetMapId(),_player->GetPositionX(),_player->GetPositionY(),_player->GetPositionZ(),_player->GetOrientation()); + WorldPacket data; // send status packet (in queue) sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, member->GetTeam(), queueSlot, STATUS_WAIT_QUEUE, 0, 0); member->GetSession()->SendPacket(&data); sBattleGroundMgr.BuildGroupJoinedBattlegroundPacket(&data, bgTypeId); member->GetSession()->SendPacket(&data); - sBattleGroundMgr.m_BattleGroundQueues[bgTypeId].AddPlayer(member, bgTypeId); + sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].AddPlayer(member, ginfo); + sLog.outDebug("Battleground: player joined queue for bg queue type %u bg type %u: GUID %u, NAME %s",bgQueueTypeId,bgTypeId,member->GetGUIDLow(), member->GetName()); } + sLog.outDebug("Battleground: group end"); + sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].Update(bgTypeId, _player->GetBattleGroundQueueIdFromLevel()); } else { - if (_player->InBattleGroundQueueForBattleGroundType(bgTypeId)) - //player is already in this queue - return; - uint32 queueSlot = _player->AddBattleGroundQueueId(bgTypeId); - if (queueSlot == PLAYER_MAX_BATTLEGROUND_QUEUES) - { - WorldPacket data; - // fill data packet - //SendPacket(data); - return; - } - + // already checked if queueSlot is valid, now just get it + uint32 queueSlot = _player->AddBattleGroundQueueId(bgQueueTypeId); // store entry point coords _player->SetBattleGroundEntryPoint(_player->GetMapId(),_player->GetPositionX(),_player->GetPositionY(),_player->GetPositionZ(),_player->GetOrientation()); @@ -173,7 +190,11 @@ void WorldSession::HandleBattleGroundJoinOpcode( WorldPacket & recv_data ) // send status packet (in queue) sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, _player->GetTeam(), queueSlot, STATUS_WAIT_QUEUE, 0, 0); SendPacket(&data); - sBattleGroundMgr.m_BattleGroundQueues[bgTypeId].AddPlayer(_player, bgTypeId); + + GroupQueueInfo * ginfo = sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].AddGroup(_player, bgTypeId, 0, false, 0); + sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].AddPlayer(_player, ginfo); + sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].Update(bgTypeId, _player->GetBattleGroundQueueIdFromLevel()); + sLog.outDebug("Battleground: player joined queue for bg queue type %u bg type %u: GUID %u, NAME %s",bgQueueTypeId,bgTypeId,_player->GetGUIDLow(), _player->GetName()); } } @@ -247,12 +268,11 @@ void WorldSession::HandleBattleGroundListOpcode( WorldPacket &recv_data ) uint32 bgTypeId; recv_data >> bgTypeId; // id from DBC - if(bgTypeId >= MAX_BATTLEGROUND_TYPES) // cheating? - return; - - // can't be received if player not in BG queue - if(!_player->InBattleGroundQueueForBattleGroundType(bgTypeId)) + if(bgTypeId >= MAX_BATTLEGROUND_TYPES) + { + sLog.outError("Battleground: invalid bgtype received."); return; + } BattlemasterListEntry const* bl = sBattlemasterListStore.LookupEntry(bgTypeId); @@ -270,80 +290,201 @@ void WorldSession::HandleBattleGroundPlayerPortOpcode( WorldPacket &recv_data ) sLog.outDebug( "WORLD: Recvd CMSG_BATTLEFIELD_PORT Message"); - uint8 unk1; + uint8 type; // arenatype if arena uint8 unk2; // unk, can be 0x0 (may be if was invited?) and 0x1 + uint32 instanceId; uint32 bgTypeId; // type id from dbc uint16 unk; // 0x1F90 constant? uint8 action; // enter battle 0x1, leave queue 0x0 - recv_data >> unk1 >> unk2 >> bgTypeId >> unk >> action; + recv_data >> type >> unk2 >> bgTypeId >> unk >> action; - if(bgTypeId >= MAX_BATTLEGROUND_TYPES) // cheating? - return; - - if(!_player->InBattleGroundQueueForBattleGroundType(bgTypeId)) - return; - - BattleGround *bg = sBattleGroundMgr.GetBattleGround(bgTypeId); - if(!bg) - return; - - uint32 queueSlot = 0; - WorldPacket data; - switch(action) + if(bgTypeId >= MAX_BATTLEGROUND_TYPES) { - case 1: // port to battleground - // cheating? - if(!_player->IsInvitedForBattleGroundType(bgTypeId)) - return; - - // check if player is not deserter - if( !_player->CanJoinToBattleground() ) + sLog.outError("Battleground: invalid bgtype received."); + // update battleground slots for the player to fix his UI and sent data. + // this is a HACK, I don't know why the client starts sending invalid packets in the first place. + // it usually happens with extremely high latency (if debugging / stepping in the code for example) + if(_player->InBattleGroundQueue()) + { + // update all queues, send invitation info if player is invited, queue info if queued + for (uint32 i = 0; i < PLAYER_MAX_BATTLEGROUND_QUEUES; i++) { - WorldPacket data2; - data2.Initialize(SMSG_GROUP_JOINED_BATTLEGROUND, 4); - data2 << (uint32) 0xFFFFFFFE; - SendPacket(&data2); - return; + uint32 queue_id = _player->GetBattleGroundQueueId(i); + if(!queue_id) + continue; + BattleGroundQueue::QueuedPlayersMap::iterator itrPlayerStatus = sBattleGroundMgr.m_BattleGroundQueues[queue_id].m_QueuedPlayers[_player->GetBattleGroundQueueIdFromLevel()].find(_player->GetGUID()); + // if the player is not in queue, contine + if(itrPlayerStatus == sBattleGroundMgr.m_BattleGroundQueues[queue_id].m_QueuedPlayers[_player->GetBattleGroundQueueIdFromLevel()].end()) + continue; + + // no group information, this should never happen + if(!itrPlayerStatus->second.GroupInfo) + continue; + + BattleGround * bg = NULL; + + // get possibly needed data from groupinfo + bgTypeId = itrPlayerStatus->second.GroupInfo->BgTypeId; + uint8 arenatype = itrPlayerStatus->second.GroupInfo->ArenaType; + uint8 israted = itrPlayerStatus->second.GroupInfo->IsRated; + uint8 status = 0; + + + if(!itrPlayerStatus->second.GroupInfo->IsInvitedToBGInstanceGUID) + { + // not invited to bg, get template + bg = sBattleGroundMgr.GetBattleGroundTemplate(bgTypeId); + status = STATUS_WAIT_QUEUE; + } + else + { + // get the bg we're invited to + BattleGround * bg = sBattleGroundMgr.GetBattleGround(itrPlayerStatus->second.GroupInfo->IsInvitedToBGInstanceGUID); + status = STATUS_WAIT_JOIN; + } + + // if bg not found, then continue + if(!bg) + continue; + + // don't invite if already in the instance + if(_player->InBattleGround() && _player->GetBattleGround() && _player->GetBattleGround()->GetInstanceID() == bg->GetInstanceID()) + continue; + + // re - invite player with proper data + WorldPacket data; + sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, itrPlayerStatus->second.GroupInfo->Team?itrPlayerStatus->second.GroupInfo->Team:_player->GetTeam(), i, status, INVITE_ACCEPT_WAIT_TIME, 0, arenatype, israted); + SendPacket(&data); } + } + return; + } - // if the player is dead, resurrect him before teleport - if(!_player->isAlive()) - { - _player->ResurrectPlayer(1.0f); - _player->SpawnCorpseBones(); - } + uint32 bgQueueTypeId = 0; + // get the bg what we were invited to + BattleGroundQueue::QueuedPlayersMap::iterator itrPlayerStatus; + bgQueueTypeId = sBattleGroundMgr.BGQueueTypeId(bgTypeId,type); + itrPlayerStatus = sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].m_QueuedPlayers[_player->GetBattleGroundQueueIdFromLevel()].find(_player->GetGUID()); - // leave current group - _player->RemoveFromGroup(); + if(itrPlayerStatus == sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].m_QueuedPlayers[_player->GetBattleGroundQueueIdFromLevel()].end()) + { + sLog.outError("Battleground: itrplayerstatus not found."); + return; + } + instanceId = itrPlayerStatus->second.GroupInfo->IsInvitedToBGInstanceGUID; - // packet to player about BG status - queueSlot = _player->GetBattleGroundQueueIndex(bgTypeId); - sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, _player->GetTeam(), queueSlot, STATUS_IN_PROGRESS, 0, bg->GetStartTime()); - _player->GetSession()->SendPacket(&data); + // if action == 1, then instanceId is _required_ + if(!instanceId && action == 1) + { + sLog.outError("Battleground: instance not found."); + return; + } - // remove battleground queue status from BGmgr - sBattleGroundMgr.m_BattleGroundQueues[bgTypeId].RemovePlayer(_player->GetGUID(), false); + BattleGround *bg = sBattleGroundMgr.GetBattleGround(instanceId); - // this is still needed here if battleground "jumping" shouldn't add deserter debuff - // also this required to prevent stuck at old battleground after SetBattleGroundId set to new - if (BattleGround *currentBg = _player->GetBattleGround()) - currentBg->RemovePlayerAtLeave(_player->GetGUID(), false, true); + // bg template might and must be used in case of leaving queue, when instance is not created yet + if(!bg && action == 0) + bg = sBattleGroundMgr.GetBattleGroundTemplate(bgTypeId); - _player->SetBattleGroundId(bg->GetTypeID()); - sBattleGroundMgr.SendToBattleGround(_player, bgTypeId); - bg->AddPlayer(_player); - break; - case 0: // leave queue - queueSlot = _player->GetBattleGroundQueueIndex(bgTypeId); - _player->RemoveBattleGroundQueueId(bgTypeId); // must be called this way, because if you move this call to queue->removeplayer, it causes bugs - sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, _player->GetTeam(), queueSlot, STATUS_NONE, 0, 0); - sBattleGroundMgr.m_BattleGroundQueues[bgTypeId].RemovePlayer(_player->GetGUID(), true); - SendPacket(&data); - break; - default: - sLog.outError("Battleground port: unknown action %u", action); - break; + if(!bg) + { + sLog.outError("Battleground: bg not found."); + return; + } + + bgTypeId = bg->GetTypeID(); + + if(_player->InBattleGroundQueue()) + { + uint32 queueSlot = 0; + uint32 team = 0; + uint32 arenatype = 0; + uint32 israted = 0; + uint32 rating = 0; + uint32 opponentsRating = 0; + // get the team info from the queue + BattleGroundQueue::QueuedPlayersMap::iterator pitr = sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].m_QueuedPlayers[_player->GetBattleGroundQueueIdFromLevel()].find(_player->GetGUID()); + if(pitr !=sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].m_QueuedPlayers[_player->GetBattleGroundQueueIdFromLevel()].end() + && pitr->second.GroupInfo ) + { + team = pitr->second.GroupInfo->Team; + arenatype = pitr->second.GroupInfo->ArenaType; + israted = pitr->second.GroupInfo->IsRated; + rating = pitr->second.GroupInfo->ArenaTeamRating; + opponentsRating = pitr->second.GroupInfo->OpponentsTeamRating; + } + else + { + sLog.outError("Battleground: Invalid player queue info!"); + return; + } + WorldPacket data; + switch(action) + { + case 1: // port to battleground + if(!_player->IsInvitedForBattleGroundQueueType(bgQueueTypeId)) + return; // cheating? + // resurrect the player + if(!_player->isAlive()) + { + _player->ResurrectPlayer(1.0f); + _player->SpawnCorpseBones(); + } + // stop taxi flight at port + if(_player->isInFlight()) + { + _player->GetMotionMaster()->MovementExpired(); + _player->m_taxi.ClearTaxiDestinations(); + } + _player->RemoveFromGroup(); + queueSlot = _player->GetBattleGroundQueueIndex(bgQueueTypeId); + sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, _player->GetTeam(), queueSlot, STATUS_IN_PROGRESS, 0, bg->GetStartTime()); + _player->GetSession()->SendPacket(&data); + // remove battleground queue status from BGmgr + sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].RemovePlayer(_player->GetGUID(), false); + // this is still needed here if battleground "jumping" shouldn't add deserter debuff + // also this required to prevent stuck at old battleground after SetBattleGroundId set to new + if( BattleGround *currentBg = _player->GetBattleGround() ) + currentBg->RemovePlayerAtLeave(_player->GetGUID(), false, true); + + // set the destination instance id + _player->SetBattleGroundId(bg->GetInstanceID()); + // set the destination team + _player->SetBGTeam(team); + // bg->HandleBeforeTeleportToBattleGround(_player); + sBattleGroundMgr.SendToBattleGround(_player, instanceId); + // add only in HandleMoveWorldPortAck() + // bg->AddPlayer(_player,team); + sLog.outDebug("Battleground: player %s (%u) joined battle for bg %u, bgtype %u, queue type %u.",_player->GetName(),_player->GetGUIDLow(),bg->GetInstanceID(),bg->GetTypeID(),bgQueueTypeId); + break; + case 0: // leave queue + queueSlot = _player->GetBattleGroundQueueIndex(bgQueueTypeId); + /* + if player leaves rated arena match before match start, it is counted as he played but he lost + */ + if (israted) + { + ArenaTeam * at = objmgr.GetArenaTeamById(team); + if (at) + { + sLog.outDebug("UPDATING memberLost's personal arena rating for %u by opponents rating: %u, because he has left queue!", GUID_LOPART(_player->GetGUID()), opponentsRating); + at->MemberLost(_player, opponentsRating); + at->SaveToDB(); + } + } + _player->RemoveBattleGroundQueueId(bgQueueTypeId); // must be called this way, because if you move this call to queue->removeplayer, it causes bugs + sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, _player->GetTeam(), queueSlot, STATUS_NONE, 0, 0); + sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].RemovePlayer(_player->GetGUID(), true); + // player left queue, we should update it, maybe now his group fits in + sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].Update(bgTypeId,_player->GetBattleGroundQueueIdFromLevel(),arenatype,israted,rating); + SendPacket(&data); + sLog.outDebug("Battleground: player %s (%u) left queue for bgtype %u, queue type %u.",_player->GetName(),_player->GetGUIDLow(),bg->GetTypeID(),bgQueueTypeId); + break; + default: + sLog.outError("Battleground port: unknown action %u", action); + break; + } } } @@ -384,7 +525,8 @@ void WorldSession::HandleBattlefieldStatusOpcode( WorldPacket & /*recv_data*/ ) BattleGround *bg = _player->GetBattleGround(); if(bg) { - uint32 queueSlot = _player->GetBattleGroundQueueIndex(bg->GetTypeID()); + uint32 bgQueueTypeId = sBattleGroundMgr.BGQueueTypeId(bg->GetTypeID(), bg->GetArenaType()); + uint32 queueSlot = _player->GetBattleGroundQueueIndex(bgQueueTypeId); if((bg->GetStatus() <= STATUS_IN_PROGRESS)) { sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, _player->GetTeam(), queueSlot, STATUS_IN_PROGRESS, 0, bg->GetStartTime()); @@ -392,15 +534,25 @@ void WorldSession::HandleBattlefieldStatusOpcode( WorldPacket & /*recv_data*/ ) } for (uint32 i = 0; i < PLAYER_MAX_BATTLEGROUND_QUEUES; i++) { - uint32 queue_id = _player->GetBattleGroundQueueId(i); - if (i == queueSlot || !queue_id) + uint32 queue_id = _player->GetBattleGroundQueueId(i); // battlegroundqueueid stores the type id, not the instance id, so this is definitely wrong + uint8 arenatype = sBattleGroundMgr.BGArenaType(queue_id); + uint8 isRated = 0; + if (i == queueSlot || !queue_id) // we need to get the instance ids continue; - BattleGround *bg2 = sBattleGroundMgr.GetBattleGround(queue_id); + BattleGroundQueue::QueuedPlayersMap::iterator itrPlayerStatus = sBattleGroundMgr.m_BattleGroundQueues[queue_id].m_QueuedPlayers[_player->GetBattleGroundQueueIdFromLevel()].find(_player->GetGUID()); + if(itrPlayerStatus == sBattleGroundMgr.m_BattleGroundQueues[queue_id].m_QueuedPlayers[_player->GetBattleGroundQueueIdFromLevel()].end()) + continue; + if(itrPlayerStatus->second.GroupInfo) + { + arenatype = itrPlayerStatus->second.GroupInfo->ArenaType; + isRated = itrPlayerStatus->second.GroupInfo->IsRated; + } + BattleGround *bg2 = sBattleGroundMgr.GetBattleGroundTemplate(sBattleGroundMgr.BGTemplateId(queue_id)); // try this if(bg2) { //in this call is small bug, this call should be filled by player's waiting time in queue //this call nulls all timers for client : - sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg2, _player->GetTeam(), i, STATUS_WAIT_QUEUE, 0, 0); + sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg2, _player->GetTeam(), i, STATUS_WAIT_QUEUE, 0, 0,arenatype,isRated); SendPacket(&data); } } @@ -411,16 +563,36 @@ void WorldSession::HandleBattlefieldStatusOpcode( WorldPacket & /*recv_data*/ ) // we should update all queues? .. i'm not sure if this code is correct for (uint32 i = 0; i < PLAYER_MAX_BATTLEGROUND_QUEUES; i++) { - if(uint32 queue_id = _player->GetBattleGroundQueueId(i)) + uint32 queue_id = _player->GetBattleGroundQueueId(i); + if(!queue_id) + continue; + uint32 bgTypeId = sBattleGroundMgr.BGTemplateId(queue_id); + uint8 arenatype = sBattleGroundMgr.BGArenaType(queue_id); + uint8 isRated = 0; + BattleGround *bg = sBattleGroundMgr.GetBattleGroundTemplate(bgTypeId); + BattleGroundQueue::QueuedPlayersMap::iterator itrPlayerStatus = sBattleGroundMgr.m_BattleGroundQueues[queue_id].m_QueuedPlayers[_player->GetBattleGroundQueueIdFromLevel()].find(_player->GetGUID()); + if(itrPlayerStatus == sBattleGroundMgr.m_BattleGroundQueues[queue_id].m_QueuedPlayers[_player->GetBattleGroundQueueIdFromLevel()].end()) + continue; + if(itrPlayerStatus->second.GroupInfo) { - if(BattleGround *bg = sBattleGroundMgr.GetBattleGround(queue_id)) - { - sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, _player->GetTeam(), i, STATUS_WAIT_QUEUE, 0, 0); - SendPacket(&data); - } + arenatype = itrPlayerStatus->second.GroupInfo->ArenaType; + isRated = itrPlayerStatus->second.GroupInfo->IsRated; + } + if(bg && queue_id) + { + sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, _player->GetTeam(), i, STATUS_WAIT_QUEUE, 0, 0, arenatype, isRated); + SendPacket(&data); } } } +/* else // not sure if it needed... + { + for (uint32 i = 0; i < PLAYER_MAX_BATTLEGROUND_QUEUES; i++) + { + sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, NULL, _player->GetTeam(),i , STATUS_NONE, 0, 0); + SendPacket(&data); + } + }*/ } void WorldSession::HandleAreaSpiritHealerQueryOpcode( WorldPacket & recv_data ) @@ -480,16 +652,12 @@ void WorldSession::HandleBattleGroundArenaJoin( WorldPacket & recv_data ) if(_player->InBattleGround()) return; - for(int qId = 0; qId < PLAYER_MAX_BATTLEGROUND_QUEUES; ++qId) - { - if(_player->GetBattleGroundQueueId(qId) != 0) - return; - } - uint64 guid; // arena Battlemaster guid uint8 type; // 2v2, 3v3 or 5v5 uint8 asGroup; // asGroup uint8 isRated; // isRated + Group * grp; + recv_data >> guid >> type >> asGroup >> isRated; Creature *unit = ObjectAccessor::GetCreature(*_player, guid); @@ -500,6 +668,7 @@ void WorldSession::HandleBattleGroundArenaJoin( WorldPacket & recv_data ) return; uint8 arenatype = 0; + uint32 arenaRating = 0; switch(type) { @@ -517,88 +686,118 @@ void WorldSession::HandleBattleGroundArenaJoin( WorldPacket & recv_data ) return; } - if(isRated && !_player->GetArenaTeamId(type)) // player not in arena team of that size + //check existance + BattleGround* bg = NULL; + if( !(bg = sBattleGroundMgr.GetBattleGroundTemplate(BATTLEGROUND_AA)) ) { - _player->GetSession()->SendNotInArenaTeamPacket(arenatype); + sLog.outError("Battleground: template bg (all arenas) not found"); return; } - if(asGroup && !_player->GetGroup()) // player not in group - return; + uint8 bgTypeId = bg->GetTypeID(); + uint32 bgQueueTypeId = sBattleGroundMgr.BGQueueTypeId(bgTypeId, arenatype); - // check existence - BattleGround *bg = sBattleGroundMgr.GetBattleGround(BATTLEGROUND_AA); - if(!bg) - return; - - bg->SetArenaType(arenatype); - bg->SetRated(isRated); - - if(asGroup && _player->GetGroup()) + // check queueing conditions + if(!asGroup) { - Group *grp = _player->GetGroup(); + // check if already in queue + if (_player->GetBattleGroundQueueIndex(bgQueueTypeId) < PLAYER_MAX_BATTLEGROUND_QUEUES) + //player is already in this queue + return; + // check if has free queue slots + if(!_player->HasFreeBattleGroundQueueId()) + return; + } + else + { + grp = _player->GetGroup(); + // no group found, error + if(!grp) + return; + uint32 err = grp->CanJoinBattleGroundQueue(bgTypeId, bgQueueTypeId, arenatype, arenatype, (bool)isRated, type); + if (err != BG_JOIN_ERR_OK) + { + SendBattleGroundOrArenaJoinError(err); + return; + } + } + + uint32 ateamId = 0; + + if(isRated) + { + ateamId = _player->GetArenaTeamId(type); + // check real arenateam existence only here (if it was moved to group->CanJoin .. () then we would ahve to get it twice) + ArenaTeam * at = objmgr.GetArenaTeamById(ateamId); + if(!at) + { + _player->GetSession()->SendNotInArenaTeamPacket(arenatype); + return; + } + // get the team rating for queueing + arenaRating = at->GetRating(); + // the arenateam id must match for everyone in the group + // get the personal ratings for queueing + uint32 avg_pers_rating = 0; + for(GroupReference *itr = grp->GetFirstMember(); itr != NULL; itr = itr->next()) + { + Player *member = itr->getSource(); + + // calc avg personal rating + avg_pers_rating += member->GetUInt32Value(PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + (type*6) + 5); + } + + if( arenatype ) + avg_pers_rating /= arenatype; + + // if avg personal rating is more than 150 points below the teams rating, the team will be queued against an opponent matching or similar to the average personal rating + if(avg_pers_rating + 150 < arenaRating) + arenaRating = avg_pers_rating; + } + + if(asGroup) + { + GroupQueueInfo * ginfo = sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].AddGroup(_player, bgTypeId, arenatype, isRated, arenaRating, ateamId); + sLog.outDebug("Battleground: arena join as group start"); + if(isRated) + sLog.outDebug("Battleground: arena team id %u, leader %s queued with rating %u for type %u",_player->GetArenaTeamId(type),_player->GetName(),arenaRating,arenatype); for(GroupReference *itr = grp->GetFirstMember(); itr != NULL; itr = itr->next()) { Player *member = itr->getSource(); if(!member) continue; - /*if (!member->CanJoinToBattleground()) - //player has deserter aura .. do nothing - */ - - if (member->InBattleGroundQueueForBattleGroundType(BATTLEGROUND_AA)) - //player is already in this queue - continue; - - // add to queue - uint32 queueSlot = member->AddBattleGroundQueueId(BATTLEGROUND_AA); - if (queueSlot == PLAYER_MAX_BATTLEGROUND_QUEUES) - { - WorldPacket data; - //fill data - //member->GetSession()->SendPacket(data); - continue; - } + uint32 queueSlot = member->AddBattleGroundQueueId(bgQueueTypeId);// add to queue // store entry point coords (same as leader entry point) member->SetBattleGroundEntryPoint(_player->GetMapId(),_player->GetPositionX(),_player->GetPositionY(),_player->GetPositionZ(),_player->GetOrientation()); WorldPacket data; // send status packet (in queue) - sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, member->GetTeam(), queueSlot, STATUS_WAIT_QUEUE, 0, 0); + sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, member->GetTeam(), queueSlot, STATUS_WAIT_QUEUE, 0, 0, arenatype, isRated); member->GetSession()->SendPacket(&data); - sBattleGroundMgr.BuildGroupJoinedBattlegroundPacket(&data, BATTLEGROUND_AA); + sBattleGroundMgr.BuildGroupJoinedBattlegroundPacket(&data, bgTypeId); member->GetSession()->SendPacket(&data); - sBattleGroundMgr.m_BattleGroundQueues[BATTLEGROUND_AA].AddPlayer(member, BATTLEGROUND_AA); + sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].AddPlayer(member, ginfo); + sLog.outDebug("Battleground: player joined queue for arena as group bg queue type %u bg type %u: GUID %u, NAME %s",bgQueueTypeId,bgTypeId,member->GetGUIDLow(), member->GetName()); } + sLog.outDebug("Battleground: arena join as group end"); + sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].Update(bgTypeId, _player->GetBattleGroundQueueIdFromLevel(), arenatype, isRated, arenaRating); } else { - /*if (!member->CanJoinToBattleground()) - //player has deserter aura .. do nothing - */ - - if (_player->InBattleGroundQueueForBattleGroundType(BATTLEGROUND_AA)) - //player is already in this queue - return; - - uint32 queueSlot = _player->AddBattleGroundQueueId(BATTLEGROUND_AA); - if (queueSlot == PLAYER_MAX_BATTLEGROUND_QUEUES) - { - WorldPacket data; - //fill data (player is in 3 queues already) - //SendPacket(data); - return; - } + uint32 queueSlot = _player->AddBattleGroundQueueId(bgQueueTypeId); // store entry point coords _player->SetBattleGroundEntryPoint(_player->GetMapId(),_player->GetPositionX(),_player->GetPositionY(),_player->GetPositionZ(),_player->GetOrientation()); WorldPacket data; // send status packet (in queue) - sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, _player->GetTeam(), queueSlot, STATUS_WAIT_QUEUE, 0, 0); + sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, _player->GetTeam(), queueSlot, STATUS_WAIT_QUEUE, 0, 0, arenatype, isRated); SendPacket(&data); - sBattleGroundMgr.m_BattleGroundQueues[BATTLEGROUND_AA].AddPlayer(_player, BATTLEGROUND_AA); + GroupQueueInfo * ginfo = sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].AddGroup(_player, bgTypeId, arenatype, isRated, arenaRating); + sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].AddPlayer(_player, ginfo); + sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].Update(bgTypeId, _player->GetBattleGroundQueueIdFromLevel(), arenatype, isRated, arenaRating); + sLog.outDebug("Battleground: player joined queue for arena, skirmish, bg queue type %u bg type %u: GUID %u, NAME %s",bgQueueTypeId,bgTypeId,_player->GetGUIDLow(), _player->GetName()); } } @@ -620,3 +819,41 @@ void WorldSession::HandleBattleGroundReportAFK( WorldPacket & recv_data ) reportedPlayer->ReportedAfkBy(_player); } + +void WorldSession::SendBattleGroundOrArenaJoinError(uint8 err) +{ + WorldPacket data; + int32 msg; + switch (err) + { + case BG_JOIN_ERR_OFFLINE_MEMBER: + msg = LANG_BG_GROUP_OFFLINE_MEMBER; + break; + case BG_JOIN_ERR_GROUP_TOO_MANY: + msg = LANG_BG_GROUP_TOO_LARGE; + break; + case BG_JOIN_ERR_MIXED_FACTION: + msg = LANG_BG_GROUP_MIXED_FACTION; + break; + case BG_JOIN_ERR_MIXED_LEVELS: + msg = LANG_BG_GROUP_MIXED_LEVELS; + break; + case BG_JOIN_ERR_GROUP_MEMBER_ALREADY_IN_QUEUE: + msg = LANG_BG_GROUP_MEMBER_ALREADY_IN_QUEUE; + break; + case BG_JOIN_ERR_GROUP_DESERTER: + msg = LANG_BG_GROUP_MEMBER_DESERTER; + break; + case BG_JOIN_ERR_ALL_QUEUES_USED: + msg = LANG_BG_GROUP_MEMBER_NO_FREE_QUEUE_SLOTS; + break; + case BG_JOIN_ERR_GROUP_NOT_ENOUGH: + case BG_JOIN_ERR_MIXED_ARENATEAM: + default: + return; + break; + } + ChatHandler::FillMessageData(&data, NULL, CHAT_MSG_BG_SYSTEM_NEUTRAL, LANG_UNIVERSAL, NULL, 0, GetMangosString(msg), NULL); + SendPacket(&data); + return; +} diff --git a/src/game/BattleGroundMgr.cpp b/src/game/BattleGroundMgr.cpp index 9c3350bd1..ce456f6d1 100644 --- a/src/game/BattleGroundMgr.cpp +++ b/src/game/BattleGroundMgr.cpp @@ -30,10 +30,13 @@ #include "SharedDefines.h" #include "Policies/SingletonImp.h" #include "MapManager.h" +#include "Map.h" +#include "MapInstanced.h" #include "ObjectMgr.h" #include "ProgressBar.h" #include "World.h" #include "Chat.h" +#include "ArenaTeam.h" INSTANTIATE_SINGLETON_1( BattleGroundMgr ); @@ -44,12 +47,12 @@ INSTANTIATE_SINGLETON_1( BattleGroundMgr ); BattleGroundQueue::BattleGroundQueue() { //queues are empty, we don't have to call clear() - for (int i = 0; i < MAX_BATTLEGROUND_QUEUES; i++) +/* for (int i = 0; i < MAX_BATTLEGROUND_QUEUES; i++) { - m_QueuedPlayers[i].Horde = 0; - m_QueuedPlayers[i].Alliance = 0; + //m_QueuedPlayers[i].Horde = 0; + //m_QueuedPlayers[i].Alliance = 0; //m_QueuedPlayers[i].AverageTime = 0; - } + }*/ } BattleGroundQueue::~BattleGroundQueue() @@ -57,31 +60,188 @@ BattleGroundQueue::~BattleGroundQueue() for (int i = 0; i < MAX_BATTLEGROUND_QUEUES; i++) { m_QueuedPlayers[i].clear(); + for(QueuedGroupsList::iterator itr = m_QueuedGroups[i].begin(); itr!= m_QueuedGroups[i].end(); ++itr) + { + delete (*itr); + } + m_QueuedGroups[i].clear(); } } -void BattleGroundQueue::AddPlayer(Player *plr, uint32 bgTypeId) +// initialize eligible groups from the given source matching the given specifications +void BattleGroundQueue::EligibleGroups::Init(BattleGroundQueue::QueuedGroupsList *source, uint32 BgTypeId, uint32 side, uint32 MaxPlayers, uint8 ArenaType, bool IsRated, uint32 MinRating, uint32 MaxRating, uint32 DisregardTime, uint32 excludeTeam) +{ + // clear from prev initialization + clear(); + BattleGroundQueue::QueuedGroupsList::iterator itr, next; + // iterate through the source + for(itr = source->begin(); itr!= source->end(); itr = next) + { + next = itr; + ++next; + if( (*itr)->BgTypeId == BgTypeId && // bg type must match + (*itr)->ArenaType == ArenaType && // arena type must match + (*itr)->IsRated == IsRated && // israted must match + (*itr)->IsInvitedToBGInstanceGUID == 0 && // leave out already invited groups + (*itr)->Team == side && // match side + (*itr)->Players.size() <= MaxPlayers && // the group must fit in the bg + ( !excludeTeam || (*itr)->ArenaTeamId != excludeTeam ) && // if excludeTeam is specified, leave out those arena team ids + ( !IsRated || (*itr)->Players.size() == MaxPlayers ) && // if rated, then pass only if the player count is exact NEEDS TESTING! (but now this should never happen) + ( (*itr)->JoinTime <= DisregardTime // pass if disregard time is greater than join time + || (*itr)->ArenaTeamRating == 0 // pass if no rating info + || ( (*itr)->ArenaTeamRating >= MinRating // pass if matches the rating range + && (*itr)->ArenaTeamRating <= MaxRating ) ) ) + { + // the group matches the conditions + // insert it in order of groupsize, and join time + uint32 size = (*itr)->Players.size(); + uint32 jointime = (*itr)->JoinTime; + bool inserted = false; + + for(std::list::iterator elig_itr = begin(); elig_itr != end(); ++elig_itr) + { + // if the next one's size is smaller, then insert + // also insert if the next one's size is equal, but it joined the queue later + if( ((*elig_itr)->Players.size()Players.size() == size && (*elig_itr)->JoinTime > jointime) ) + { + insert(elig_itr,(*itr)); + inserted = true; + break; + } + } + // if not inserted -> this is the smallest group -> push_back + if(!inserted) + { + push_back((*itr)); + } + } + } +} + +// remove group from eligible groups +// used when building selection pools +void BattleGroundQueue::EligibleGroups::RemoveGroup(GroupQueueInfo * ginfo) +{ + for(std::list::iterator itr = begin(); itr != end(); ++itr) + { + if((*itr)==ginfo) + { + erase(itr); + return; + } + } +} + +// selection pool initialization, used to clean up from prev selection +void BattleGroundQueue::SelectionPool::Init() +{ + SelectedGroups.clear(); + MaxGroup = 0; + PlayerCount = 0; +} + +// get the maximal group from the selection pool +// used when building the pool, and have to remove the largest +GroupQueueInfo * BattleGroundQueue::SelectionPool::GetMaximalGroup() +{ + if(SelectedGroups.empty()) + { + sLog.outError("Getting max group when selection pool is empty, this should never happen."); + MaxGroup = NULL; + return 0; + } + // actually select the max group if it's not set + if(MaxGroup==0 && !SelectedGroups.empty()) + { + uint32 max_size = 0; + for(std::list::iterator itr = SelectedGroups.begin(); itr != SelectedGroups.end(); ++itr) + { + if(max_size<(*itr)->Players.size()) + { + MaxGroup =(*itr); + max_size = MaxGroup->Players.size(); + } + } + } + return MaxGroup; +} + +// remove group info from selection pool +// used when building selection pools and have to remove maximal group +void BattleGroundQueue::SelectionPool::RemoveGroup(GroupQueueInfo *ginfo) +{ + // uninitiate max group info if needed + if(MaxGroup == ginfo) + MaxGroup = 0; + // find what to remove + for(std::list::iterator itr = SelectedGroups.begin(); itr != SelectedGroups.end(); ++itr) + { + if((*itr)==ginfo) + { + SelectedGroups.erase(itr); + // decrease selected players count + PlayerCount -= ginfo->Players.size(); + return; + } + } +} + +// add group to selection +// used when building selection pools +void BattleGroundQueue::SelectionPool::AddGroup(GroupQueueInfo * ginfo) +{ + SelectedGroups.push_back(ginfo); + // increase selected players count + PlayerCount+=ginfo->Players.size(); + if(!MaxGroup || ginfo->Players.size() > MaxGroup->Players.size()) + { + // update max group info if needed + MaxGroup = ginfo; + } +} + +// add group to bg queue with the given leader and bg specifications +GroupQueueInfo * BattleGroundQueue::AddGroup(Player *leader, uint32 BgTypeId, uint8 ArenaType, bool isRated, uint32 arenaRating, uint32 arenateamid) +{ + uint32 queue_id = leader->GetBattleGroundQueueIdFromLevel(); + + // create new ginfo + // cannot use the method like in addplayer, because that could modify an in-queue group's stats + // (e.g. leader leaving queue then joining as individual again) + GroupQueueInfo* ginfo = new GroupQueueInfo; + ginfo->BgTypeId = BgTypeId; + ginfo->ArenaType = ArenaType; + ginfo->ArenaTeamId = arenateamid; + ginfo->IsRated = isRated; + ginfo->IsInvitedToBGInstanceGUID = 0; // maybe this should be modifiable by function arguments to enable selection of running instances? + ginfo->JoinTime = getMSTime(); + ginfo->Team = leader->GetTeam(); + ginfo->ArenaTeamRating = arenaRating; + ginfo->OpponentsTeamRating = 0; //initialize it to 0 + + ginfo->Players.clear(); + + m_QueuedGroups[queue_id].push_back(ginfo); + + // return ginfo, because it is needed to add players to this group info + return ginfo; +} + +void BattleGroundQueue::AddPlayer(Player *plr, GroupQueueInfo *ginfo) { uint32 queue_id = plr->GetBattleGroundQueueIdFromLevel(); //if player isn't in queue, he is added, if already is, then values are overwritten, no memory leak PlayerQueueInfo& info = m_QueuedPlayers[queue_id][plr->GetGUID()]; info.InviteTime = 0; - info.IsInvitedToBGInstanceGUID = 0; info.LastInviteTime = 0; info.LastOnlineTime = getMSTime(); - info.Team = plr->GetTeam(); - - //add player to waiting order queue - m_PlayersSortedByWaitTime[queue_id].push_back(plr->GetGUID()); - - if(plr->GetTeam() == ALLIANCE) - ++m_QueuedPlayers[queue_id].Alliance; - else - ++m_QueuedPlayers[queue_id].Horde; - - Update(bgTypeId, queue_id); + info.GroupInfo = ginfo; + // add the pinfo to ginfo's list + ginfo->Players[plr->GetGUID()] = &info; +/* if( sWorld.getConfig(CONFIG_BATTLEGROUND_QUEUE_ANNOUNCER_ENABLE) ) { BattleGround* bg = sBattleGroundMgr.GetBattleGround(bgTypeId); @@ -111,7 +271,8 @@ void BattleGroundQueue::AddPlayer(Player *plr, uint32 bgTypeId) sWorld.SendWorldText(LANG_BG_QUEUE_ANNOUNCE_WORLD, bgName, q_min_level, q_max_level, qAlliance, (MinPlayers > qAlliance) ? (MinPlayers - qAlliance) : 0, qHorde, (MinPlayers > qHorde) ? (MinPlayers - qHorde) : 0); } - } + + }*/ } void BattleGroundQueue::RemovePlayer(uint64 guid, bool decreaseInvitedCount) @@ -120,11 +281,22 @@ void BattleGroundQueue::RemovePlayer(uint64 guid, bool decreaseInvitedCount) uint32 queue_id = 0; QueuedPlayersMap::iterator itr; + GroupQueueInfo * group; + QueuedGroupsList::iterator group_itr; bool IsSet = false; - if(!plr) - { //player is offline, we need to find him somewhere in queues - /// there is something wrong if this code is run, because we have in queue only online players! - sLog.outError("Battleground: removing offline player from BG queue - this might not happen, but it should not cause crash"); + if(plr) + { + queue_id = plr->GetBattleGroundQueueIdFromLevel(); + + itr = m_QueuedPlayers[queue_id].find(guid); + if(itr != m_QueuedPlayers[queue_id].end()) + IsSet = true; + } + + if(!IsSet) + { + // either player is offline, or he levelled up to another queue category + // sLog.outError("Battleground: removing offline player from BG queue - this might not happen, but it should not cause crash"); for (uint32 i = 0; i < MAX_BATTLEGROUND_QUEUES; i++) { itr = m_QueuedPlayers[i].find(guid); @@ -136,44 +308,248 @@ void BattleGroundQueue::RemovePlayer(uint64 guid, bool decreaseInvitedCount) } } } - else - { //player is online, we have his level, so we can find exact queue from his level - queue_id = plr->GetBattleGroundQueueIdFromLevel(); - itr = m_QueuedPlayers[queue_id].find(guid); - IsSet = true; + + // couldn't find the player in bg queue, return + if(!IsSet) + { + sLog.outError("Battleground: couldn't find player to remove."); + return; } - //all variables are set, so remove player - //remove player from time queue - m_PlayersSortedByWaitTime[queue_id].remove(guid); + group = itr->second.GroupInfo; - if (IsSet && itr != m_QueuedPlayers[queue_id].end()) + for(group_itr=m_QueuedGroups[queue_id].begin(); group_itr != m_QueuedGroups[queue_id].end(); ++group_itr) { - if (!itr->second.IsInvitedToBGInstanceGUID) + if(group == (GroupQueueInfo*)(*group_itr)) + break; + } + + // variables are set (what about leveling up when in queue????) + // remove player from group + // if only player there, remove group + + // remove player queue info from group queue info + std::map::iterator pitr = group->Players.find(guid); + + if(pitr != group->Players.end()) + group->Players.erase(pitr); + + // check for iterator correctness + if (group_itr != m_QueuedGroups[queue_id].end() && itr != m_QueuedPlayers[queue_id].end()) + { + // used when player left the queue, NOT used when porting to bg + if (decreaseInvitedCount) { - if(itr->second.Team == ALLIANCE) - --m_QueuedPlayers[queue_id].Alliance; - else - --m_QueuedPlayers[queue_id].Horde; - } - else - { - if (decreaseInvitedCount) + // if invited to bg, and should decrease invited count, then do it + if(group->IsInvitedToBGInstanceGUID) { - BattleGround* bg = sBattleGroundMgr.GetBattleGround(itr->second.IsInvitedToBGInstanceGUID); + BattleGround* bg = sBattleGroundMgr.GetBattleGround(group->IsInvitedToBGInstanceGUID); if (bg) - bg->DecreaseInvitedCount(itr->second.Team); + bg->DecreaseInvitedCount(group->Team); + if (bg && !bg->GetPlayersSize() && !bg->GetInvitedCount(ALLIANCE) && !bg->GetInvitedCount(HORDE)) + { + // no more players on battleground, set delete it + bg->SetDeleteThis(); + } + } + // update the join queue, maybe now the player's group fits in a queue! + // not yet implemented (should store bgTypeId in group queue info?) + } + // remove player queue info + m_QueuedPlayers[queue_id].erase(itr); + // remove group queue info if needed + if(group->Players.empty()) + { + m_QueuedGroups[queue_id].erase(group_itr); + delete group; + } + // NEEDS TESTING! + // group wasn't empty, so it wasn't deleted, and player have left a rated queue -> everyone from the group should leave too + // don't remove recursively if already invited to bg! + else if(!group->IsInvitedToBGInstanceGUID && decreaseInvitedCount && group->IsRated) + { + // remove next player, this is recursive + // first send removal information + if(Player *plr2 = objmgr.GetPlayer(group->Players.begin()->first)) + { + BattleGround * bg = sBattleGroundMgr.GetBattleGroundTemplate(group->BgTypeId); + uint32 bgQueueTypeId = sBattleGroundMgr.BGQueueTypeId(group->BgTypeId,group->ArenaType); + uint32 queueSlot = plr2->GetBattleGroundQueueIndex(bgQueueTypeId); + plr2->RemoveBattleGroundQueueId(bgQueueTypeId); // must be called this way, because if you move this call to queue->removeplayer, it causes bugs + WorldPacket data; + sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, plr2->GetTeam(), queueSlot, STATUS_NONE, 0, 0); + plr2->GetSession()->SendPacket(&data); + } + // then actually delete, this may delete the group as well! + RemovePlayer(group->Players.begin()->first,decreaseInvitedCount); + } + } +} + +bool BattleGroundQueue::InviteGroupToBG(GroupQueueInfo * ginfo, BattleGround * bg, uint32 side) +{ + // set side if needed + if(side) + ginfo->Team = side; + + if(!ginfo->IsInvitedToBGInstanceGUID) + { + // not yet invited + // set invitation + ginfo->IsInvitedToBGInstanceGUID = bg->GetInstanceID(); + uint32 bgQueueTypeId = sBattleGroundMgr.BGQueueTypeId(bg->GetTypeID(), bg->GetArenaType()); + // loop through the players + for(std::map::iterator itr = ginfo->Players.begin(); itr != ginfo->Players.end(); ++itr) + { + // set status + itr->second->InviteTime = getMSTime(); + itr->second->LastInviteTime = getMSTime(); + + // get the player + Player* plr = objmgr.GetPlayer(itr->first); + // if offline, skip him + if(!plr) + continue; + + // invite the player + sBattleGroundMgr.InvitePlayer(plr, bg->GetInstanceID(),ginfo->Team); + + WorldPacket data; + + uint32 queueSlot = plr->GetBattleGroundQueueIndex(bgQueueTypeId); + + sLog.outDebug("Battleground: invited plr %s (%u) to BG instance %u queueindex %u bgtype %u, I can't help it if they don't press the enter battle button.",plr->GetName(),plr->GetGUIDLow(),bg->GetInstanceID(),queueSlot,bg->GetTypeID()); + + // send status packet + sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, side?side:plr->GetTeam(), queueSlot, STATUS_WAIT_JOIN, INVITE_ACCEPT_WAIT_TIME, 0); + plr->GetSession()->SendPacket(&data); + } + return true; + } + + return false; +} + +// this function is responsible for the selection of queued groups when trying to create new battlegrounds +bool BattleGroundQueue::BuildSelectionPool(uint32 bgTypeId, uint32 queue_id, uint32 MinPlayers, uint32 MaxPlayers, SelectionPoolBuildMode mode, uint8 ArenaType, bool isRated, uint32 MinRating, uint32 MaxRating, uint32 DisregardTime, uint32 excludeTeam) +{ + uint32 side; + switch(mode) + { + case NORMAL_ALLIANCE: + case ONESIDE_ALLIANCE_TEAM1: + case ONESIDE_ALLIANCE_TEAM2: + side = ALLIANCE; + break; + case NORMAL_HORDE: + case ONESIDE_HORDE_TEAM1: + case ONESIDE_HORDE_TEAM2: + side = HORDE; + break; + default: + //unknown mode, return false + sLog.outDebug("Battleground: unknown selection pool build mode, returning..."); + return false; + break; + } + + // inititate the groups eligible to create the bg + m_EligibleGroups.Init(&(m_QueuedGroups[queue_id]), bgTypeId, side, MaxPlayers, ArenaType, isRated, MinRating, MaxRating, DisregardTime, excludeTeam); + // init the selected groups (clear) + m_SelectionPools[mode].Init(); + while(!(m_EligibleGroups.empty())) + { + sLog.outDebug("m_EligibleGroups is not empty, continue building selection pool"); + // in decreasing group size, add groups to join if they fit in the MaxPlayersPerTeam players + for(EligibleGroups::iterator itr= m_EligibleGroups.begin(); itr!=m_EligibleGroups.end(); ++itr) + { + // get the maximal not yet checked group + GroupQueueInfo * MaxGroup = (*itr); + // if it fits in the maxplayer size, add it + if( (m_SelectionPools[mode].GetPlayerCount() + MaxGroup->Players.size()) <= MaxPlayers ) + { + m_SelectionPools[mode].AddGroup(MaxGroup); + } + } + if(m_SelectionPools[mode].GetPlayerCount()>=MinPlayers) + { + // the selection pool is set, return + sLog.outDebug("pool build succeeded, return true"); + return true; + } + // if the selection pool's not set, then remove the group with the highest player count, and try again with the rest. + GroupQueueInfo * MaxGroup = m_SelectionPools[mode].GetMaximalGroup(); + m_EligibleGroups.RemoveGroup(MaxGroup); + m_SelectionPools[mode].RemoveGroup(MaxGroup); + } + // failed to build a selection pool matching the given values + return false; +} + +// used to remove the Enter Battle window if the battle has already, but someone still has it +// (this can happen in arenas mainly, since the preparation is shorter than the timer for the bgqueueremove event +void BattleGroundQueue::BGEndedRemoveInvites(BattleGround *bg) +{ + uint32 queue_id = bg->GetQueueType(); + uint32 bgInstanceId = bg->GetInstanceID(); + uint32 bgQueueTypeId = sBattleGroundMgr.BGQueueTypeId(bg->GetTypeID(), bg->GetArenaType()); + QueuedGroupsList::iterator itr, next; + for(itr = m_QueuedGroups[queue_id].begin(); itr != m_QueuedGroups[queue_id].end(); itr = next) + { + // must do this way, because the groupinfo will be deleted when all playerinfos are removed + GroupQueueInfo * ginfo = (*itr); + next = itr; + ++next; + // if group was invited to this bg instance, then remove all references + if(ginfo->IsInvitedToBGInstanceGUID == bgInstanceId) + { + // after removing this much playerinfos, the ginfo will be deleted, so we'll use a for loop + uint32 to_remove = ginfo->Players.size(); + uint32 team = ginfo->Team; + for(int i = 0; i < to_remove; ++i) + { + // always remove the first one in the group + std::map::iterator itr2 = ginfo->Players.begin(); + if(itr2 == ginfo->Players.end()) + { + sLog.outError("Empty Players in ginfo, this should never happen!"); + return; + } + + // get the player + Player * plr = objmgr.GetPlayer(itr2->first); + if(!plr) + { + sLog.outError("Player offline when trying to remove from GroupQueueInfo, this should never happen."); + continue; + } + + // get the queueslot + uint32 queueSlot = plr->GetBattleGroundQueueIndex(bgQueueTypeId); + if (queueSlot < PLAYER_MAX_BATTLEGROUND_QUEUES) // player is in queue + { + plr->RemoveBattleGroundQueueId(bgQueueTypeId); + // remove player from queue, this might delete the ginfo as well! don't use that pointer after this! + RemovePlayer(itr2->first, true); + // this is probably unneeded, since this player was already invited -> does not fit when initing eligible groups + // but updateing the queue can't hurt + Update(bgQueueTypeId, bg->GetQueueType()); + // send info to client + WorldPacket data; + sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, team, queueSlot, STATUS_NONE, 0, 0); + plr->GetSession()->SendPacket(&data); + } } } - m_QueuedPlayers[queue_id].erase(itr); } } /* -this method is called when player is inserted, or removed from BG Queue - there is only one player's status changed, so we don't use while(true) cycles to invite whole queue -add method calls this by itself, the remove method could works in other way, so you have to call this method from other code after calling remove method +this method is called when group is inserted, or player / group is removed from BG Queue - there is only one player's status changed, so we don't use while(true) cycles to invite whole queue +it must be called after fully adding the members of a group to ensure group joining +should be called after removeplayer functions in some cases */ -void BattleGroundQueue::Update(uint32 bgTypeId, uint32 queue_id) +void BattleGroundQueue::Update(uint32 bgTypeId, uint32 queue_id, uint8 arenatype, bool isRated, uint32 arenaRating) { if (queue_id >= MAX_BATTLEGROUND_QUEUES) { @@ -183,158 +559,352 @@ void BattleGroundQueue::Update(uint32 bgTypeId, uint32 queue_id) } //if no players in queue ... do nothing - if (m_QueuedPlayers[queue_id].Alliance == 0 && m_QueuedPlayers[queue_id].Horde == 0) + if (m_QueuedGroups[queue_id].empty()) return; + uint32 bgQueueTypeId = sBattleGroundMgr.BGQueueTypeId(bgTypeId, arenatype); + //battleground with free slot for player should be always the last in this queue - for (BGFreeSlotQueueType::iterator itr = sBattleGroundMgr.BGFreeSlotQueue[bgTypeId].begin(); itr != sBattleGroundMgr.BGFreeSlotQueue[bgTypeId].end(); ++itr) + BGFreeSlotQueueType::iterator itr, next; + for (itr = sBattleGroundMgr.BGFreeSlotQueue[bgTypeId].begin(); itr != sBattleGroundMgr.BGFreeSlotQueue[bgTypeId].end(); itr = next) { + next = itr; + ++next; // battleground is running, so if: // DO NOT allow queue manager to invite new player to running arena - if ((*itr)->isBattleGround() && (*itr)->GetQueueType() == queue_id && (*itr)->GetStatus() > STATUS_WAIT_QUEUE && (*itr)->GetStatus() < STATUS_WAIT_LEAVE) + if ((*itr)->isBattleGround() && (*itr)->GetTypeID() == bgTypeId && (*itr)->GetQueueType() == queue_id && (*itr)->GetStatus() > STATUS_WAIT_QUEUE && (*itr)->GetStatus() < STATUS_WAIT_LEAVE) { //we must check both teams BattleGround* bg = *itr; //we have to store battleground pointer here, because when battleground is full, it is removed from free queue (not yet implemented!!) // and iterator is invalid - //check if there are some players in queue - if (m_QueuedPlayers[queue_id].Alliance > 0 || m_QueuedPlayers[queue_id].Horde > 0) + for(QueuedGroupsList::iterator itr = m_QueuedGroups[queue_id].begin(); itr != m_QueuedGroups[queue_id].end(); ++itr) { - for (PlayerGuidsSortedByTimeQueue::iterator itr2 = m_PlayersSortedByWaitTime[queue_id].begin(); itr2 != m_PlayersSortedByWaitTime[queue_id].end();) + // did the group join for this bg type? + if((*itr)->BgTypeId != bgTypeId) + continue; + // if so, check if fits in + if(bg->GetFreeSlotsForTeam((*itr)->Team) >= (*itr)->Players.size()) { - Player* plr = objmgr.GetPlayer(*itr2); - if (!plr) - { - //something is wrong!, kick player from queue - sLog.outError("BATTLEGROUND: problem with inviting offline player to Battleground queue .... pls report bug"); - uint64 oldval = *itr2; - itr2 = m_PlayersSortedByWaitTime[queue_id].erase(itr2); - RemovePlayer(oldval, true); - continue; - } - - // player will be invited, if in bg there is a free slot for him - if (bg->HasFreeSlotsForTeam(plr->GetTeam())) - { - // iterator to player's queue status - QueuedPlayersMap::iterator itrPlayerStatus = m_QueuedPlayers[queue_id].find(*itr2); - - // remove him from time queue - itr2 = m_PlayersSortedByWaitTime[queue_id].erase(itr2); - - // only check to be sure ... but this condition shouldn't be true (if it is true, then there is a bug somewhere and pls report it) - if (itrPlayerStatus == m_QueuedPlayers[queue_id].end()) - continue; - - // check if player is not already invited - if (!itrPlayerStatus->second.IsInvitedToBGInstanceGUID) - { - itrPlayerStatus->second.IsInvitedToBGInstanceGUID = bg->GetInstanceID(); - itrPlayerStatus->second.InviteTime = getMSTime(); - itrPlayerStatus->second.LastInviteTime = getMSTime(); - if(itrPlayerStatus->second.Team == ALLIANCE) - --m_QueuedPlayers[queue_id].Alliance; - else - --m_QueuedPlayers[queue_id].Horde; - sBattleGroundMgr.InvitePlayer(plr, bg->GetInstanceID()); - - WorldPacket data; - uint32 queueSlot = plr->GetBattleGroundQueueIndex(bgTypeId); - sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, plr->GetTeam(), queueSlot, STATUS_WAIT_JOIN, INVITE_ACCEPT_WAIT_TIME, 0); - plr->GetSession()->SendPacket(&data); - } - } - else - ++itr2; - - //if battleground is FULL, then it is removed from free slot queue - not yet implemented! - if (!bg->HasFreeSlots()) - { - //if bg is full, there is no need to invite other players, so break - break; - //remove BG from BGFreeSlotQueue - not used now, in this system we don't remove BGs from free queue - //bg->RemoveFromBGFreeSlotQueue() --- do not uncomment this - not yet implemented - } + // if group fits in, invite it + InviteGroupToBG((*itr),bg,(*itr)->Team); } } + + if (!bg->HasFreeSlots()) + { + //remove BG from BGFreeSlotQueue + bg->RemoveFromBGFreeSlotQueue(); + } } } - /* THIS IS A CASE THAT IN QUEUE THERE IS ENOUGHT PLAYERS TO START NEW BG */ - //itr->end is the last BG - template, which is not already started! + // finished iterating through the bgs with free slots, maybe we need to create a new bg - /* here will be a most of change, when we create battlegrounds instantiated */ - /* if (there is enough players to start new BG) - Battleground* newbg = sBattleGroundMgr.CreateNewBattleGround(bgTypeId) - - that function will use the COPY constructor on BattleGround class ( in bg manager we should have one battleground as a template - (battleground template will be used only to create new BGs, it will be an instance of BG class, but it won't ever start) */ - - /* following code is working with current Battleground system and it should be removed, when BGs will work like instances */ - BattleGround* bg2 = sBattleGroundMgr.GetBattleGround(bgTypeId); - if (bg2->GetQueueType() != MAX_BATTLEGROUND_QUEUES || bg2->GetStatus() != STATUS_WAIT_QUEUE) - return; - if (m_QueuedPlayers[queue_id].Alliance >= bg2->GetMinPlayersPerTeam() && m_QueuedPlayers[queue_id].Horde >= bg2->GetMinPlayersPerTeam()) + BattleGround * bg_template = sBattleGroundMgr.GetBattleGroundTemplate(bgTypeId); + if(!bg_template) { - bg2->SetStatus(STATUS_WAIT_JOIN); - bg2->SetQueueType(queue_id); + sLog.outError("Battleground: Update: bg template not found for %u", bgTypeId); + return; + } - for (PlayerGuidsSortedByTimeQueue::iterator itr2 = m_PlayersSortedByWaitTime[queue_id].begin(); itr2 != m_PlayersSortedByWaitTime[queue_id].end();) + // get the min. players per team, properly for larger arenas as well. (must have full teams for arena matches!) + uint32 MinPlayersPerTeam = bg_template->GetMinPlayersPerTeam(); + uint32 MaxPlayersPerTeam = bg_template->GetMaxPlayersPerTeam(); + if(bg_template->isArena()) + { + if(sBattleGroundMgr.isArenaTesting()) { - Player* plr = objmgr.GetPlayer(*itr2); - if (!plr) + MaxPlayersPerTeam = 1; + MinPlayersPerTeam = 1; + } + else + { + switch(arenatype) { - //something is wrong!, kick player from queue - sLog.outError("BATTLEGROUND: problem with inviting offline player to Battleground queue .... pls report bug"); - uint64 oldval = *itr2; - itr2 = m_PlayersSortedByWaitTime[queue_id].erase(itr2); - RemovePlayer(oldval, true); - continue; + case ARENA_TYPE_2v2: + MaxPlayersPerTeam = 2; + MinPlayersPerTeam = 2; + break; + case ARENA_TYPE_3v3: + MaxPlayersPerTeam = 3; + MinPlayersPerTeam = 3; + break; + case ARENA_TYPE_5v5: + MaxPlayersPerTeam = 5; + MinPlayersPerTeam = 5; + break; + } + } + } + + // found out the minimum and maximum ratings the newly added team should battle against + // arenaRating is the rating of the latest joined team + uint32 arenaMinRating = (arenaRating <= sBattleGroundMgr.GetMaxRatingDifference()) ? 0 : arenaRating - sBattleGroundMgr.GetMaxRatingDifference(); + // if no rating is specified, set maxrating to 0 + uint32 arenaMaxRating = (arenaRating == 0)? 0 : arenaRating + sBattleGroundMgr.GetMaxRatingDifference(); + uint32 discardTime = 0; + // if max rating difference is set and the time past since server startup is greater than the rating discard time + // (after what time the ratings aren't taken into account when making teams) then + // the discard time is current_time - time_to_discard, teams that joined after that, will have their ratings taken into account + // else leave the discard time on 0, this way all ratings will be discarded + if(sBattleGroundMgr.GetMaxRatingDifference() && getMSTime() >= sBattleGroundMgr.GetRatingDiscardTimer()) + discardTime = getMSTime() - sBattleGroundMgr.GetRatingDiscardTimer(); + + // try to build the selection pools + bool bAllyOK = BuildSelectionPool(bgTypeId, queue_id, MinPlayersPerTeam, MaxPlayersPerTeam, NORMAL_ALLIANCE, arenatype, isRated, arenaMinRating, arenaMaxRating, discardTime); + if(bAllyOK) + sLog.outDebug("Battleground: ally pool succesfully build"); + else + sLog.outDebug("Battleground: ally pool wasn't created"); + bool bHordeOK = BuildSelectionPool(bgTypeId, queue_id, MinPlayersPerTeam, MaxPlayersPerTeam, NORMAL_HORDE, arenatype, isRated, arenaMinRating, arenaMaxRating, discardTime); + if(bHordeOK) + sLog.outDebug("Battleground: horde pool succesfully built"); + else + sLog.outDebug("Battleground: horde pool wasn't created"); + + // if selection pools are ready, create the new bg + if (bAllyOK && bHordeOK) + { + BattleGround * bg2 = 0; + // special handling for arenas + if(bg_template->isArena()) + { + // Find a random arena, that can be created + uint8 arenas[] = {BATTLEGROUND_NA, BATTLEGROUND_BE, BATTLEGROUND_RL}; + uint32 arena_num = urand(0,2); + if( !(bg2 = sBattleGroundMgr.CreateNewBattleGround(arenas[arena_num%3])) && + !(bg2 = sBattleGroundMgr.CreateNewBattleGround(arenas[(arena_num+1)%3])) && + !(bg2 = sBattleGroundMgr.CreateNewBattleGround(arenas[(arena_num+2)%3])) ) + { + sLog.outError("Battleground: couldn't create any arena instance!"); + return; } - /* TODO: (i'm not sure this code will be useful: - here should be some condition like if (bg2->isArena() && bg2->isRated()) + // set the MaxPlayersPerTeam values based on arenatype + // setting the min player values isn't needed, since we won't be using that value later on. + if(sBattleGroundMgr.isArenaTesting()) { - invite players from 1 certain group on each faction to play arena match - } else if ....and existing code - */ - // player will be invited, if in bg there is a free slot for him - if (bg2->HasFreeSlotsForTeam(plr->GetTeam())) - { - // iterator to player's queue status - QueuedPlayersMap::iterator itrPlayerStatus = m_QueuedPlayers[queue_id].find(*itr2); - - // remove him from time queue - itr2 = m_PlayersSortedByWaitTime[queue_id].erase(itr2); - - // only check to be sure ... but this condition shouldn't be true (if it is true, then there is a bug somewhere and report it) - if (itrPlayerStatus == m_QueuedPlayers[queue_id].end()) - continue; - - //check if player is not already invited - if (!itrPlayerStatus->second.IsInvitedToBGInstanceGUID) - { - itrPlayerStatus->second.IsInvitedToBGInstanceGUID = bg2->GetInstanceID(); - itrPlayerStatus->second.InviteTime = getMSTime(); - itrPlayerStatus->second.LastInviteTime = getMSTime(); - - if(itrPlayerStatus->second.Team == ALLIANCE) - --m_QueuedPlayers[queue_id].Alliance; - else - --m_QueuedPlayers[queue_id].Horde; - - sBattleGroundMgr.InvitePlayer(plr, bg2->GetInstanceID()); - - WorldPacket data; - uint32 queueSlot = plr->GetBattleGroundQueueIndex(bgTypeId); - sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg2, plr->GetTeam(), queueSlot, STATUS_WAIT_JOIN, INVITE_ACCEPT_WAIT_TIME, 0); - plr->GetSession()->SendPacket(&data); - } + bg2->SetMaxPlayersPerTeam(1); + bg2->SetMaxPlayers(2); } else - ++itr2; + { + switch(arenatype) + { + case ARENA_TYPE_2v2: + bg2->SetMaxPlayersPerTeam(2); + bg2->SetMaxPlayers(4); + break; + case ARENA_TYPE_3v3: + bg2->SetMaxPlayersPerTeam(3); + bg2->SetMaxPlayers(6); + break; + case ARENA_TYPE_5v5: + bg2->SetMaxPlayersPerTeam(5); + bg2->SetMaxPlayers(10); + break; + default: + break; + } + } } + else + { + // create new battleground + bg2 = sBattleGroundMgr.CreateNewBattleGround(bgTypeId); + } + + if(!bg2) + { + sLog.outError("Battleground: couldn't create bg %u",bgTypeId); + return; + } + + // start the joining of the bg + bg2->SetStatus(STATUS_WAIT_JOIN); + bg2->SetQueueType(queue_id); + // initialize arena / rating info + bg2->SetArenaType(arenatype); + // set rating + bg2->SetRated(isRated); + + std::list::iterator itr; + + // invite groups from horde selection pool + for(itr = m_SelectionPools[NORMAL_HORDE].SelectedGroups.begin(); itr != m_SelectionPools[NORMAL_HORDE].SelectedGroups.end(); ++itr) + { + InviteGroupToBG((*itr),bg2,HORDE); + } + + // invite groups from ally selection pools + for(itr = m_SelectionPools[NORMAL_ALLIANCE].SelectedGroups.begin(); itr != m_SelectionPools[NORMAL_ALLIANCE].SelectedGroups.end(); ++itr) + { + InviteGroupToBG((*itr),bg2,ALLIANCE); + } + + if (isRated) + { + std::list::iterator itr_alliance = m_SelectionPools[NORMAL_ALLIANCE].SelectedGroups.begin(); + std::list::iterator itr_horde = m_SelectionPools[NORMAL_HORDE].SelectedGroups.begin(); + (*itr_alliance)->OpponentsTeamRating = (*itr_horde)->ArenaTeamRating; + sLog.outDebug("setting oposite teamrating for team %u to %u", (*itr_alliance)->ArenaTeamId, (*itr_alliance)->OpponentsTeamRating); + (*itr_horde)->OpponentsTeamRating = (*itr_alliance)->ArenaTeamRating; + sLog.outDebug("setting oposite teamrating for team %u to %u", (*itr_horde)->ArenaTeamId, (*itr_horde)->OpponentsTeamRating); + } + + // start the battleground bg2->StartBattleGround(); } + + // there weren't enough players for a "normal" match + // if arena, enable horde versus horde or alliance versus alliance teams here + + else if(bg_template->isArena()) + { + bool bOneSideHordeTeam1 = false, bOneSideHordeTeam2 = false; + bool bOneSideAllyTeam1 = false, bOneSideAllyTeam2 = false; + bOneSideHordeTeam1 = BuildSelectionPool(bgTypeId, queue_id,MaxPlayersPerTeam,MaxPlayersPerTeam,ONESIDE_HORDE_TEAM1,arenatype, isRated, arenaMinRating, arenaMaxRating, discardTime); + if(bOneSideHordeTeam1) + { + // one team has been selected, find out if other can be selected too + std::list::iterator itr; + // temporarily change the team side to enable building the next pool excluding the already selected groups + for(itr = m_SelectionPools[ONESIDE_HORDE_TEAM1].SelectedGroups.begin(); itr != m_SelectionPools[ONESIDE_HORDE_TEAM1].SelectedGroups.end(); ++itr) + (*itr)->Team=ALLIANCE; + + bOneSideHordeTeam2 = BuildSelectionPool(bgTypeId, queue_id,MaxPlayersPerTeam,MaxPlayersPerTeam,ONESIDE_HORDE_TEAM2,arenatype, isRated, arenaMinRating, arenaMaxRating, discardTime, (*(m_SelectionPools[ONESIDE_HORDE_TEAM1].SelectedGroups.begin()))->ArenaTeamId); + + // change back the team to horde + for(itr = m_SelectionPools[ONESIDE_HORDE_TEAM1].SelectedGroups.begin(); itr != m_SelectionPools[ONESIDE_HORDE_TEAM1].SelectedGroups.end(); ++itr) + (*itr)->Team=HORDE; + + if(!bOneSideHordeTeam2) + bOneSideHordeTeam1 = false; + } + if(!bOneSideHordeTeam1) + { + // check for one sided ally + bOneSideAllyTeam1 = BuildSelectionPool(bgTypeId, queue_id,MaxPlayersPerTeam,MaxPlayersPerTeam,ONESIDE_ALLIANCE_TEAM1,arenatype, isRated, arenaMinRating, arenaMaxRating, discardTime); + if(bOneSideAllyTeam1) + { + // one team has been selected, find out if other can be selected too + std::list::iterator itr; + // temporarily change the team side to enable building the next pool excluding the already selected groups + for(itr = m_SelectionPools[ONESIDE_ALLIANCE_TEAM1].SelectedGroups.begin(); itr != m_SelectionPools[ONESIDE_ALLIANCE_TEAM1].SelectedGroups.end(); ++itr) + (*itr)->Team=HORDE; + + bOneSideAllyTeam2 = BuildSelectionPool(bgTypeId, queue_id,MaxPlayersPerTeam,MaxPlayersPerTeam,ONESIDE_ALLIANCE_TEAM2,arenatype, isRated, arenaMinRating, arenaMaxRating, discardTime,(*(m_SelectionPools[ONESIDE_ALLIANCE_TEAM1].SelectedGroups.begin()))->ArenaTeamId); + + // change back the team to ally + for(itr = m_SelectionPools[ONESIDE_ALLIANCE_TEAM1].SelectedGroups.begin(); itr != m_SelectionPools[ONESIDE_ALLIANCE_TEAM1].SelectedGroups.end(); ++itr) + (*itr)->Team=ALLIANCE; + } + + if(!bOneSideAllyTeam2) + bOneSideAllyTeam1 = false; + } + // 1-sided BuildSelectionPool() will work, because the MinPlayersPerTeam == MaxPlayersPerTeam in every arena!!!! + if( (bOneSideHordeTeam1 && bOneSideHordeTeam2) || + (bOneSideAllyTeam1 && bOneSideAllyTeam2) ) + { + // which side has enough players? + uint32 side = 0; + SelectionPoolBuildMode mode1, mode2; + // find out what pools are we using + if(bOneSideAllyTeam1 && bOneSideAllyTeam2) + { + side = ALLIANCE; + mode1 = ONESIDE_ALLIANCE_TEAM1; + mode2 = ONESIDE_ALLIANCE_TEAM2; + } + else + { + side = HORDE; + mode1 = ONESIDE_HORDE_TEAM1; + mode2 = ONESIDE_HORDE_TEAM2; + } + + // create random arena + uint8 arenas[] = {BATTLEGROUND_NA, BATTLEGROUND_BE, BATTLEGROUND_RL}; + uint32 arena_num = urand(0,2); + BattleGround* bg2 = NULL; + if( !(bg2 = sBattleGroundMgr.CreateNewBattleGround(arenas[arena_num%3])) && + !(bg2 = sBattleGroundMgr.CreateNewBattleGround(arenas[(arena_num+1)%3])) && + !(bg2 = sBattleGroundMgr.CreateNewBattleGround(arenas[(arena_num+2)%3])) ) + { + sLog.outError("Could not create arena."); + return; + } + + sLog.outDebug("Battleground: One-faction arena created."); + // init stats + if(sBattleGroundMgr.isArenaTesting()) + { + bg2->SetMaxPlayersPerTeam(1); + bg2->SetMaxPlayers(2); + } + else + { + switch(arenatype) + { + case ARENA_TYPE_2v2: + bg2->SetMaxPlayersPerTeam(2); + bg2->SetMaxPlayers(4); + break; + case ARENA_TYPE_3v3: + bg2->SetMaxPlayersPerTeam(3); + bg2->SetMaxPlayers(6); + break; + case ARENA_TYPE_5v5: + bg2->SetMaxPlayersPerTeam(5); + bg2->SetMaxPlayers(10); + break; + default: + break; + } + } + + bg2->SetRated(isRated); + + // assigned team of the other group + uint32 other_side; + if(side == ALLIANCE) + other_side = HORDE; + else + other_side = ALLIANCE; + + // start the joining of the bg + bg2->SetStatus(STATUS_WAIT_JOIN); + bg2->SetQueueType(queue_id); + // initialize arena / rating info + bg2->SetArenaType(arenatype); + + std::list::iterator itr; + + // invite players from the first group as horde players (actually green team) + for(itr = m_SelectionPools[mode1].SelectedGroups.begin(); itr != m_SelectionPools[mode1].SelectedGroups.end(); ++itr) + { + InviteGroupToBG((*itr),bg2,HORDE); + } + + // invite players from the second group as ally players (actually gold team) + for(itr = m_SelectionPools[mode2].SelectedGroups.begin(); itr != m_SelectionPools[mode2].SelectedGroups.end(); ++itr) + { + InviteGroupToBG((*itr),bg2,ALLIANCE); + } + + if (isRated) + { + std::list::iterator itr_alliance = m_SelectionPools[mode1].SelectedGroups.begin(); + std::list::iterator itr_horde = m_SelectionPools[mode2].SelectedGroups.begin(); + (*itr_alliance)->OpponentsTeamRating = (*itr_horde)->ArenaTeamRating; + (*itr_horde)->OpponentsTeamRating = (*itr_alliance)->ArenaTeamRating; + } + + bg2->StartBattleGround(); + } + } } /*********************************************************/ @@ -361,14 +931,19 @@ bool BGQueueInviteEvent::Execute(uint64 /*e_time*/, uint32 /*p_time*/) uint32 queueSlot = plr->GetBattleGroundQueueIndex(bg->GetTypeID()); if (queueSlot < PLAYER_MAX_BATTLEGROUND_QUEUES) // player is in queue { - // check if player is invited to this bg ... this check must be here, because when player leaves queue and joins another, it would cause a problems - BattleGroundQueue::QueuedPlayersMap const& qpMap = sBattleGroundMgr.m_BattleGroundQueues[bg->GetTypeID()].m_QueuedPlayers[plr->GetBattleGroundQueueIdFromLevel()]; - BattleGroundQueue::QueuedPlayersMap::const_iterator qItr = qpMap.find(m_PlayerGuid); - if (qItr != qpMap.end() && qItr->second.IsInvitedToBGInstanceGUID == m_BgInstanceGUID) + uint32 bgQueueTypeId = sBattleGroundMgr.BGQueueTypeId(bg->GetTypeID(), bg->GetArenaType()); + uint32 queueSlot = plr->GetBattleGroundQueueIndex(bgQueueTypeId); + if (queueSlot < PLAYER_MAX_BATTLEGROUND_QUEUES) // player is in queue { - WorldPacket data; - sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, plr->GetTeam(), queueSlot, STATUS_WAIT_JOIN, INVITE_ACCEPT_WAIT_TIME/2, 0); - plr->GetSession()->SendPacket(&data); + // check if player is invited to this bg ... this check must be here, because when player leaves queue and joins another, it would cause a problems + BattleGroundQueue::QueuedPlayersMap const& qpMap = sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].m_QueuedPlayers[plr->GetBattleGroundQueueIdFromLevel()]; + BattleGroundQueue::QueuedPlayersMap::const_iterator qItr = qpMap.find(m_PlayerGuid); + if (qItr != qpMap.end() && qItr->second.GroupInfo->IsInvitedToBGInstanceGUID == m_BgInstanceGUID) + { + WorldPacket data; + sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, qItr->second.GroupInfo->Team, queueSlot, STATUS_WAIT_JOIN, INVITE_ACCEPT_WAIT_TIME/2, 0); + plr->GetSession()->SendPacket(&data); + } } } return true; //event will be deleted @@ -387,32 +962,40 @@ bool BGQueueRemoveEvent::Execute(uint64 /*e_time*/, uint32 /*p_time*/) // player logged off (we should do nothing, he is correctly removed from queue in another procedure) return true; - // Player can be in another BG queue and must be removed in normal way in any case - //if (plr->InBattleGround()) - // // player is already in battleground ... do nothing (battleground queue status is deleted when player is teleported to BG) - // return true; - BattleGround* bg = sBattleGroundMgr.GetBattleGround(m_BgInstanceGUID); if (!bg) return true; - uint32 queueSlot = plr->GetBattleGroundQueueIndex(bg->GetTypeID()); - if (queueSlot < PLAYER_MAX_BATTLEGROUND_QUEUES) // player is in queue (base at player data + sLog.outDebug("Battleground: removing player %u from bg queue for instance %u because of not pressing enter battle in time.",plr->GetGUIDLow(),m_BgInstanceGUID); + + uint32 bgQueueTypeId = sBattleGroundMgr.BGQueueTypeId(bg->GetTypeID(), bg->GetArenaType()); + uint32 queueSlot = plr->GetBattleGroundQueueIndex(bgQueueTypeId); + if (queueSlot < PLAYER_MAX_BATTLEGROUND_QUEUES) // player is in queue { // check if player is invited to this bg ... this check must be here, because when player leaves queue and joins another, it would cause a problems - BattleGroundQueue::QueuedPlayersMap const& qpMap = sBattleGroundMgr.m_BattleGroundQueues[bg->GetTypeID()].m_QueuedPlayers[plr->GetBattleGroundQueueIdFromLevel()]; - BattleGroundQueue::QueuedPlayersMap::const_iterator qItr = qpMap.find(m_PlayerGuid); - if (qItr!=qpMap.end() && qItr->second.IsInvitedToBGInstanceGUID == m_BgInstanceGUID) + BattleGroundQueue::QueuedPlayersMap::iterator qMapItr = sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].m_QueuedPlayers[plr->GetBattleGroundQueueIdFromLevel()].find(m_PlayerGuid); + if (qMapItr != sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].m_QueuedPlayers[plr->GetBattleGroundQueueIdFromLevel()].end() && qMapItr->second.GroupInfo && qMapItr->second.GroupInfo->IsInvitedToBGInstanceGUID == m_BgInstanceGUID) { - plr->RemoveBattleGroundQueueId(bg->GetTypeID()); - sBattleGroundMgr.m_BattleGroundQueues[bg->GetTypeID()].RemovePlayer(m_PlayerGuid, true); - sBattleGroundMgr.m_BattleGroundQueues[bg->GetTypeID()].Update(bg->GetTypeID(), bg->GetQueueType()); - + if (qMapItr->second.GroupInfo->IsRated) + { + ArenaTeam * at = objmgr.GetArenaTeamById(qMapItr->second.GroupInfo->ArenaTeamId); + if (at) + { + sLog.outDebug("UPDATING memberLost's personal arena rating for %u by opponents rating: %u", GUID_LOPART(plr->GetGUID()), qMapItr->second.GroupInfo->OpponentsTeamRating); + at->MemberLost(plr, qMapItr->second.GroupInfo->OpponentsTeamRating); + at->SaveToDB(); + } + } + plr->RemoveBattleGroundQueueId(bgQueueTypeId); + sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].RemovePlayer(m_PlayerGuid, true); + sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].Update(bgQueueTypeId, bg->GetQueueType()); WorldPacket data; - sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, plr->GetTeam(), queueSlot, STATUS_NONE, 0, 0); + sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, m_PlayersTeam, queueSlot, STATUS_NONE, 0, 0); plr->GetSession()->SendPacket(&data); } } + else + sLog.outDebug("Battleground: Player was already removed from queue"); //event will be deleted return true; @@ -431,22 +1014,80 @@ void BGQueueRemoveEvent::Abort(uint64 /*e_time*/) BattleGroundMgr::BattleGroundMgr() { m_BattleGrounds.clear(); + m_AutoDistributePoints = (bool)sWorld.getConfig(CONFIG_ARENA_AUTO_DISTRIBUTE_POINTS); + m_MaxRatingDifference = sWorld.getConfig(CONFIG_ARENA_MAX_RATING_DIFFERENCE); + m_RatingDiscardTimer = sWorld.getConfig(CONFIG_ARENA_RATING_DISCARD_TIMER); + m_PrematureFinishTimer = sWorld.getConfig(CONFIG_BATTLEGROUND_PREMATURE_FINISH_TIMER); + m_NextRatingDiscardUpdate = m_RatingDiscardTimer; + m_AutoDistributionTimeChecker = 0; + m_ArenaTesting = false; } BattleGroundMgr::~BattleGroundMgr() { - for(std::map::iterator itr = m_BattleGrounds.begin(); itr != m_BattleGrounds.end(); ++itr) - delete itr->second; + BattleGroundSet::iterator itr, next; + for(itr = m_BattleGrounds.begin(); itr != m_BattleGrounds.end(); itr = next) + { + next = itr; + ++next; + BattleGround * bg = itr->second; + m_BattleGrounds.erase(itr); + delete bg; + } m_BattleGrounds.clear(); } +// used to update running battlegrounds, and delete finished ones void BattleGroundMgr::Update(time_t diff) { - for(BattleGroundSet::iterator itr = m_BattleGrounds.begin(); itr != m_BattleGrounds.end(); ++itr) + BattleGroundSet::iterator itr, next; + for(itr = m_BattleGrounds.begin(); itr != m_BattleGrounds.end(); itr = next) + { + next = itr; + ++next; itr->second->Update(diff); + // use the SetDeleteThis variable + // direct deletion caused crashes + if(itr->second->m_SetDeleteThis) + { + BattleGround * bg = itr->second; + m_BattleGrounds.erase(itr); + delete bg; + } + } + // if rating difference counts, maybe force-update queues + if(m_MaxRatingDifference) + { + // it's time to force update + if(m_NextRatingDiscardUpdate < diff) + { + // forced update for level 70 rated arenas + m_BattleGroundQueues[BATTLEGROUND_QUEUE_2v2].Update(BATTLEGROUND_AA,6,ARENA_TYPE_2v2,true,0); + m_BattleGroundQueues[BATTLEGROUND_QUEUE_3v3].Update(BATTLEGROUND_AA,6,ARENA_TYPE_3v3,true,0); + m_BattleGroundQueues[BATTLEGROUND_QUEUE_5v5].Update(BATTLEGROUND_AA,6,ARENA_TYPE_5v5,true,0); + m_NextRatingDiscardUpdate = m_RatingDiscardTimer; + } + else + m_NextRatingDiscardUpdate -= diff; + } + if(m_AutoDistributePoints) + { + if(m_AutoDistributionTimeChecker < diff) + { + if(sWorld.GetGameTime() > m_NextAutoDistributionTime) + { + DistributeArenaPoints(); + m_NextAutoDistributionTime = sWorld.GetGameTime() + BATTLEGROUND_ARENA_POINT_DISTRIBUTION_DAY * sWorld.getConfig(CONFIG_ARENA_AUTO_DISTRIBUTE_INTERVAL_DAYS); + CharacterDatabase.PExecute("UPDATE saved_variables SET NextArenaPointDistributionTime = '"I64FMTD"'", m_NextAutoDistributionTime); + } + m_AutoDistributionTimeChecker = 600000; // check 10 minutes + } + else + m_AutoDistributionTimeChecker -= diff; + } } -void BattleGroundMgr::BuildBattleGroundStatusPacket(WorldPacket *data, BattleGround *bg, uint32 team, uint8 QueueSlot, uint8 StatusID, uint32 Time1, uint32 Time2) +void BattleGroundMgr::BuildBattleGroundStatusPacket(WorldPacket *data, BattleGround *bg, uint32 team, uint8 QueueSlot, uint8 StatusID, uint32 Time1, uint32 Time2, uint32 arenatype, uint8 israted) { // we can be in 3 queues in same time... if(StatusID == 0) @@ -460,10 +1101,55 @@ void BattleGroundMgr::BuildBattleGroundStatusPacket(WorldPacket *data, BattleGro data->Initialize(SMSG_BATTLEFIELD_STATUS, (4+1+1+4+2+4+1+4+4+4)); *data << uint32(QueueSlot); // queue id (0...2) - player can be in 3 queues in time // uint64 in client - *data << uint64( uint64(bg->GetArenaType()) | (uint64(0x0D) << 8) | (uint64(bg->GetTypeID()) << 16) | (uint64(0x1F90) << 48) ); + *data << uint64( uint64(arenatype ? arenatype : bg->GetArenaType()) | (uint64(0x0D) << 8) | (uint64(bg->GetTypeID()) << 16) | (uint64(0x1F90) << 48) ); *data << uint32(0); // unknown // alliance/horde for BG and skirmish/rated for Arenas - *data << uint8(bg->isArena() ? (bg->isRated() ? 1 : 0) : bg->GetTeamIndexByTeamId(team)); + *data << uint8(bg->isArena() ? ( israted ? israted : bg->isRated() ) : bg->GetTeamIndexByTeamId(team)); +/* *data << uint8(arenatype ? arenatype : bg->GetArenaType()); // team type (0=BG, 2=2x2, 3=3x3, 5=5x5), for arenas // NOT PROPER VALUE IF ARENA ISN'T RUNNING YET!!!! + switch(bg->GetTypeID()) // value depends on bg id + { + case BATTLEGROUND_AV: + *data << uint8(1); + break; + case BATTLEGROUND_WS: + *data << uint8(2); + break; + case BATTLEGROUND_AB: + *data << uint8(3); + break; + case BATTLEGROUND_NA: + *data << uint8(4); + break; + case BATTLEGROUND_BE: + *data << uint8(5); + break; + case BATTLEGROUND_AA: + *data << uint8(6); + break; + case BATTLEGROUND_EY: + *data << uint8(7); + break; + case BATTLEGROUND_RL: + *data << uint8(8); + break; + default: // unknown + *data << uint8(0); + break; + } + + if(bg->isArena() && (StatusID == STATUS_WAIT_QUEUE)) + *data << uint32(BATTLEGROUND_AA); // all arenas I don't think so. + else + *data << uint32(bg->GetTypeID()); // BG id from DBC + + *data << uint16(0x1F90); // unk value 8080 + *data << uint32(bg->GetInstanceID()); // instance id + + if(bg->isBattleGround()) + *data << uint8(bg->GetTeamIndexByTeamId(team)); // team + else + *data << uint8(israted?israted:bg->isRated()); // is rated battle +*/ *data << uint32(StatusID); // status switch(StatusID) { @@ -493,13 +1179,24 @@ void BattleGroundMgr::BuildPvpLogDataPacket(WorldPacket *data, BattleGround *bg) // last check on 2.4.1 data->Initialize(MSG_PVP_LOG_DATA, (1+1+4+40*bg->GetPlayerScoresSize())); *data << uint8(type); // seems to be type (battleground=0/arena=1) + if(type) // arena { - for(uint8 i = 0; i < 2; i++) + // it seems this must be according to BG_WINNER_A/H and _NOT_ BG_TEAM_A/H + for(int i = 1; i >= 0; --i) { - *data << uint32(3000+1+i); // rating change: showed value - 3000 - *data << uint32(0); // 2.4.0, has some to do with rating change... - *data << uint8(0); // some unknown string + *data << uint32(3000-bg->m_ArenaTeamRatingChanges[i]); // rating change: showed value - 3000 + *data << uint32(3999); // huge thanks for TOM_RUS for this! + sLog.outDebug("rating change: %d", bg->m_ArenaTeamRatingChanges[i]); + } + for(int i = 1; i >= 0; --i) + { + uint32 at_id = bg->m_ArenaTeamIds[i]; + ArenaTeam * at = objmgr.GetArenaTeamById(at_id); + if(at) + *data << at->GetName(); + else//*/ + *data << (uint8)0; } } @@ -519,32 +1216,35 @@ void BattleGroundMgr::BuildPvpLogDataPacket(WorldPacket *data, BattleGround *bg) { *data << (uint64)itr->first; *data << (int32)itr->second->KillingBlows; - if(type) + Player *plr = objmgr.GetPlayer(itr->first); + uint32 team = bg->GetPlayerTeam(itr->first); + if(!team && plr) team = plr->GetTeam(); + if(type == 0) + { + *data << (int32)itr->second->HonorableKills; + *data << (int32)itr->second->Deaths; + *data << (int32)(itr->second->BonusHonor); + } + else { - // this value is team (green/gold)? // that part probably wrong - Player *plr = objmgr.GetPlayer(itr->first); if(plr) { - if(plr->GetTeam() == HORDE) + if(team == HORDE) *data << uint8(0); - else if(plr->GetTeam() == ALLIANCE) + else if(team == ALLIANCE) + { *data << uint8(1); + } else *data << uint8(0); } else *data << uint8(0); } - else - { - *data << (int32)itr->second->HonorableKills; - *data << (int32)itr->second->Deaths; - *data << (int32)itr->second->BonusHonor; // bonus honor - } - *data << (int32)itr->second->DamageDone; // damage done - *data << (int32)itr->second->HealingDone; // healing done - switch(bg->GetTypeID()) // battleground specific things + *data << (int32)itr->second->DamageDone; // damage done + *data << (int32)itr->second->HealingDone; // healing done + switch(bg->GetTypeID()) // battleground specific things { case BATTLEGROUND_AV: *data << (uint32)0x00000005; // count of next fields @@ -565,13 +1265,16 @@ void BattleGroundMgr::BuildPvpLogDataPacket(WorldPacket *data, BattleGround *bg) *data << (uint32)((BattleGroundABScore*)itr->second)->BasesDefended; // bases defended break; case BATTLEGROUND_EY: - *data << (uint32)0x00000001; // count of next fields + *data << (uint32)0x00000001; // count of next fields *data << (uint32)((BattleGroundEYScore*)itr->second)->FlagCaptures; // flag captures break; case BATTLEGROUND_NA: case BATTLEGROUND_BE: case BATTLEGROUND_AA: case BATTLEGROUND_RL: + case BATTLEGROUND_SA: // wotlk + case BATTLEGROUND_DS: // wotlk + case BATTLEGROUND_RV: // wotlk *data << (int32)0; // 0 break; default: @@ -622,23 +1325,120 @@ void BattleGroundMgr::BuildPlayerJoinedBattleGroundPacket(WorldPacket *data, Pla *data << uint64(plr->GetGUID()); } -void BattleGroundMgr::InvitePlayer(Player* plr, uint32 bgInstanceGUID) +void BattleGroundMgr::InvitePlayer(Player* plr, uint32 bgInstanceGUID, uint32 team) { // set invited player counters: BattleGround* bg = GetBattleGround(bgInstanceGUID); if(!bg) return; + bg->IncreaseInvitedCount(team); + + plr->SetInviteForBattleGroundQueueType(BGQueueTypeId(bg->GetTypeID(),bg->GetArenaType()), bgInstanceGUID); + + // set the arena teams for rated matches + if(bg->isArena() && bg->isRated()) + { + switch(bg->GetArenaType()) + { + case ARENA_TYPE_2v2: + bg->SetArenaTeamIdForTeam(team, plr->GetArenaTeamId(0)); + break; + case ARENA_TYPE_3v3: + bg->SetArenaTeamIdForTeam(team, plr->GetArenaTeamId(1)); + break; + case ARENA_TYPE_5v5: + bg->SetArenaTeamIdForTeam(team, plr->GetArenaTeamId(2)); + break; + default: + break; + } + } - bg->IncreaseInvitedCount(plr->GetTeam()); - plr->SetInviteForBattleGroundType(bg->GetTypeID()); // create invite events: //add events to player's counters ---- this is not good way - there should be something like global event processor, where we should add those events BGQueueInviteEvent* inviteEvent = new BGQueueInviteEvent(plr->GetGUID(), bgInstanceGUID); plr->m_Events.AddEvent(inviteEvent, plr->m_Events.CalculateTime(INVITE_ACCEPT_WAIT_TIME/2)); - BGQueueRemoveEvent* removeEvent = new BGQueueRemoveEvent(plr->GetGUID(), bgInstanceGUID, plr->GetTeam()); + BGQueueRemoveEvent* removeEvent = new BGQueueRemoveEvent(plr->GetGUID(), bgInstanceGUID, team); plr->m_Events.AddEvent(removeEvent, plr->m_Events.CalculateTime(INVITE_ACCEPT_WAIT_TIME)); } +BattleGround * BattleGroundMgr::GetBattleGroundTemplate(uint32 bgTypeId) +{ + return BGFreeSlotQueue[bgTypeId].empty() ? NULL : BGFreeSlotQueue[bgTypeId].back(); +} + +// create a new battleground that will really be used to play +BattleGround * BattleGroundMgr::CreateNewBattleGround(uint32 bgTypeId) +{ + BattleGround *bg = NULL; + + // get the template BG + BattleGround *bg_template = GetBattleGroundTemplate(bgTypeId); + + if(!bg_template) + { + sLog.outError("BattleGround: CreateNewBattleGround - bg template not found for %u", bgTypeId); + return 0; + } + + // create a copy of the BG template + switch(bgTypeId) + { + case BATTLEGROUND_AV: + bg = new BattleGroundAV(*(BattleGroundAV*)bg_template); + break; + case BATTLEGROUND_WS: + bg = new BattleGroundWS(*(BattleGroundWS*)bg_template); + break; + case BATTLEGROUND_AB: + bg = new BattleGroundAB(*(BattleGroundAB*)bg_template); + break; + case BATTLEGROUND_NA: + bg = new BattleGroundNA(*(BattleGroundNA*)bg_template); + break; + case BATTLEGROUND_BE: + bg = new BattleGroundBE(*(BattleGroundBE*)bg_template); + break; + case BATTLEGROUND_AA: + bg = new BattleGroundAA(*(BattleGroundAA*)bg_template); + break; + case BATTLEGROUND_EY: + bg = new BattleGroundEY(*(BattleGroundEY*)bg_template); + break; + case BATTLEGROUND_RL: + bg = new BattleGroundRL(*(BattleGroundRL*)bg_template); + break; + default: + //bg = new BattleGround; + return 0; + break; // placeholder for non implemented BG + } + + // generate a new instance id + bg->SetInstanceID(MapManager::Instance().GenerateInstanceId()); // set instance id + + // reset the new bg (set status to status_wait_queue from status_none) + bg->Reset(); + + /* will be setup in BG::Update() when the first player is ported in + if(!(bg->SetupBattleGround())) + { + sLog.outError("BattleGround: CreateNewBattleGround: SetupBattleGround failed for bg %u", bgTypeId); + delete bg; + return 0; + } + */ + + // add BG to free slot queue + bg->AddToBGFreeSlotQueue(); + + // add bg to update list + AddBattleGround(bg->GetInstanceID(), bg); + + return bg; +} + +// used to create the BG templates uint32 BattleGroundMgr::CreateBattleGround(uint32 bgTypeId, uint32 MinPlayersPerTeam, uint32 MaxPlayersPerTeam, uint32 LevelMin, uint32 LevelMax, char* BattleGroundName, uint32 MapID, float Team1StartLocX, float Team1StartLocY, float Team1StartLocZ, float Team1StartLocO, float Team2StartLocX, float Team2StartLocY, float Team2StartLocZ, float Team2StartLocO) { // Create the BG @@ -658,12 +1458,8 @@ uint32 BattleGroundMgr::CreateBattleGround(uint32 bgTypeId, uint32 MinPlayersPer } bg->SetMapId(MapID); + bg->Reset(); - if(!bg->SetupBattleGround()) - { - delete bg; - return 0; - } BattlemasterListEntry const *bl = sBattlemasterListStore.LookupEntry(bgTypeId); //in previous method is checked if exists entry in sBattlemasterListStore, so no check needed @@ -673,7 +1469,7 @@ uint32 BattleGroundMgr::CreateBattleGround(uint32 bgTypeId, uint32 MinPlayersPer } bg->SetTypeID(bgTypeId); - bg->SetInstanceID(bgTypeId); // temporary + bg->SetInstanceID(0); // template bg, instance id is 0 bg->SetMinPlayersPerTeam(MinPlayersPerTeam); bg->SetMaxPlayersPerTeam(MaxPlayersPerTeam); bg->SetMinPlayers(MinPlayersPerTeam*2); @@ -682,12 +1478,14 @@ uint32 BattleGroundMgr::CreateBattleGround(uint32 bgTypeId, uint32 MinPlayersPer bg->SetTeamStartLoc(ALLIANCE, Team1StartLocX, Team1StartLocY, Team1StartLocZ, Team1StartLocO); bg->SetTeamStartLoc(HORDE, Team2StartLocX, Team2StartLocY, Team2StartLocZ, Team2StartLocO); bg->SetLevelRange(LevelMin, LevelMax); - //add BaggleGround instance to FreeSlotQueue + + //add BattleGround instance to FreeSlotQueue (.back() will return the template!) bg->AddToBGFreeSlotQueue(); - AddBattleGround(bg->GetInstanceID(), bg); - //sLog.outDetail("BattleGroundMgr: Created new battleground: %u %s (Map %u, %u players per team, Levels %u-%u)", bg_TypeID, bg->m_Name, bg->m_MapId, bg->m_MaxPlayersPerTeam, bg->m_LevelMin, bg->m_LevelMax); - return bg->GetInstanceID(); + // do NOT add to update list, since this is a template battleground! + + // return some not-null value, bgTypeId is good enough for me + return bgTypeId; } void BattleGroundMgr::CreateInitialBattleGrounds() @@ -807,6 +1605,77 @@ void BattleGroundMgr::CreateInitialBattleGrounds() sLog.outString( ">> Loaded %u battlegrounds", count ); } +void BattleGroundMgr::InitAutomaticArenaPointDistribution() +{ + if(m_AutoDistributePoints) + { + sLog.outDebug("Initializing Automatic Arena Point Distribution"); + QueryResult * result = CharacterDatabase.Query("SELECT NextArenaPointDistributionTime FROM saved_variables"); + if(!result) + { + sLog.outDebug("Battleground: Next arena point distribution time not found in SavedVariables, reseting it now."); + m_NextAutoDistributionTime = sWorld.GetGameTime() + BATTLEGROUND_ARENA_POINT_DISTRIBUTION_DAY * sWorld.getConfig(CONFIG_ARENA_AUTO_DISTRIBUTE_INTERVAL_DAYS); + CharacterDatabase.PExecute("INSERT INTO saved_variables (NextArenaPointDistributionTime) VALUES ('"I64FMTD"')", m_NextAutoDistributionTime); + } + else + { + m_NextAutoDistributionTime = (*result)[0].GetUInt64(); + delete result; + } + sLog.outDebug("Automatic Arena Point Distribution initialized."); + } +} + +void BattleGroundMgr::DistributeArenaPoints() +{ + // used to distribute arena points based on last week's stats + sWorld.SendGlobalText("Flushing Arena points based on team ratings, this may take a few minutes. Please stand by...", NULL); + + sWorld.SendGlobalText("Distributing arena points to players...", NULL); + + //temporary structure for storing maximum points to add values for all players + std::map PlayerPoints; + + //at first update all points for all team members + for(ObjectMgr::ArenaTeamMap::iterator team_itr = objmgr.GetArenaTeamMapBegin(); team_itr != objmgr.GetArenaTeamMapEnd(); ++team_itr) + { + if(ArenaTeam * at = team_itr->second) + { + at->UpdateArenaPointsHelper(PlayerPoints); + } + } + + //cycle that gives points to all players + for (std::map::iterator plr_itr = PlayerPoints.begin(); plr_itr != PlayerPoints.end(); ++plr_itr) + { + //update to database + CharacterDatabase.PExecute("UPDATE characters SET arena_pending_points = '%u' WHERE `guid` = '%u'", plr_itr->second, plr_itr->first); + //add points if player is online + Player* pl = objmgr.GetPlayer(plr_itr->first); + if (pl) + pl->ModifyArenaPoints(plr_itr->second); + } + + PlayerPoints.clear(); + + sWorld.SendGlobalText("Finished setting arena points for online players.", NULL); + + sWorld.SendGlobalText("Modifying played count, arena points etc. for loaded arena teams, sending updated stats to online players...", NULL); + for(ObjectMgr::ArenaTeamMap::iterator titr = objmgr.GetArenaTeamMapBegin(); titr != objmgr.GetArenaTeamMapEnd(); ++titr) + { + if(ArenaTeam * at = titr->second) + { + at->FinishWeek(); // set played this week etc values to 0 in memory, too + at->SaveToDB(); // save changes + at->NotifyStatsChanged(); // notify the players of the changes + } + } + + sWorld.SendGlobalText("Modification done.", NULL); + + sWorld.SendGlobalText("Done flushing Arena points.", NULL); +} + void BattleGroundMgr::BuildBattleGroundListPacket(WorldPacket *data, uint64 guid, Player* plr, uint32 bgTypeId) { uint32 PlayerLevel = 10; @@ -842,18 +1711,25 @@ void BattleGroundMgr::BuildBattleGroundListPacket(WorldPacket *data, uint64 guid } } -void BattleGroundMgr::SendToBattleGround(Player *pl, uint32 bgTypeId) +void BattleGroundMgr::SendToBattleGround(Player *pl, uint32 instanceId) { - BattleGround *bg = GetBattleGround(bgTypeId); + BattleGround *bg = GetBattleGround(instanceId); if(bg) { uint32 mapid = bg->GetMapId(); float x, y, z, O; - bg->GetTeamStartLoc(pl->GetTeam(), x, y, z, O); + uint32 team = pl->GetBGTeam(); + if(team==0) + team = pl->GetTeam(); + bg->GetTeamStartLoc(team, x, y, z, O); sLog.outDetail("BATTLEGROUND: Sending %s to map %u, X %f, Y %f, Z %f, O %f", pl->GetName(), mapid, x, y, z, O); pl->TeleportTo(mapid, x, y, z, O); } + else + { + sLog.outError("player %u trying to port to non-existent bg instance %u",pl->GetGUIDLow(), instanceId); + } } void BattleGroundMgr::SendAreaSpiritHealerQueryOpcode(Player *pl, BattleGround *bg, uint64 guid) @@ -865,3 +1741,100 @@ void BattleGroundMgr::SendAreaSpiritHealerQueryOpcode(Player *pl, BattleGround * data << guid << time_; pl->GetSession()->SendPacket(&data); } + +void BattleGroundMgr::RemoveBattleGround(uint32 instanceID) +{ + BattleGroundSet::iterator itr = m_BattleGrounds.find(instanceID); + if(itr!=m_BattleGrounds.end()) + m_BattleGrounds.erase(itr); +} + +bool BattleGroundMgr::IsArenaType(uint32 bgTypeId) const +{ + return ( bgTypeId == BATTLEGROUND_AA || + bgTypeId == BATTLEGROUND_BE || + bgTypeId == BATTLEGROUND_NA || + bgTypeId == BATTLEGROUND_RL ); +} + +bool BattleGroundMgr::IsBattleGroundType(uint32 bgTypeId) const +{ + return !IsArenaType(bgTypeId); +} + +uint32 BattleGroundMgr::BGQueueTypeId(uint32 bgTypeId, uint8 arenaType) const +{ + switch(bgTypeId) + { + case BATTLEGROUND_WS: + return BATTLEGROUND_QUEUE_WS; + case BATTLEGROUND_AB: + return BATTLEGROUND_QUEUE_AB; + case BATTLEGROUND_AV: + return BATTLEGROUND_QUEUE_AV; + case BATTLEGROUND_EY: + return BATTLEGROUND_QUEUE_EY; + case BATTLEGROUND_AA: + case BATTLEGROUND_NA: + case BATTLEGROUND_RL: + case BATTLEGROUND_BE: + switch(arenaType) + { + case ARENA_TYPE_2v2: + return BATTLEGROUND_QUEUE_2v2; + case ARENA_TYPE_3v3: + return BATTLEGROUND_QUEUE_3v3; + case ARENA_TYPE_5v5: + return BATTLEGROUND_QUEUE_5v5; + default: + return 0; + } + default: + return 0; + } +} + +uint32 BattleGroundMgr::BGTemplateId(uint32 bgQueueTypeId) const +{ + switch(bgQueueTypeId) + { + case BATTLEGROUND_QUEUE_WS: + return BATTLEGROUND_WS; + case BATTLEGROUND_QUEUE_AB: + return BATTLEGROUND_AB; + case BATTLEGROUND_QUEUE_AV: + return BATTLEGROUND_AV; + case BATTLEGROUND_QUEUE_EY: + return BATTLEGROUND_EY; + case BATTLEGROUND_QUEUE_2v2: + case BATTLEGROUND_QUEUE_3v3: + case BATTLEGROUND_QUEUE_5v5: + return BATTLEGROUND_AA; + default: + return 0; + } +} + +uint8 BattleGroundMgr::BGArenaType(uint32 bgQueueTypeId) const +{ + switch(bgQueueTypeId) + { + case BATTLEGROUND_QUEUE_2v2: + return ARENA_TYPE_2v2; + case BATTLEGROUND_QUEUE_3v3: + return ARENA_TYPE_3v3; + case BATTLEGROUND_QUEUE_5v5: + return ARENA_TYPE_5v5; + default: + return 0; + } +} + +void BattleGroundMgr::ToggleArenaTesting() +{ + m_ArenaTesting = !m_ArenaTesting; + if(m_ArenaTesting) + sWorld.SendGlobalText("Arenas are set to 1v1 for debugging. So, don't join as group.", NULL); + else + sWorld.SendGlobalText("Arenas are set to normal playercount.", NULL); +} diff --git a/src/game/BattleGroundMgr.h b/src/game/BattleGroundMgr.h index 193e5f430..2998efed8 100644 --- a/src/game/BattleGroundMgr.h +++ b/src/game/BattleGroundMgr.h @@ -30,55 +30,103 @@ typedef std::map BattleGroundSet; //typedef std::map BattleGroundQueueSet; typedef std::deque BGFreeSlotQueueType; -#define MAX_BATTLEGROUND_QUEUES 7 // for level ranges 10-19, 20-29, 30-39, 40-49, 50-59, 60-69, 70+ +#define MAX_BATTLEGROUND_QUEUES 8 // for level ranges 10-19, 20-29, 30-39, 40-49, 50-59, 60-69, 70-79, 80+ -#define MAX_BATTLEGROUND_TYPES 9 // each BG type will be in array +#define MAX_BATTLEGROUND_TYPES 12 // each BG type will be in array -struct PlayerQueueInfo +#define MAX_BATTLEGROUND_QUEUE_TYPES 8 + +#define BATTLEGROUND_ARENA_POINT_DISTRIBUTION_DAY 86400 // seconds in a day + +struct GroupQueueInfo; // type predefinition +struct PlayerQueueInfo // stores information for players in queue { uint32 InviteTime; // first invite time uint32 LastInviteTime; // last invite time - uint32 IsInvitedToBGInstanceGUID; // was invited to certain BG uint32 LastOnlineTime; // for tracking and removing offline players from queue after 5 minutes + GroupQueueInfo * GroupInfo; // pointer to the associated groupqueueinfo +}; + +struct GroupQueueInfo // stores information about the group in queue (also used when joined as solo!) +{ + std::map Players; // player queue info map uint32 Team; // Player team (ALLIANCE/HORDE) - bool IsRated; - bool AsGroup; // uint32 GroupId; - uint8 ArenaType; -}; - -struct PlayersCount -{ - uint32 Alliance; - uint32 Horde; -}; - -template class bgqueue: public std::map<_Kty, _Ty> -{ - public: - uint32 Alliance; - uint32 Horde; - //bool Ready; // not used now - //uint32 AverageTime; //not already implemented (it should be average time in queue for last 10 players) + uint32 BgTypeId; // battleground type id + bool IsRated; // rated + uint8 ArenaType; // 2v2, 3v3, 5v5 or 0 when BG + uint32 ArenaTeamId; // team id if rated match + uint32 JoinTime; // time when group was added + uint32 IsInvitedToBGInstanceGUID; // was invited to certain BG + uint32 ArenaTeamRating; // if rated match, inited to the rating of the team + uint32 OpponentsTeamRating; // for rated arena matches }; +class BattleGround; class BattleGroundQueue { public: BattleGroundQueue(); ~BattleGroundQueue(); -/* - uint32 GetType(); - void SetType(uint32 type);*/ - void Update(uint32 bgTypeId, uint32 queue_id); + void Update(uint32 bgTypeId, uint32 queue_id, uint8 arenatype = 0, bool isRated = false, uint32 minRating = 0); - void AddPlayer(Player *plr, uint32 bgTypeId); + GroupQueueInfo * AddGroup(Player * leader, uint32 BgTypeId, uint8 ArenaType, bool isRated, uint32 ArenaRating, uint32 ArenaTeamId = 0); + void AddPlayer(Player *plr, GroupQueueInfo *ginfo); void RemovePlayer(uint64 guid, bool decreaseInvitedCount); + void DecreaseGroupLength(uint32 queueId, uint32 AsGroup); + void BGEndedRemoveInvites(BattleGround * bg); - typedef bgqueue QueuedPlayersMap; + typedef std::map QueuedPlayersMap; QueuedPlayersMap m_QueuedPlayers[MAX_BATTLEGROUND_QUEUES]; - typedef std::list PlayerGuidsSortedByTimeQueue; - PlayerGuidsSortedByTimeQueue m_PlayersSortedByWaitTime[MAX_BATTLEGROUND_QUEUES]; + + typedef std::list QueuedGroupsList; + QueuedGroupsList m_QueuedGroups[MAX_BATTLEGROUND_QUEUES]; + + // class to hold pointers to the groups eligible for a specific selection pool building mode + class EligibleGroups : public std::list + { + public: + void Init(QueuedGroupsList * source, uint32 BgTypeId, uint32 side, uint32 MaxPlayers, uint8 ArenaType = 0, bool IsRated = false, uint32 MinRating = 0, uint32 MaxRating = 0, uint32 DisregardTime = 0, uint32 excludeTeam = 0); + void RemoveGroup(GroupQueueInfo * ginfo); + }; + + EligibleGroups m_EligibleGroups; + + // class to select and invite groups to bg + class SelectionPool + { + public: + void Init(); + void AddGroup(GroupQueueInfo * group); + GroupQueueInfo * GetMaximalGroup(); + void RemoveGroup(GroupQueueInfo * group); + uint32 GetPlayerCount() const {return PlayerCount;} + public: + std::list SelectedGroups; + private: + uint32 PlayerCount; + GroupQueueInfo * MaxGroup; + }; + + enum SelectionPoolBuildMode + { + NORMAL_ALLIANCE, + NORMAL_HORDE, + ONESIDE_ALLIANCE_TEAM1, + ONESIDE_ALLIANCE_TEAM2, + ONESIDE_HORDE_TEAM1, + ONESIDE_HORDE_TEAM2, + + NUM_SELECTION_POOL_TYPES + }; + + SelectionPool m_SelectionPools[NUM_SELECTION_POOL_TYPES]; + + bool BuildSelectionPool(uint32 bgTypeId, uint32 queue_id, uint32 MinPlayers, uint32 MaxPlayers, SelectionPoolBuildMode mode, uint8 ArenaType = 0, bool isRated = false, uint32 MinRating = 0, uint32 MaxRating = 0, uint32 DisregardTime = 0, uint32 excludeTeam = 0); + + private: + + bool InviteGroupToBG(GroupQueueInfo * ginfo, BattleGround * bg, uint32 side); }; /* @@ -96,7 +144,6 @@ class BGQueueInviteEvent : public BasicEvent private: uint64 m_PlayerGuid; uint32 m_BgInstanceGUID; - }; /* @@ -116,7 +163,6 @@ class BGQueueRemoveEvent : public BasicEvent uint32 m_PlayersTeam; }; - class BattleGroundMgr { public: @@ -132,18 +178,18 @@ class BattleGroundMgr void BuildGroupJoinedBattlegroundPacket(WorldPacket *data, uint32 bgTypeId); void BuildUpdateWorldStatePacket(WorldPacket *data, uint32 field, uint32 value); void BuildPvpLogDataPacket(WorldPacket *data, BattleGround *bg); - void BuildBattleGroundStatusPacket(WorldPacket *data, BattleGround *bg, uint32 team, uint8 QueueSlot, uint8 StatusID, uint32 Time1, uint32 Time2); + void BuildBattleGroundStatusPacket(WorldPacket *data, BattleGround *bg, uint32 team, uint8 QueueSlot, uint8 StatusID, uint32 Time1, uint32 Time2, uint32 arenatype = 0, uint8 israted = 0); void BuildPlaySoundPacket(WorldPacket *data, uint32 soundid); /* Player invitation */ // called from Queue update, or from Addplayer to queue - void InvitePlayer(Player* plr, uint32 bgInstanceGUID); + void InvitePlayer(Player* plr, uint32 bgInstanceGUID, uint32 team); /* Battlegrounds */ BattleGroundSet::iterator GetBattleGroundsBegin() { return m_BattleGrounds.begin(); }; BattleGroundSet::iterator GetBattleGroundsEnd() { return m_BattleGrounds.end(); }; - BattleGround* GetBattleGround(uint8 ID) + BattleGround* GetBattleGround(uint32 ID) { BattleGroundSet::iterator i = m_BattleGrounds.find(ID); if(i != m_BattleGrounds.end()) @@ -152,9 +198,13 @@ class BattleGroundMgr return NULL; }; + BattleGround * GetBattleGroundTemplate(uint32 bgTypeId); + BattleGround * CreateNewBattleGround(uint32 bgTypeId); + uint32 CreateBattleGround(uint32 bgTypeId, uint32 MinPlayersPerTeam, uint32 MaxPlayersPerTeam, uint32 LevelMin, uint32 LevelMax, char* BattleGroundName, uint32 MapID, float Team1StartLocX, float Team1StartLocY, float Team1StartLocZ, float Team1StartLocO, float Team2StartLocX, float Team2StartLocY, float Team2StartLocZ, float Team2StartLocO); inline void AddBattleGround(uint32 ID, BattleGround* BG) { m_BattleGrounds[ID] = BG; }; + void RemoveBattleGround(uint32 instanceID); void CreateInitialBattleGrounds(); @@ -162,16 +212,39 @@ class BattleGroundMgr /* Battleground queues */ //these queues are instantiated when creating BattlegroundMrg - BattleGroundQueue m_BattleGroundQueues[MAX_BATTLEGROUND_TYPES]; // public, because we need to access them in BG handler code + BattleGroundQueue m_BattleGroundQueues[MAX_BATTLEGROUND_QUEUE_TYPES]; // public, because we need to access them in BG handler code BGFreeSlotQueueType BGFreeSlotQueue[MAX_BATTLEGROUND_TYPES]; void SendAreaSpiritHealerQueryOpcode(Player *pl, BattleGround *bg, uint64 guid); + bool IsArenaType(uint32 bgTypeId) const; + bool IsBattleGroundType(uint32 bgTypeId) const; + uint32 BGQueueTypeId(uint32 bgTypeId, uint8 arenaType) const; + uint32 BGTemplateId(uint32 bgQueueTypeId) const; + uint8 BGArenaType(uint32 bgQueueTypeId) const; + + uint32 GetMaxRatingDifference() const {return m_MaxRatingDifference;} + uint32 GetRatingDiscardTimer() const {return m_RatingDiscardTimer;} + + void InitAutomaticArenaPointDistribution(); + void DistributeArenaPoints(); + uint32 GetPrematureFinishTime() const {return m_PrematureFinishTimer;} + void ToggleArenaTesting(); + const bool isArenaTesting() const { return m_ArenaTesting; } + private: /* Battlegrounds */ BattleGroundSet m_BattleGrounds; + uint32 m_MaxRatingDifference; + uint32 m_RatingDiscardTimer; + uint32 m_NextRatingDiscardUpdate; + bool m_AutoDistributePoints; + uint64 m_NextAutoDistributionTime; + uint32 m_AutoDistributionTimeChecker; + uint32 m_PrematureFinishTimer; + bool m_ArenaTesting; }; #define sBattleGroundMgr MaNGOS::Singleton::Instance() diff --git a/src/game/BattleGroundNA.cpp b/src/game/BattleGroundNA.cpp index ac4705f5c..385de1211 100644 --- a/src/game/BattleGroundNA.cpp +++ b/src/game/BattleGroundNA.cpp @@ -47,6 +47,12 @@ void BattleGroundNA::Update(time_t diff) if (!(m_Events & 0x01)) { m_Events |= 0x01; + // setup here, only when at least one player has ported to the map + if(!SetupBattleGround()) + { + EndNow(); + return; + } for(uint32 i = BG_NA_OBJECT_DOOR_1; i <= BG_NA_OBJECT_DOOR_4; i++) SpawnBGObject(i, RESPAWN_IMMEDIATELY); @@ -73,6 +79,9 @@ void BattleGroundNA::Update(time_t diff) for(uint32 i = BG_NA_OBJECT_DOOR_1; i <= BG_NA_OBJECT_DOOR_2; i++) DoorOpen(i); + for(uint32 i = BG_NA_OBJECT_BUFF_1; i <= BG_NA_OBJECT_BUFF_2; i++) + SpawnBGObject(i, 60); + SendMessageToAll(LANG_ARENA_BEGUN); SetStatus(STATUS_IN_PROGRESS); SetStartDelayTime(0); @@ -80,6 +89,11 @@ void BattleGroundNA::Update(time_t diff) for(BattleGroundPlayerMap::const_iterator itr = GetPlayers().begin(); itr != GetPlayers().end(); ++itr) if(Player *plr = objmgr.GetPlayer(itr->first)) plr->RemoveAurasDueToSpell(SPELL_ARENA_PREPARATION); + + if(!GetPlayersCountByTeam(ALLIANCE) && GetPlayersCountByTeam(HORDE)) + EndBattleGround(HORDE); + else if(GetPlayersCountByTeam(ALLIANCE) && !GetPlayersCountByTeam(HORDE)) + EndBattleGround(ALLIANCE); } } @@ -96,11 +110,23 @@ void BattleGroundNA::AddPlayer(Player *plr) BattleGroundNAScore* sc = new BattleGroundNAScore; m_PlayerScores[plr->GetGUID()] = sc; + + UpdateWorldState(0xa0f, GetAlivePlayersCountByTeam(ALLIANCE)); + UpdateWorldState(0xa10, GetAlivePlayersCountByTeam(HORDE)); } void BattleGroundNA::RemovePlayer(Player* /*plr*/, uint64 /*guid*/) { + if(GetStatus() == STATUS_WAIT_LEAVE) + return; + UpdateWorldState(0xa0f, GetAlivePlayersCountByTeam(ALLIANCE)); + UpdateWorldState(0xa10, GetAlivePlayersCountByTeam(HORDE)); + + if(!GetAlivePlayersCountByTeam(ALLIANCE) && GetPlayersCountByTeam(HORDE)) + EndBattleGround(HORDE); + else if(GetPlayersCountByTeam(ALLIANCE) && !GetAlivePlayersCountByTeam(HORDE)) + EndBattleGround(ALLIANCE); } void BattleGroundNA::HandleKillPlayer(Player *player, Player *killer) @@ -114,17 +140,27 @@ void BattleGroundNA::HandleKillPlayer(Player *player, Player *killer) return; } - BattleGround::HandleKillPlayer(player, killer); + BattleGround::HandleKillPlayer(player,killer); - uint32 killer_team_index = GetTeamIndexByTeamId(killer->GetTeam()); + UpdateWorldState(0xa0f, GetAlivePlayersCountByTeam(ALLIANCE)); + UpdateWorldState(0xa10, GetAlivePlayersCountByTeam(HORDE)); - ++m_TeamKills[killer_team_index]; // add kills to killer's team - - if(m_TeamKills[killer_team_index] >= GetPlayersCountByTeam(player->GetTeam())) + if(!GetAlivePlayersCountByTeam(ALLIANCE)) { // all opponents killed - EndBattleGround(killer->GetTeam()); + EndBattleGround(HORDE); } + else if(!GetAlivePlayersCountByTeam(HORDE)) + { + // all opponents killed + EndBattleGround(ALLIANCE); + } +} + +bool BattleGroundNA::HandlePlayerUnderMap(Player *player) +{ + player->TeleportTo(GetMapId(),4055.504395,2919.660645,13.611241,player->GetOrientation(),false); + return true; } void BattleGroundNA::HandleAreaTrigger(Player *Source, uint32 Trigger) @@ -149,19 +185,28 @@ void BattleGroundNA::HandleAreaTrigger(Player *Source, uint32 Trigger) // HandleTriggerBuff(buff_guid,Source); } +void BattleGroundNA::FillInitialWorldStates(WorldPacket &data) +{ + data << uint32(0xa0f) << uint32(GetAlivePlayersCountByTeam(ALLIANCE)); // 7 + data << uint32(0xa10) << uint32(GetAlivePlayersCountByTeam(HORDE)); // 8 + data << uint32(0xa11) << uint32(1); // 9 +} + void BattleGroundNA::ResetBGSubclass() { - m_TeamKills[BG_TEAM_ALLIANCE] = 0; - m_TeamKills[BG_TEAM_HORDE] = 0; + } bool BattleGroundNA::SetupBattleGround() { // gates - if( !AddObject(BG_NA_OBJECT_DOOR_1, BG_NA_OBJECT_TYPE_DOOR_1, 4031.854f, 2966.833f, 12.6462f, -2.648788f, 0, 0, 0.9697962f, -0.2439165f, RESPAWN_IMMEDIATELY) - || !AddObject(BG_NA_OBJECT_DOOR_2, BG_NA_OBJECT_TYPE_DOOR_2, 4081.179f, 2874.97f, 12.39171f, 0.4928045f, 0, 0, 0.2439165f, 0.9697962f, RESPAWN_IMMEDIATELY) - || !AddObject(BG_NA_OBJECT_DOOR_3, BG_NA_OBJECT_TYPE_DOOR_3, 4023.709f, 2981.777f, 10.70117f, -2.648788f, 0, 0, 0.9697962f, -0.2439165f, RESPAWN_IMMEDIATELY) - || !AddObject(BG_NA_OBJECT_DOOR_4, BG_NA_OBJECT_TYPE_DOOR_4, 4090.064f, 2858.438f, 10.23631f, 0.4928045f, 0, 0, 0.2439165f, 0.9697962f, RESPAWN_IMMEDIATELY)) + if( !AddObject(BG_NA_OBJECT_DOOR_1, BG_NA_OBJECT_TYPE_DOOR_1, 4031.854, 2966.833, 12.6462, -2.648788, 0, 0, 0.9697962, -0.2439165, RESPAWN_IMMEDIATELY) + || !AddObject(BG_NA_OBJECT_DOOR_2, BG_NA_OBJECT_TYPE_DOOR_2, 4081.179, 2874.97, 12.39171, 0.4928045, 0, 0, 0.2439165, 0.9697962, RESPAWN_IMMEDIATELY) + || !AddObject(BG_NA_OBJECT_DOOR_3, BG_NA_OBJECT_TYPE_DOOR_3, 4023.709, 2981.777, 10.70117, -2.648788, 0, 0, 0.9697962, -0.2439165, RESPAWN_IMMEDIATELY) + || !AddObject(BG_NA_OBJECT_DOOR_4, BG_NA_OBJECT_TYPE_DOOR_4, 4090.064, 2858.438, 10.23631, 0.4928045, 0, 0, 0.2439165, 0.9697962, RESPAWN_IMMEDIATELY) + // buffs + || !AddObject(BG_NA_OBJECT_BUFF_1, BG_NA_OBJECT_TYPE_BUFF_1, 4009.189941, 2895.250000, 13.052700, -1.448624, 0, 0, 0.6626201, -0.7489557, 120) + || !AddObject(BG_NA_OBJECT_BUFF_2, BG_NA_OBJECT_TYPE_BUFF_2, 4103.330078, 2946.350098, 13.051300, -0.06981307, 0, 0, 0.03489945, -0.9993908, 120)) { sLog.outErrorDb("BatteGroundNA: Failed to spawn some object!"); return false; diff --git a/src/game/BattleGroundNA.h b/src/game/BattleGroundNA.h index 723e5b08e..a44460919 100644 --- a/src/game/BattleGroundNA.h +++ b/src/game/BattleGroundNA.h @@ -26,7 +26,9 @@ enum BattleGroundNAObjectTypes BG_NA_OBJECT_DOOR_2 = 1, BG_NA_OBJECT_DOOR_3 = 2, BG_NA_OBJECT_DOOR_4 = 3, - BG_NA_OBJECT_MAX = 4 + BG_NA_OBJECT_BUFF_1 = 4, + BG_NA_OBJECT_BUFF_2 = 5, + BG_NA_OBJECT_MAX = 6 }; enum BattleGroundNAObjects @@ -34,7 +36,9 @@ enum BattleGroundNAObjects BG_NA_OBJECT_TYPE_DOOR_1 = 183978, BG_NA_OBJECT_TYPE_DOOR_2 = 183980, BG_NA_OBJECT_TYPE_DOOR_3 = 183977, - BG_NA_OBJECT_TYPE_DOOR_4 = 183979 + BG_NA_OBJECT_TYPE_DOOR_4 = 183979, + BG_NA_OBJECT_TYPE_BUFF_1 = 184663, + BG_NA_OBJECT_TYPE_BUFF_2 = 184664 }; class BattleGroundNAScore : public BattleGroundScore @@ -61,9 +65,8 @@ class BattleGroundNA : public BattleGround void HandleAreaTrigger(Player *Source, uint32 Trigger); bool SetupBattleGround(); virtual void ResetBGSubclass(); + virtual void FillInitialWorldStates(WorldPacket &d); void HandleKillPlayer(Player* player, Player *killer); - - private: - uint32 m_TeamKills[2]; // count of kills for each team + bool HandlePlayerUnderMap(Player * plr); }; #endif diff --git a/src/game/BattleGroundRL.cpp b/src/game/BattleGroundRL.cpp index 4be135c70..bf3b5b029 100644 --- a/src/game/BattleGroundRL.cpp +++ b/src/game/BattleGroundRL.cpp @@ -47,6 +47,13 @@ void BattleGroundRL::Update(time_t diff) { m_Events |= 0x01; + // setup here, only when at least one player has ported to the map + if(!SetupBattleGround()) + { + EndNow(); + return; + } + for(uint32 i = BG_RL_OBJECT_DOOR_1; i <= BG_RL_OBJECT_DOOR_2; i++) SpawnBGObject(i, RESPAWN_IMMEDIATELY); @@ -73,6 +80,9 @@ void BattleGroundRL::Update(time_t diff) for(uint32 i = BG_RL_OBJECT_DOOR_1; i <= BG_RL_OBJECT_DOOR_2; i++) DoorOpen(i); + for(uint32 i = BG_RL_OBJECT_BUFF_1; i <= BG_RL_OBJECT_BUFF_2; i++) + SpawnBGObject(i, 60); + SendMessageToAll(LANG_ARENA_BEGUN); SetStatus(STATUS_IN_PROGRESS); SetStartDelayTime(0); @@ -80,6 +90,11 @@ void BattleGroundRL::Update(time_t diff) for(BattleGroundPlayerMap::const_iterator itr = GetPlayers().begin(); itr != GetPlayers().end(); ++itr) if(Player *plr = objmgr.GetPlayer(itr->first)) plr->RemoveAurasDueToSpell(SPELL_ARENA_PREPARATION); + + if(!GetPlayersCountByTeam(ALLIANCE) && GetPlayersCountByTeam(HORDE)) + EndBattleGround(HORDE); + else if(GetPlayersCountByTeam(ALLIANCE) && !GetPlayersCountByTeam(HORDE)) + EndBattleGround(ALLIANCE); } } @@ -96,11 +111,23 @@ void BattleGroundRL::AddPlayer(Player *plr) BattleGroundRLScore* sc = new BattleGroundRLScore; m_PlayerScores[plr->GetGUID()] = sc; + + UpdateWorldState(0xbb8, GetAlivePlayersCountByTeam(ALLIANCE)); + UpdateWorldState(0xbb9, GetAlivePlayersCountByTeam(HORDE)); } void BattleGroundRL::RemovePlayer(Player* /*plr*/, uint64 /*guid*/) { + if(GetStatus() == STATUS_WAIT_LEAVE) + return; + UpdateWorldState(0xbb8, GetAlivePlayersCountByTeam(ALLIANCE)); + UpdateWorldState(0xbb9, GetAlivePlayersCountByTeam(HORDE)); + + if(!GetAlivePlayersCountByTeam(ALLIANCE) && GetPlayersCountByTeam(HORDE)) + EndBattleGround(HORDE); + else if(GetPlayersCountByTeam(ALLIANCE) && !GetAlivePlayersCountByTeam(HORDE)) + EndBattleGround(ALLIANCE); } void BattleGroundRL::HandleKillPlayer(Player *player, Player *killer) @@ -114,17 +141,27 @@ void BattleGroundRL::HandleKillPlayer(Player *player, Player *killer) return; } - BattleGround::HandleKillPlayer(player, killer); + BattleGround::HandleKillPlayer(player,killer); - uint32 killer_team_index = GetTeamIndexByTeamId(killer->GetTeam()); + UpdateWorldState(0xbb8, GetAlivePlayersCountByTeam(ALLIANCE)); + UpdateWorldState(0xbb9, GetAlivePlayersCountByTeam(HORDE)); - ++m_TeamKills[killer_team_index]; // add kills to killer's team - - if(m_TeamKills[killer_team_index] >= GetPlayersCountByTeam(player->GetTeam())) + if(!GetAlivePlayersCountByTeam(ALLIANCE)) { // all opponents killed - EndBattleGround(killer->GetTeam()); + EndBattleGround(HORDE); } + else if(!GetAlivePlayersCountByTeam(HORDE)) + { + // all opponents killed + EndBattleGround(ALLIANCE); + } +} + +bool BattleGroundRL::HandlePlayerUnderMap(Player *player) +{ + player->TeleportTo(GetMapId(),1285.810547,1667.896851,39.957642,player->GetOrientation(),false); + return true; } void BattleGroundRL::HandleAreaTrigger(Player *Source, uint32 Trigger) @@ -150,17 +187,26 @@ void BattleGroundRL::HandleAreaTrigger(Player *Source, uint32 Trigger) // HandleTriggerBuff(buff_guid,Source); } +void BattleGroundRL::FillInitialWorldStates(WorldPacket &data) +{ + data << uint32(0xbb8) << uint32(GetAlivePlayersCountByTeam(ALLIANCE)); // 7 + data << uint32(0xbb9) << uint32(GetAlivePlayersCountByTeam(HORDE)); // 8 + data << uint32(0xbba) << uint32(1); // 9 +} + void BattleGroundRL::ResetBGSubclass() { - m_TeamKills[BG_TEAM_ALLIANCE] = 0; - m_TeamKills[BG_TEAM_HORDE] = 0; + } bool BattleGroundRL::SetupBattleGround() { // gates - if( !AddObject(BG_RL_OBJECT_DOOR_1, BG_RL_OBJECT_TYPE_DOOR_1, 1293.561f, 1601.938f, 31.60557f, -1.457349f, 0, 0, -0.6658813f, 0.7460576f, RESPAWN_IMMEDIATELY) - || !AddObject(BG_RL_OBJECT_DOOR_2, BG_RL_OBJECT_TYPE_DOOR_2, 1278.648f, 1730.557f, 31.60557f, 1.684245f, 0, 0, 0.7460582f, 0.6658807f, RESPAWN_IMMEDIATELY)) + if( !AddObject(BG_RL_OBJECT_DOOR_1, BG_RL_OBJECT_TYPE_DOOR_1, 1293.561, 1601.938, 31.60557, -1.457349, 0, 0, -0.6658813, 0.7460576, RESPAWN_IMMEDIATELY) + || !AddObject(BG_RL_OBJECT_DOOR_2, BG_RL_OBJECT_TYPE_DOOR_2, 1278.648, 1730.557, 31.60557, 1.684245, 0, 0, 0.7460582, 0.6658807, RESPAWN_IMMEDIATELY) + // buffs + || !AddObject(BG_RL_OBJECT_BUFF_1, BG_RL_OBJECT_TYPE_BUFF_1, 1328.719971, 1632.719971, 36.730400, -1.448624, 0, 0, 0.6626201, -0.7489557, 120) + || !AddObject(BG_RL_OBJECT_BUFF_2, BG_RL_OBJECT_TYPE_BUFF_2, 1243.300049, 1699.170044, 34.872601, -0.06981307, 0, 0, 0.03489945, -0.9993908, 120)) { sLog.outErrorDb("BatteGroundRL: Failed to spawn some object!"); return false; diff --git a/src/game/BattleGroundRL.h b/src/game/BattleGroundRL.h index 0e9a38bca..dd000ce13 100644 --- a/src/game/BattleGroundRL.h +++ b/src/game/BattleGroundRL.h @@ -24,13 +24,17 @@ enum BattleGroundRLObjectTypes { BG_RL_OBJECT_DOOR_1 = 0, BG_RL_OBJECT_DOOR_2 = 1, - BG_RL_OBJECT_MAX = 2 + BG_RL_OBJECT_BUFF_1 = 2, + BG_RL_OBJECT_BUFF_2 = 3, + BG_RL_OBJECT_MAX = 4 }; enum BattleGroundRLObjects { BG_RL_OBJECT_TYPE_DOOR_1 = 185918, - BG_RL_OBJECT_TYPE_DOOR_2 = 185917 + BG_RL_OBJECT_TYPE_DOOR_2 = 185917, + BG_RL_OBJECT_TYPE_BUFF_1 = 184663, + BG_RL_OBJECT_TYPE_BUFF_2 = 184664 }; class BattleGroundRLScore : public BattleGroundScore @@ -57,9 +61,8 @@ class BattleGroundRL : public BattleGround void HandleAreaTrigger(Player *Source, uint32 Trigger); bool SetupBattleGround(); virtual void ResetBGSubclass(); + virtual void FillInitialWorldStates(WorldPacket &d); void HandleKillPlayer(Player* player, Player *killer); - - private: - uint32 m_TeamKills[2]; // count of kills for each team + bool HandlePlayerUnderMap(Player * plr); }; #endif diff --git a/src/game/BattleGroundWS.cpp b/src/game/BattleGroundWS.cpp index 23c90a763..53c67c16f 100644 --- a/src/game/BattleGroundWS.cpp +++ b/src/game/BattleGroundWS.cpp @@ -49,6 +49,16 @@ void BattleGroundWS::Update(time_t diff) { m_Events |= 0x01; + // setup here, only when at least one player has ported to the map + if(!SetupBattleGround()) + { + EndNow(); + return; + } + +// for(uint32 i = WS_SPIRIT_MAIN_ALLIANCE; i <= WS_SPIRIT_MAIN_HORDE; i++) +// SpawnBGCreature(i, RESPAWN_IMMEDIATELY); + for(uint32 i = BG_WS_OBJECT_DOOR_A_1; i <= BG_WS_OBJECT_DOOR_H_4; i++) { SpawnBGObject(i, RESPAWN_IMMEDIATELY); @@ -285,7 +295,32 @@ void BattleGroundWS::EventPlayerCapturedFlag(Player *Source) void BattleGroundWS::EventPlayerDroppedFlag(Player *Source) { - // Drop allowed in any BG state + if(GetStatus() != STATUS_IN_PROGRESS) + { + // if not running, do not cast things at the dropper player (prevent spawning the "dropped" flag), neither send unnecessary messages + // just take off the aura + if(Source->GetTeam() == ALLIANCE) + { + if(!this->IsHordeFlagPickedup()) + return; + if(GetHordeFlagPickerGUID() == Source->GetGUID()) + { + SetHordeFlagPicker(0); + Source->RemoveAurasDueToSpell(BG_WS_SPELL_WARSONG_FLAG); + } + } + else + { + if(!this->IsAllianceFlagPickedup()) + return; + if(GetAllianceFlagPickerGUID() == Source->GetGUID()) + { + SetAllianceFlagPicker(0); + Source->RemoveAurasDueToSpell(BG_WS_SPELL_SILVERWING_FLAG); + } + } + return; + } const char *message = ""; uint8 type = 0; diff --git a/src/game/Calendar.cpp b/src/game/Calendar.cpp new file mode 100644 index 000000000..cebf7252e --- /dev/null +++ b/src/game/Calendar.cpp @@ -0,0 +1,17 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ diff --git a/src/game/Calendar.h b/src/game/Calendar.h new file mode 100644 index 000000000..94e4ff103 --- /dev/null +++ b/src/game/Calendar.h @@ -0,0 +1,26 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef MANGOS_CALENDAR_H +#define MANGOS_CALENDAR_H + +class Calendar +{ + +}; +#endif diff --git a/src/game/CalendarHandler.cpp b/src/game/CalendarHandler.cpp new file mode 100644 index 000000000..9c69e3a91 --- /dev/null +++ b/src/game/CalendarHandler.cpp @@ -0,0 +1,118 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "Common.h" +#include "Log.h" +#include "Player.h" +#include "WorldPacket.h" +#include "WorldSession.h" +#include "Opcodes.h" + +void WorldSession::HandleCalendarGetCalendar(WorldPacket &recv_data) +{ + sLog.outDebug("WORLD: CMSG_CALENDAR_GET_CALENDAR"); + recv_data.hexlike(); +} + +void WorldSession::HandleCalendarGetEvent(WorldPacket &recv_data) +{ + sLog.outDebug("WORLD: CMSG_CALENDAR_GET_EVENT"); + recv_data.hexlike(); +} + +void WorldSession::HandleCalendarGuildFilter(WorldPacket &recv_data) +{ + sLog.outDebug("WORLD: CMSG_CALENDAR_GUILD_FILTER"); + recv_data.hexlike(); +} + +void WorldSession::HandleCalendarArenaTeam(WorldPacket &recv_data) +{ + sLog.outDebug("WORLD: CMSG_CALENDAR_ARENA_TEAM"); + recv_data.hexlike(); +} + +void WorldSession::HandleCalendarAddEvent(WorldPacket &recv_data) +{ + sLog.outDebug("WORLD: CMSG_CALENDAR_ADD_EVENT"); + recv_data.hexlike(); +} + +void WorldSession::HandleCalendarUpdateEvent(WorldPacket &recv_data) +{ + sLog.outDebug("WORLD: CMSG_CALENDAR_UPDATE_EVENT"); + recv_data.hexlike(); +} + +void WorldSession::HandleCalendarRemoveEvent(WorldPacket &recv_data) +{ + sLog.outDebug("WORLD: CMSG_CALENDAR_REMOVE_EVENT"); + recv_data.hexlike(); +} + +void WorldSession::HandleCalendarCopyEvent(WorldPacket &recv_data) +{ + sLog.outDebug("WORLD: CMSG_CALENDAR_COPY_EVENT"); + recv_data.hexlike(); +} + +void WorldSession::HandleCalendarEventInvite(WorldPacket &recv_data) +{ + sLog.outDebug("WORLD: CMSG_CALENDAR_EVENT_INVITE"); + recv_data.hexlike(); +} + +void WorldSession::HandleCalendarEventRsvp(WorldPacket &recv_data) +{ + sLog.outDebug("WORLD: CMSG_CALENDAR_EVENT_RSVP"); + recv_data.hexlike(); +} + +void WorldSession::HandleCalendarEventRemoveInvite(WorldPacket &recv_data) +{ + sLog.outDebug("WORLD: CMSG_CALENDAR_EVENT_REMOVE_INVITE"); + recv_data.hexlike(); +} + +void WorldSession::HandleCalendarEventStatus(WorldPacket &recv_data) +{ + sLog.outDebug("WORLD: CMSG_CALENDAR_EVENT_STATUS"); + recv_data.hexlike(); +} + +void WorldSession::HandleCalendarEventModeratorStatus(WorldPacket &recv_data) +{ + sLog.outDebug("WORLD: CMSG_CALENDAR_EVENT_MODERATOR_STATUS"); + recv_data.hexlike(); +} + +void WorldSession::HandleCalendarComplain(WorldPacket &recv_data) +{ + sLog.outDebug("WORLD: CMSG_CALENDAR_COMPLAIN"); + recv_data.hexlike(); +} + +void WorldSession::HandleCalendarGetNumPending(WorldPacket &recv_data) +{ + sLog.outDebug("WORLD: CMSG_CALENDAR_GET_NUM_PENDING"); + recv_data.hexlike(); + + WorldPacket data(SMSG_CALENDAR_SEND_NUM_PENDING, 4); + data << uint32(0); // 0 - no pending invites, 1 - some pending invites + SendPacket(&data); +} diff --git a/src/game/Channel.cpp b/src/game/Channel.cpp index 2fb8b5d09..d1dee730c 100644 --- a/src/game/Channel.cpp +++ b/src/game/Channel.cpp @@ -21,7 +21,7 @@ #include "World.h" #include "SocialMgr.h" -Channel::Channel(std::string name, uint32 channel_id) +Channel::Channel(const std::string& name, uint32 channel_id) : m_name(name), m_announce(true), m_moderate(false), m_channelId(channel_id), m_ownerGUID(0), m_password(""), m_flags(0) { // set special flags if built-in channel @@ -626,7 +626,7 @@ void Channel::Invite(uint64 p, const char *newname) SendToOne(&data, newp->GetGUID()); data.clear(); } - MakePlayerInvited(&data, newp->GetGUID()); + MakePlayerInvited(&data, newp->GetName()); SendToOne(&data, p); } @@ -773,7 +773,7 @@ void Channel::MakeOwnerChanged(WorldPacket *data, uint64 guid) } // done 0x09 -void Channel::MakePlayerNotFound(WorldPacket *data, std::string name) +void Channel::MakePlayerNotFound(WorldPacket *data, const std::string& name) { MakeNotifyPacket(data, CHAT_PLAYER_NOT_FOUND_NOTICE); *data << name; @@ -916,13 +916,8 @@ void Channel::MakeNotModerated(WorldPacket *data) } // done 0x1D -void Channel::MakePlayerInvited(WorldPacket *data, uint64 guid) +void Channel::MakePlayerInvited(WorldPacket *data, const std::string& name) { - std::string name; - - if(!objmgr.GetPlayerNameByGUID(guid, name) || name.empty()) - return; // player name not found - MakeNotifyPacket(data, CHAT_PLAYER_INVITED_NOTICE); *data << name; } diff --git a/src/game/Channel.h b/src/game/Channel.h index fc87efdd0..55ebf57ea 100644 --- a/src/game/Channel.h +++ b/src/game/Channel.h @@ -170,7 +170,7 @@ class Channel void MakeNotModerator(WorldPacket *data); //? 0x06 void MakePasswordChanged(WorldPacket *data, uint64 guid); //+ 0x07 void MakeOwnerChanged(WorldPacket *data, uint64 guid); //? 0x08 - void MakePlayerNotFound(WorldPacket *data, std::string name); //+ 0x09 + void MakePlayerNotFound(WorldPacket *data, const std::string& name); //+ 0x09 void MakeNotOwner(WorldPacket *data); //? 0x0A void MakeChannelOwner(WorldPacket *data); //? 0x0B void MakeModeChange(WorldPacket *data, uint64 guid, uint8 oldflags); //+ 0x0C @@ -190,7 +190,7 @@ class Channel void MakeWrongFaction(WorldPacket *data); //? 0x1A void MakeInvalidName(WorldPacket *data); //? 0x1B void MakeNotModerated(WorldPacket *data); //? 0x1C - void MakePlayerInvited(WorldPacket *data, uint64 guid); //+ 0x1D + void MakePlayerInvited(WorldPacket *data, const std::string& name); //+ 0x1D void MakePlayerInviteBanned(WorldPacket *data, uint64 guid); //? 0x1E void MakeThrottled(WorldPacket *data); //? 0x1F void MakeNotInArea(WorldPacket *data); //? 0x20 @@ -244,14 +244,14 @@ class Channel } public: - Channel(std::string name, uint32 channel_id); + Channel(const std::string& name, uint32 channel_id); std::string GetName() const { return m_name; } uint32 GetChannelId() const { return m_channelId; } bool IsConstant() const { return m_channelId != 0; } bool IsAnnounce() const { return m_announce; } bool IsLFG() const { return GetFlags() & CHANNEL_FLAG_LFG; } std::string GetPassword() const { return m_password; } - void SetPassword(std::string npassword) { m_password = npassword; } + void SetPassword(const std::string& npassword) { m_password = npassword; } void SetAnnounce(bool nannounce) { m_announce = nannounce; } uint32 GetNumPlayers() const { return players.size(); } uint8 GetFlags() const { return m_flags; } diff --git a/src/game/ChannelMgr.h b/src/game/ChannelMgr.h index b3e3ac2e4..124afec5c 100644 --- a/src/game/ChannelMgr.h +++ b/src/game/ChannelMgr.h @@ -36,7 +36,7 @@ class ChannelMgr delete itr->second; channels.clear(); } - Channel *GetJoinChannel(std::string name, uint32 channel_id) + Channel *GetJoinChannel(const std::string& name, uint32 channel_id) { if(channels.count(name) == 0) { @@ -45,7 +45,7 @@ class ChannelMgr } return channels[name]; } - Channel *GetChannel(std::string name, Player *p) + Channel *GetChannel(const std::string& name, Player *p) { ChannelMap::const_iterator i = channels.find(name); @@ -59,7 +59,7 @@ class ChannelMgr else return i->second; } - void LeftChannel(std::string name) + void LeftChannel(const std::string& name) { ChannelMap::const_iterator i = channels.find(name); @@ -76,7 +76,7 @@ class ChannelMgr } private: ChannelMap channels; - void MakeNotOnPacket(WorldPacket *data, std::string name) + void MakeNotOnPacket(WorldPacket *data, const std::string& name) { data->Initialize(SMSG_CHANNEL_NOTIFY, (1+10)); // we guess size (*data) << (uint8)0x05 << name; diff --git a/src/game/CharacterHandler.cpp b/src/game/CharacterHandler.cpp index 8880a7b2e..b338c48af 100644 --- a/src/game/CharacterHandler.cpp +++ b/src/game/CharacterHandler.cpp @@ -36,6 +36,7 @@ #include "PlayerDump.h" #include "SocialMgr.h" #include "Util.h" +#include "ArenaTeam.h" #include "Language.h" class LoginQueryHolder : public SqlQueryHolder @@ -59,7 +60,7 @@ bool LoginQueryHolder::Initialize() // NOTE: all fields in `characters` must be read to prevent lost character data at next save in case wrong DB structure. // !!! NOTE: including unused `zone`,`online` - res &= SetPQuery(PLAYER_LOGIN_QUERY_LOADFROM, "SELECT guid, account, data, name, race, class, position_x, position_y, position_z, map, orientation, taximask, cinematic, totaltime, leveltime, rest_bonus, logout_time, is_logout_resting, resettalents_cost, resettalents_time, trans_x, trans_y, trans_z, trans_o, transguid, extra_flags, stable_slots, at_login, zone, online, death_expire_time, taxi_path, dungeon_difficulty FROM characters WHERE guid = '%u'", GUID_LOPART(m_guid)); + res &= SetPQuery(PLAYER_LOGIN_QUERY_LOADFROM, "SELECT guid, account, data, name, race, class, position_x, position_y, position_z, map, orientation, taximask, cinematic, totaltime, leveltime, rest_bonus, logout_time, is_logout_resting, resettalents_cost, resettalents_time, trans_x, trans_y, trans_z, trans_o, transguid, extra_flags, stable_slots, at_login, zone, online, death_expire_time, taxi_path, dungeon_difficulty, arena_pending_points FROM characters WHERE guid = '%u'", GUID_LOPART(m_guid)); res &= SetPQuery(PLAYER_LOGIN_QUERY_LOADGROUP, "SELECT leaderGuid FROM group_member WHERE memberGuid ='%u'", GUID_LOPART(m_guid)); res &= SetPQuery(PLAYER_LOGIN_QUERY_LOADBOUNDINSTANCES, "SELECT id, permanent, map, difficulty, resettime FROM character_instance LEFT JOIN instance ON instance = id WHERE guid = '%u'", GUID_LOPART(m_guid)); res &= SetPQuery(PLAYER_LOGIN_QUERY_LOADAURAS, "SELECT caster_guid,spell,effect_index,stackcount,amount,maxduration,remaintime,remaincharges FROM character_aura WHERE guid = '%u'", GUID_LOPART(m_guid)); @@ -79,6 +80,9 @@ bool LoginQueryHolder::Initialize() res &= SetPQuery(PLAYER_LOGIN_QUERY_LOADDECLINEDNAMES, "SELECT genitive, dative, accusative, instrumental, prepositional FROM character_declinedname WHERE guid = '%u'",GUID_LOPART(m_guid)); // in other case still be dummy query res &= SetPQuery(PLAYER_LOGIN_QUERY_LOADGUILD, "SELECT guildid,rank FROM guild_member WHERE guid = '%u'", GUID_LOPART(m_guid)); + res &= SetPQuery(PLAYER_LOGIN_QUERY_LOADARENAINFO, "SELECT arenateamid, played_week, played_season, personal_rating FROM arena_team_member WHERE guid='%u'", GUID_LOPART(m_guid)); + res &= SetPQuery(PLAYER_LOGIN_QUERY_LOADACHIEVEMENTS, "SELECT achievement, date FROM character_achievement WHERE guid = '%u'", GUID_LOPART(m_guid)); + res &= SetPQuery(PLAYER_LOGIN_QUERY_LOADCRITERIAPROGRESS,"SELECT criteria, counter, date FROM character_achievement_progress WHERE guid = '%u'", GUID_LOPART(m_guid)); return res; } @@ -228,17 +232,16 @@ void WorldSession::HandleCharCreateOpcode( WorldPacket & recv_data ) if (raceEntry->addon > Expansion()) { data << (uint8)CHAR_CREATE_EXPANSION; - sLog.outError("Not Expansion 1 account:[%d] but tried to Create character with expansion 1 race (%u)",GetAccountId(),race_); + sLog.outError("Expansion %u account:[%d] tried to Create character with expansion %u race (%u)",Expansion(),GetAccountId(),raceEntry->addon,race_); SendPacket( &data ); return; } // prevent character creating Expansion class without Expansion account - // TODO: use possible addon field in ChrClassesEntry in next dbc version - if (Expansion() < 2 && class_ == CLASS_DEATH_KNIGHT) + if (classEntry->addon > Expansion()) { - data << (uint8)CHAR_CREATE_EXPANSION; - sLog.outError("Not Expansion 2 account:[%d] but tried to Create character with expansion 2 class (%u)",GetAccountId(),class_); + data << (uint8)CHAR_CREATE_EXPANSION_CLASS; + sLog.outError("Expansion %u account:[%d] tried to Create character with expansion %u class (%u)",Expansion(),GetAccountId(),classEntry->addon,class_); SendPacket( &data ); return; } @@ -305,29 +308,56 @@ void WorldSession::HandleCharCreateOpcode( WorldPacket & recv_data ) } } + // speedup check for heroic class disabled case + uint32 heroic_free_slots = sWorld.getConfig(CONFIG_HEROIC_CHARACTERS_PER_REALM); + if(heroic_free_slots==0 && GetSecurity()==SEC_PLAYER && class_ == CLASS_DEATH_KNIGHT) + { + data << (uint8)CHAR_CREATE_UNIQUE_CLASS_LIMIT; + SendPacket( &data ); + return; + } + bool AllowTwoSideAccounts = !sWorld.IsPvPRealm() || sWorld.getConfig(CONFIG_ALLOW_TWO_SIDE_ACCOUNTS) || GetSecurity() > SEC_PLAYER; uint32 skipCinematics = sWorld.getConfig(CONFIG_SKIP_CINEMATICS); bool have_same_race = false; - if(!AllowTwoSideAccounts || skipCinematics == 1) + if(!AllowTwoSideAccounts || skipCinematics == 1 || class_ == CLASS_DEATH_KNIGHT) { - QueryResult *result2 = CharacterDatabase.PQuery("SELECT DISTINCT race FROM characters WHERE account = '%u' %s", GetAccountId(),skipCinematics == 1 ? "" : "LIMIT 1"); + QueryResult *result2 = CharacterDatabase.PQuery("SELECT race,class FROM characters WHERE account = '%u' %s", + GetAccountId(), (skipCinematics == 1 || class_ == CLASS_DEATH_KNIGHT) ? "" : "LIMIT 1"); if(result2) { uint32 team_= Player::TeamForRace(race_); Field* field = result2->Fetch(); - uint8 race = field[0].GetUInt32(); + uint8 acc_race = field[0].GetUInt32(); + + if(GetSecurity()==SEC_PLAYER && class_ == CLASS_DEATH_KNIGHT) + { + uint8 acc_class = field[1].GetUInt32(); + if(acc_class == CLASS_DEATH_KNIGHT) + { + if(heroic_free_slots > 0) + --heroic_free_slots; + + if(heroic_free_slots==0) + { + data << (uint8)CHAR_CREATE_UNIQUE_CLASS_LIMIT; + SendPacket( &data ); + return; + } + } + } // need to check team only for first character // TODO: what to if account already has characters of both races? if (!AllowTwoSideAccounts) { - uint32 team=0; - if(race > 0) - team = Player::TeamForRace(race); + uint32 acc_team=0; + if(acc_race > 0) + acc_team = Player::TeamForRace(acc_race); - if(team != team_) + if(acc_team != team_) { data << (uint8)CHAR_CREATE_PVP_TEAMS_VIOLATION; SendPacket( &data ); @@ -336,15 +366,35 @@ void WorldSession::HandleCharCreateOpcode( WorldPacket & recv_data ) } } - if (skipCinematics == 1) + // search same race for cinematic or same class if need + // TODO: check if cinematic already shown? (already logged in?; cinematic field) + while ((skipCinematics == 1 && !have_same_race) || class_ == CLASS_DEATH_KNIGHT) { - // TODO: check if cinematic already shown? (already logged in?; cinematic field) - while (race_ != race && result2->NextRow()) + if(!result2->NextRow()) + break; + + field = result2->Fetch(); + acc_race = field[0].GetUInt32(); + + if(!have_same_race) + have_same_race = race_ == acc_race; + + if(GetSecurity()==SEC_PLAYER && class_ == CLASS_DEATH_KNIGHT) { - field = result2->Fetch(); - race = field[0].GetUInt32(); + uint8 acc_class = field[1].GetUInt32(); + if(acc_class == CLASS_DEATH_KNIGHT) + { + if(heroic_free_slots > 0) + --heroic_free_slots; + + if(heroic_free_slots==0) + { + data << (uint8)CHAR_CREATE_UNIQUE_CLASS_LIMIT; + SendPacket( &data ); + return; + } + } } - have_same_race = race_ == race; } delete result2; } @@ -411,7 +461,7 @@ void WorldSession::HandleCharDeleteOpcode( WorldPacket & recv_data ) } // is arena team captain - if(objmgr.GetArenaTeamByCapitan(guid)) + if(objmgr.GetArenaTeamByCaptain(guid)) { WorldPacket data(SMSG_CHAR_DELETE, 1); data << (uint8)CHAR_DELETE_FAILED_ARENA_CAPTAIN; @@ -453,6 +503,12 @@ void WorldSession::HandlePlayerLoginOpcode( WorldPacket & recv_data ) { CHECK_PACKET_SIZE(recv_data,8); + if(PlayerLoading() || GetPlayer() != NULL) + { + sLog.outError("Player tryes to login again, AccountId = %d",GetAccountId()); + return; + } + m_playerLoading = true; uint64 playerGuid = 0; @@ -500,9 +556,11 @@ void WorldSession::HandlePlayerLogin(LoginQueryHolder * holder) data << pCurrChar->GetOrientation(); SendPacket(&data); - data.Initialize( SMSG_ACCOUNT_DATA_TIMES, 128 ); - for(int i = 0; i < 32; i++) - data << uint32(0); + data.Initialize( SMSG_ACCOUNT_DATA_TIMES, 4+1+8*4 ); // changed in WotLK + data << uint32(time(NULL)); // unix time of something + data << uint8(1); + for(int i = 0; i < NUM_ACCOUNT_DATA_TYPES; i++) + data << uint32(GetAccountData(i)->Time); // also unix time SendPacket(&data); data.Initialize(SMSG_FEATURE_SYSTEM_STATUS, 2); // added in 2.2.0 @@ -599,12 +657,20 @@ void WorldSession::HandlePlayerLogin(LoginQueryHolder * holder) { pCurrChar->setCinematic(1); - ChrRacesEntry const* rEntry = sChrRacesStore.LookupEntry(pCurrChar->getRace()); - if(rEntry) + if(ChrClassesEntry const* cEntry = sChrClassesStore.LookupEntry(pCurrChar->getClass())) { - data.Initialize( SMSG_TRIGGER_CINEMATIC,4 ); - data << uint32(rEntry->startmovie); - SendPacket( &data ); + if(cEntry->CinematicSequence) + { + data.Initialize(SMSG_TRIGGER_CINEMATIC, 4); + data << uint32(cEntry->CinematicSequence); + SendPacket( &data ); + } + else if(ChrRacesEntry const* rEntry = sChrRacesStore.LookupEntry(pCurrChar->getRace())) + { + data.Initialize(SMSG_TRIGGER_CINEMATIC, 4); + data << uint32(rEntry->CinematicSequence); + SendPacket( &data ); + } } } @@ -648,22 +714,6 @@ void WorldSession::HandlePlayerLogin(LoginQueryHolder * holder) pCurrChar->CastSpell(pCurrChar, 20584, true, 0);// auras SPELL_AURA_INCREASE_SPEED(+speed in wisp form), SPELL_AURA_INCREASE_SWIM_SPEED(+swim speed in wisp form), SPELL_AURA_TRANSFORM (to wisp form) pCurrChar->CastSpell(pCurrChar, 8326, true, 0); // auras SPELL_AURA_GHOST, SPELL_AURA_INCREASE_SPEED(why?), SPELL_AURA_INCREASE_SWIM_SPEED(why?) - //pCurrChar->SetUInt32Value(UNIT_FIELD_AURA+41, 8326); - //pCurrChar->SetUInt32Value(UNIT_FIELD_AURA+42, 20584); - //pCurrChar->SetUInt32Value(UNIT_FIELD_AURAFLAGS+6, 238); - //pCurrChar->SetUInt32Value(UNIT_FIELD_AURALEVELS+11, 514); - //pCurrChar->SetUInt32Value(UNIT_FIELD_AURAAPPLICATIONS+11, 65535); - //pCurrChar->SetUInt32Value(UNIT_FIELD_DISPLAYID, 1825); - //if (pCurrChar->getRace() == RACE_NIGHTELF) - //{ - // pCurrChar->SetSpeed(MOVE_RUN, 1.5f*1.2f, true); - // pCurrChar->SetSpeed(MOVE_SWIM, 1.5f*1.2f, true); - //} - //else - //{ - // pCurrChar->SetSpeed(MOVE_RUN, 1.5f, true); - // pCurrChar->SetSpeed(MOVE_SWIM, 1.5f, true); - //} pCurrChar->SetMovement(MOVE_WATER_WALK); } @@ -893,53 +943,27 @@ void WorldSession::HandleToggleCloakOpcode( WorldPacket & /*recv_data*/ ) void WorldSession::HandleChangePlayerNameOpcode(WorldPacket& recv_data) { - CHECK_PACKET_SIZE(recv_data,8+1); + CHECK_PACKET_SIZE(recv_data, 8+1); uint64 guid; std::string newname; - std::string oldname; - - CHECK_PACKET_SIZE(recv_data, 8+1); recv_data >> guid; recv_data >> newname; - QueryResult *result = CharacterDatabase.PQuery("SELECT at_login, name FROM characters WHERE guid ='%u'", GUID_LOPART(guid)); - if (!result) - { - WorldPacket data(SMSG_CHAR_RENAME, 1); - data << (uint8)CHAR_CREATE_ERROR; - SendPacket( &data ); - return; - } - - uint32 at_loginFlags; - Field *fields = result->Fetch(); - at_loginFlags = fields[0].GetUInt32(); - oldname = fields[1].GetCppString(); - delete result; - - if (!(at_loginFlags & AT_LOGIN_RENAME)) - { - WorldPacket data(SMSG_CHAR_RENAME, 1); - data << (uint8)CHAR_CREATE_ERROR; - SendPacket( &data ); - return; - } - // prevent character rename to invalid name if(!normalizePlayerName(newname)) { WorldPacket data(SMSG_CHAR_RENAME, 1); - data << (uint8)CHAR_NAME_NO_NAME; + data << uint8(CHAR_NAME_NO_NAME); SendPacket( &data ); return; } - if(!ObjectMgr::IsValidName(newname,true)) + if(!ObjectMgr::IsValidName(newname, true)) { WorldPacket data(SMSG_CHAR_RENAME, 1); - data << (uint8)CHAR_NAME_INVALID_CHARACTER; + data << uint8(CHAR_NAME_INVALID_CHARACTER); SendPacket( &data ); return; } @@ -948,41 +972,56 @@ void WorldSession::HandleChangePlayerNameOpcode(WorldPacket& recv_data) if(GetSecurity() == SEC_PLAYER && objmgr.IsReservedName(newname)) { WorldPacket data(SMSG_CHAR_RENAME, 1); - data << (uint8)CHAR_NAME_RESERVED; + data << uint8(CHAR_NAME_RESERVED); SendPacket( &data ); return; } - if(objmgr.GetPlayerGUIDByName(newname)) // character with this name already exist + std::string escaped_newname = newname; + CharacterDatabase.escape_string(escaped_newname); + + // make sure that the character belongs to the current account, that rename at login is enabled + // and that there is no character with the desired new name + CharacterDatabase.AsyncPQuery(&WorldSession::HandleChangePlayerNameOpcodeCallBack, + GetAccountId(), newname, + "SELECT guid, name FROM characters WHERE guid = %d AND account = %d AND (at_login & %d) = %d AND NOT EXISTS (SELECT NULL FROM characters WHERE name = '%s')", + GUID_LOPART(guid), GetAccountId(), AT_LOGIN_RENAME, AT_LOGIN_RENAME, escaped_newname.c_str() + ); +} + +void WorldSession::HandleChangePlayerNameOpcodeCallBack(QueryResult *result, uint32 accountId, std::string newname) +{ + WorldSession * session = sWorld.FindSession(accountId); + if(!session) + { + if(result) delete result; + return; + } + + if (!result) { WorldPacket data(SMSG_CHAR_RENAME, 1); - data << (uint8)CHAR_CREATE_ERROR; - SendPacket( &data ); + data << uint8(CHAR_CREATE_ERROR); + session->SendPacket( &data ); return; } - if(newname == oldname) // checked by client - { - WorldPacket data(SMSG_CHAR_RENAME, 1); - data << (uint8)CHAR_NAME_FAILURE; - SendPacket( &data ); - return; - } + uint32 guidLow = result->Fetch()[0].GetUInt32(); + uint64 guid = MAKE_NEW_GUID(guidLow, 0, HIGHGUID_PLAYER); + std::string oldname = result->Fetch()[1].GetCppString(); - // we have to check character at_login_flag & AT_LOGIN_RENAME also (fake packets hehe) + delete result; - CharacterDatabase.escape_string(newname); - CharacterDatabase.PExecute("UPDATE characters set name = '%s', at_login = at_login & ~ %u WHERE guid ='%u'", newname.c_str(), uint32(AT_LOGIN_RENAME),GUID_LOPART(guid)); - CharacterDatabase.PExecute("DELETE FROM character_declinedname WHERE guid ='%u'", GUID_LOPART(guid)); + CharacterDatabase.PExecute("UPDATE characters set name = '%s', at_login = at_login & ~ %u WHERE guid ='%u'", newname.c_str(), uint32(AT_LOGIN_RENAME), guidLow); + CharacterDatabase.PExecute("DELETE FROM character_declinedname WHERE guid ='%u'", guidLow); - std::string IP_str = GetRemoteAddress(); - sLog.outChar("Account: %d (IP: %s) Character:[%s] (guid:%u) Changed name to: %s",GetAccountId(),IP_str.c_str(),oldname.c_str(),GUID_LOPART(guid),newname.c_str()); + sLog.outChar("Account: %d (IP: %s) Character:[%s] (guid:%u) Changed name to: %s", session->GetAccountId(), session->GetRemoteAddress().c_str(), oldname.c_str(), guidLow, newname.c_str()); - WorldPacket data(SMSG_CHAR_RENAME,1+8+(newname.size()+1)); - data << (uint8)RESPONSE_SUCCESS; - data << guid; + WorldPacket data(SMSG_CHAR_RENAME, 1+8+(newname.size()+1)); + data << uint8(RESPONSE_SUCCESS); + data << uint64(guid); data << newname; - SendPacket(&data); + session->SendPacket(&data); } void WorldSession::HandleDeclinedPlayerNameOpcode(WorldPacket& recv_data) @@ -1074,3 +1113,166 @@ void WorldSession::HandleDeclinedPlayerNameOpcode(WorldPacket& recv_data) data << uint64(guid); SendPacket(&data); } + +void WorldSession::HandleAlterAppearance( WorldPacket & recv_data ) +{ + sLog.outDebug("CMSG_ALTER_APPEARANCE"); + + CHECK_PACKET_SIZE(recv_data, 4+4+4); + + uint32 Hair, Color, FacialHair; + recv_data >> Hair >> Color >> FacialHair; + + BarberShopStyleEntry const* bs_hair = sBarberShopStyleStore.LookupEntry(Hair); + + if(!bs_hair || bs_hair->type != 0 || bs_hair->race != _player->getRace() || bs_hair->gender != _player->getGender()) + return; + + BarberShopStyleEntry const* bs_facialHair = sBarberShopStyleStore.LookupEntry(FacialHair); + + if(!bs_facialHair || bs_facialHair->type != 2 || bs_facialHair->race != _player->getRace() || bs_facialHair->gender != _player->getGender()) + return; + + uint32 Cost = _player->GetBarberShopCost(bs_hair->hair_id, Color, bs_facialHair->hair_id); + + // 0 - ok + // 1,3 - not enough money + // 2 - you have to seat on barber chair + if(_player->GetMoney() < Cost) + { + WorldPacket data(SMSG_BARBER_SHOP_RESULT, 4); + data << uint32(1); // no money + SendPacket(&data); + return; + } + else + { + WorldPacket data(SMSG_BARBER_SHOP_RESULT, 4); + data << uint32(0); // ok + SendPacket(&data); + } + + _player->SetMoney(_player->GetMoney() - Cost); // it isn't free + + _player->SetByteValue(PLAYER_BYTES, 2, uint8(bs_hair->hair_id)); + _player->SetByteValue(PLAYER_BYTES, 3, uint8(Color)); + _player->SetByteValue(PLAYER_BYTES_2, 0, uint8(bs_facialHair->hair_id)); + + _player->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_VISIT_BARBER_SHOP, 1); + + _player->SetStandState(0); // stand up +} + +void WorldSession::HandleRemoveGlyph( WorldPacket & recv_data ) +{ + CHECK_PACKET_SIZE(recv_data, 4); + + uint32 slot; + recv_data >> slot; + + if(slot > 5) + { + sLog.outDebug("Client sent wrong glyph slot number in opcode CMSG_REMOVE_GLYPH %u", slot); + return; + } + + if(uint32 glyph = _player->GetGlyph(slot)) + { + if(GlyphPropertiesEntry const *gp = sGlyphPropertiesStore.LookupEntry(glyph)) + { + _player->RemoveAurasDueToSpell(gp->SpellId); + _player->SetGlyph(slot, 0); + } + } +} + +void WorldSession::HandleCharCustomize(WorldPacket& recv_data) +{ + CHECK_PACKET_SIZE(recv_data, 8+1); + + uint64 guid; + std::string newname; + + recv_data >> guid; + recv_data >> newname; + + CHECK_PACKET_SIZE(recv_data, recv_data.rpos()+1+1+1+1+1+1); + + uint8 gender, skin, face, hairStyle, hairColor, facialHair; + recv_data >> gender >> skin >> face >> hairStyle >> hairColor >> facialHair; + + QueryResult *result = CharacterDatabase.PQuery("SELECT at_login FROM characters WHERE guid ='%u'", GUID_LOPART(guid)); + if (!result) + { + WorldPacket data(SMSG_CHAR_CUSTOMIZE, 1); + data << uint8(CHAR_CREATE_ERROR); + SendPacket( &data ); + return; + } + + Field *fields = result->Fetch(); + uint32 at_loginFlags = fields[0].GetUInt32(); + delete result; + + if (!(at_loginFlags & AT_LOGIN_CUSTOMIZE)) + { + WorldPacket data(SMSG_CHAR_CUSTOMIZE, 1); + data << uint8(CHAR_CREATE_ERROR); + SendPacket( &data ); + return; + } + + // prevent character rename to invalid name + if(!normalizePlayerName(newname)) + { + WorldPacket data(SMSG_CHAR_CUSTOMIZE, 1); + data << uint8(CHAR_NAME_NO_NAME); + SendPacket( &data ); + return; + } + + if(!ObjectMgr::IsValidName(newname,true)) + { + WorldPacket data(SMSG_CHAR_CUSTOMIZE, 1); + data << uint8(CHAR_NAME_INVALID_CHARACTER); + SendPacket( &data ); + return; + } + + // check name limitations + if(GetSecurity() == SEC_PLAYER && objmgr.IsReservedName(newname)) + { + WorldPacket data(SMSG_CHAR_CUSTOMIZE, 1); + data << uint8(CHAR_NAME_RESERVED); + SendPacket( &data ); + return; + } + + if(objmgr.GetPlayerGUIDByName(newname)) // character with this name already exist + { + WorldPacket data(SMSG_CHAR_CUSTOMIZE, 1); + data << uint8(CHAR_CREATE_NAME_IN_USE); + SendPacket( &data ); + return; + } + + CharacterDatabase.escape_string(newname); + Player::Customize(guid, gender, skin, face, hairStyle, hairColor, facialHair); + CharacterDatabase.PExecute("UPDATE characters set name = '%s', at_login = at_login & ~ %u WHERE guid ='%u'", newname.c_str(), uint32(AT_LOGIN_CUSTOMIZE), GUID_LOPART(guid)); + CharacterDatabase.PExecute("DELETE FROM character_declinedname WHERE guid ='%u'", GUID_LOPART(guid)); + + std::string IP_str = GetRemoteAddress(); + sLog.outChar("Account: %d (IP: %s), Character guid: %u Customized to: %s", GetAccountId(), IP_str.c_str(), GUID_LOPART(guid), newname.c_str()); + + WorldPacket data(SMSG_CHAR_CUSTOMIZE, 1+8+(newname.size()+1)+6); + data << uint8(RESPONSE_SUCCESS); + data << uint64(guid); + data << newname; + data << uint8(gender); + data << uint8(skin); + data << uint8(face); + data << uint8(hairStyle); + data << uint8(hairColor); + data << uint8(facialHair); + SendPacket(&data); +} diff --git a/src/game/Chat.cpp b/src/game/Chat.cpp index aa2ad5a0b..5013e3605 100644 --- a/src/game/Chat.cpp +++ b/src/game/Chat.cpp @@ -185,6 +185,7 @@ ChatCommand * ChatHandler::getCommandTable() { "sellerr", SEC_ADMINISTRATOR, false, &ChatHandler::HandleSellErrorCommand, "", NULL }, { "buyerr", SEC_ADMINISTRATOR, false, &ChatHandler::HandleBuyErrorCommand, "", NULL }, { "sendopcode", SEC_ADMINISTRATOR, false, &ChatHandler::HandleSendOpcodeCommand, "", NULL }, + { "spawnvehicle", SEC_ADMINISTRATOR, false, &ChatHandler::HandleSpawnVehicle, "", NULL }, { "uws", SEC_ADMINISTRATOR, false, &ChatHandler::HandleUpdateWorldStateCommand, "", NULL }, { "ps", SEC_ADMINISTRATOR, false, &ChatHandler::HandlePlaySound2Command, "", NULL }, { "scn", SEC_ADMINISTRATOR, false, &ChatHandler::HandleSendChannelNotifyCommand, "", NULL }, @@ -197,6 +198,7 @@ ChatCommand * ChatHandler::getCommandTable() { "Mod32Value", SEC_ADMINISTRATOR, false, &ChatHandler::HandleMod32Value, "", NULL }, { "anim", SEC_GAMEMASTER, false, &ChatHandler::HandleAnimCommand, "", NULL }, { "lootrecipient", SEC_GAMEMASTER, false, &ChatHandler::HandleGetLootRecipient, "", NULL }, + { "arena", SEC_ADMINISTRATOR, false, &ChatHandler::HandleDebugArenaCommand, "", NULL }, { NULL, 0, false, NULL, "", NULL } }; @@ -257,6 +259,7 @@ ChatCommand * ChatHandler::getCommandTable() { "item_enchantment_template", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadItemEnchantementsCommand, "", NULL }, { "item_loot_template", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadLootTemplatesItemCommand, "", NULL }, { "mangos_string", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadMangosStringCommand, "", NULL }, + { "milling_loot_template", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadLootTemplatesMillingCommand, "", NULL }, { "npc_gossip", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadNpcGossipCommand, "", NULL }, { "npc_option", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadNpcOptionCommand, "", NULL }, { "npc_trainer", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadNpcTrainerCommand, "", NULL }, @@ -553,6 +556,7 @@ ChatCommand * ChatHandler::getCommandTable() { "sendmail", SEC_MODERATOR, true, &ChatHandler::HandleSendMailCommand, "", NULL }, { "sendmoney", SEC_ADMINISTRATOR, true, &ChatHandler::HandleSendMoneyCommand, "", NULL }, { "rename", SEC_GAMEMASTER, true, &ChatHandler::HandleRenameCommand, "", NULL }, + { "customize", SEC_GAMEMASTER, true, &ChatHandler::HandleCustomizeCommand, "", NULL }, { "loadscripts", SEC_ADMINISTRATOR, true, &ChatHandler::HandleLoadScriptsCommand, "", NULL }, { "mute", SEC_GAMEMASTER, true, &ChatHandler::HandleMuteCommand, "", NULL }, { "unmute", SEC_GAMEMASTER, true, &ChatHandler::HandleUnmuteCommand, "", NULL }, @@ -560,6 +564,7 @@ ChatCommand * ChatHandler::getCommandTable() { "cometome", SEC_ADMINISTRATOR, false, &ChatHandler::HandleComeToMeCommand, "", NULL }, { "damage", SEC_ADMINISTRATOR, false, &ChatHandler::HandleDamageCommand, "", NULL }, { "combatstop", SEC_GAMEMASTER, false, &ChatHandler::HandleCombatStopCommand, "", NULL }, + { "flusharenapoints", SEC_ADMINISTRATOR, false, &ChatHandler::HandleFlushArenaPointsCommand, "", NULL }, { "chardelete", SEC_CONSOLE, true, &ChatHandler::HandleCharacterDeleteCommand, "", NULL }, { "sendmessage", SEC_ADMINISTRATOR, true, &ChatHandler::HandleSendMessageCommand, "", NULL }, { "repairitems", SEC_GAMEMASTER, false, &ChatHandler::HandleRepairitemsCommand, "", NULL }, @@ -706,7 +711,7 @@ void ChatHandler::PSendSysMessage(const char *format, ...) SendSysMessage(str); } -bool ChatHandler::ExecuteCommandInTable(ChatCommand *table, const char* text, std::string fullcmd) +bool ChatHandler::ExecuteCommandInTable(ChatCommand *table, const char* text, const std::string& fullcmd) { char const* oldtext = text; std::string cmd = ""; diff --git a/src/game/Chat.h b/src/game/Chat.h index 73e0d6d50..804e3c9bd 100644 --- a/src/game/Chat.h +++ b/src/game/Chat.h @@ -80,7 +80,7 @@ class ChatHandler void SendGlobalSysMessage(const char *str); - bool ExecuteCommandInTable(ChatCommand *table, const char* text, std::string fullcommand); + bool ExecuteCommandInTable(ChatCommand *table, const char* text, const std::string& fullcommand); bool ShowHelpForCommand(ChatCommand *table, const char* cmd); bool ShowHelpForSubCommands(ChatCommand *table, char const* cmd, char const* subcmd); @@ -225,6 +225,7 @@ class ChatHandler bool HandleReloadLootTemplatesFishingCommand(const char* args); bool HandleReloadLootTemplatesGameobjectCommand(const char* args); bool HandleReloadLootTemplatesItemCommand(const char* args); + bool HandleReloadLootTemplatesMillingCommand(const char* args); bool HandleReloadLootTemplatesPickpocketingCommand(const char* args); bool HandleReloadLootTemplatesProspectingCommand(const char* args); bool HandleReloadLootTemplatesReferenceCommand(const char* args); @@ -405,6 +406,7 @@ class ChatHandler bool HandleSendChannelNotifyCommand(const char* args); bool HandleSendChatMsgCommand(const char* args); bool HandleRenameCommand(const char * args); + bool HandleCustomizeCommand(const char * args); bool HandleLoadPDumpCommand(const char *args); bool HandleWritePDumpCommand(const char *args); bool HandleCastCommand(const char *args); @@ -415,6 +417,7 @@ class ChatHandler bool HandleComeToMeCommand(const char *args); bool HandleCombatStopCommand(const char *args); bool HandleSendMessageCommand(const char * args); + bool HandleFlushArenaPointsCommand(const char *args); bool HandleRepairitemsCommand(const char* args); bool HandleWaterwalkCommand(const char* args); @@ -429,6 +432,8 @@ class ChatHandler bool HandleSaveAllCommand(const char* args); bool HandleGetItemState(const char * args); bool HandleGetLootRecipient(const char * args); + bool HandleDebugArenaCommand(const char * args); + bool HandleSpawnVehicle(const char * args); Player* getSelectedPlayer(); Creature* getSelectedCreature(); diff --git a/src/game/Corpse.cpp b/src/game/Corpse.cpp index cacd7deac..83358c3b3 100644 --- a/src/game/Corpse.cpp +++ b/src/game/Corpse.cpp @@ -34,7 +34,7 @@ Corpse::Corpse(CorpseType type) : WorldObject() m_objectType |= TYPEMASK_CORPSE; m_objectTypeId = TYPEID_CORPSE; // 2.3.2 - 0x58 - m_updateFlag = (UPDATEFLAG_LOWGUID | UPDATEFLAG_HIGHGUID | UPDATEFLAG_HASPOSITION); + m_updateFlag = (UPDATEFLAG_LOWGUID | UPDATEFLAG_HIGHGUID | UPDATEFLAG_HAS_POSITION); m_valuesCount = CORPSE_END; diff --git a/src/game/Creature.cpp b/src/game/Creature.cpp index 8ab1b3258..5c41bd477 100644 --- a/src/game/Creature.cpp +++ b/src/game/Creature.cpp @@ -117,11 +117,12 @@ Unit(), i_AI(NULL), lootForPickPocketed(false), lootForBody(false), m_groupLootTimer(0), lootingGroupLeaderGUID(0), m_lootMoney(0), m_lootRecipient(0), m_deathTimer(0), m_respawnTime(0), m_respawnDelay(25), m_corpseDelay(60), m_respawnradius(0.0f), -m_gossipOptionLoaded(false), m_emoteState(0), m_isPet(false), m_isTotem(false), -m_regenTimer(2000), m_defaultMovementType(IDLE_MOTION_TYPE), m_equipmentId(0), +m_gossipOptionLoaded(false), m_emoteState(0), m_isPet(false), m_isTotem(false), m_isVehicle(false), +m_defaultMovementType(IDLE_MOTION_TYPE), m_equipmentId(0), m_AlreadyCallAssistance(false), m_regenHealth(true), m_AI_locked(false), m_isDeadByDefault(false), m_meleeDamageSchoolMask(SPELL_SCHOOL_MASK_NORMAL),m_creatureInfo(NULL), m_DBTableGuid(0) { + m_regenTimer = 200; m_valuesCount = UNIT_END; for(int i =0; i<4; ++i) @@ -265,7 +266,6 @@ bool Creature::UpdateEntry(uint32 Entry, uint32 team, const CreatureData *data ) // creatures always have melee weapon ready if any SetByteValue(UNIT_FIELD_BYTES_2, 0, SHEATH_STATE_MELEE ); - SetByteValue(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_AURAS ); SelectLevel(GetCreatureInfo()); if (team == HORDE) @@ -671,8 +671,11 @@ bool Creature::isCanIneractWithBattleMaster(Player* pPlayer, bool msg) const case BATTLEGROUND_NA: case BATTLEGROUND_BE: case BATTLEGROUND_AA: - case BATTLEGROUND_RL: pPlayer->PlayerTalkClass->SendGossipMenu(10024,GetGUID()); break; - break; + case BATTLEGROUND_RL: + case BATTLEGROUND_SA: + case BATTLEGROUND_DS: + case BATTLEGROUND_RV: pPlayer->PlayerTalkClass->SendGossipMenu(10024,GetGUID()); break; + default: break; } return false; } @@ -1351,11 +1354,7 @@ void Creature::LoadEquipment(uint32 equip_entry, bool force) if (force) { for (uint8 i = 0; i < 3; i++) - { - SetUInt32Value( UNIT_VIRTUAL_ITEM_SLOT_DISPLAY + i, 0); - SetUInt32Value( UNIT_VIRTUAL_ITEM_INFO + (i * 2), 0); - SetUInt32Value( UNIT_VIRTUAL_ITEM_INFO + (i * 2) + 1, 0); - } + SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID + i, 0); m_equipmentId = 0; } return; @@ -1367,11 +1366,7 @@ void Creature::LoadEquipment(uint32 equip_entry, bool force) m_equipmentId = equip_entry; for (uint8 i = 0; i < 3; i++) - { - SetUInt32Value( UNIT_VIRTUAL_ITEM_SLOT_DISPLAY + i, einfo->equipmodel[i]); - SetUInt32Value( UNIT_VIRTUAL_ITEM_INFO + (i * 2), einfo->equipinfo[i]); - SetUInt32Value( UNIT_VIRTUAL_ITEM_INFO + (i * 2) + 1, einfo->equipslot[i]); - } + SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID + i, einfo->equipentry[i]); } bool Creature::hasQuest(uint32 quest_id) const diff --git a/src/game/Creature.h b/src/game/Creature.h index 01111568a..86daa0500 100644 --- a/src/game/Creature.h +++ b/src/game/Creature.h @@ -237,9 +237,7 @@ struct NpcOptionLocale struct EquipmentInfo { uint32 entry; - uint32 equipmodel[3]; - uint32 equipinfo[3]; - uint32 equipslot[3]; + uint32 equipentry[3]; }; // from `creature` table @@ -414,6 +412,7 @@ class MANGOS_DLL_SPEC Creature : public Unit uint32 GetEquipmentId() const { return m_equipmentId; } bool isPet() const { return m_isPet; } + bool isVehicle() const { return m_isVehicle; } void SetCorpseDelay(uint32 delay) { m_corpseDelay = delay; } bool isTotem() const { return m_isTotem; } bool isRacialLeader() const { return GetCreatureInfo()->RacialLeader; } @@ -626,10 +625,10 @@ class MANGOS_DLL_SPEC Creature : public Unit uint8 m_emoteState; bool m_isPet; // set only in Pet::Pet + bool m_isVehicle; // set only in Vehicle::Vehicle bool m_isTotem; // set only in Totem::Totem void RegenerateMana(); void RegenerateHealth(); - uint32 m_regenTimer; MovementGeneratorType m_defaultMovementType; Cell m_currentCell; // store current cell where creature listed uint32 m_DBTableGuid; ///< For new or temporary creatures is 0 for saved it is lowguid diff --git a/src/game/DynamicObject.cpp b/src/game/DynamicObject.cpp index a73ffecc8..b288dcb85 100644 --- a/src/game/DynamicObject.cpp +++ b/src/game/DynamicObject.cpp @@ -36,7 +36,7 @@ DynamicObject::DynamicObject() : WorldObject() m_objectType |= TYPEMASK_DYNAMICOBJECT; m_objectTypeId = TYPEID_DYNAMICOBJECT; // 2.3.2 - 0x58 - m_updateFlag = (UPDATEFLAG_LOWGUID | UPDATEFLAG_HIGHGUID | UPDATEFLAG_HASPOSITION); + m_updateFlag = (UPDATEFLAG_LOWGUID | UPDATEFLAG_HIGHGUID | UPDATEFLAG_HAS_POSITION); m_valuesCount = DYNAMICOBJECT_END; } diff --git a/src/game/GMTicketMgr.h b/src/game/GMTicketMgr.h index 01e00874d..5f7bf69ea 100644 --- a/src/game/GMTicketMgr.h +++ b/src/game/GMTicketMgr.h @@ -31,7 +31,7 @@ class GMTicket { } - GMTicket(uint32 guid, std::string text, time_t update) : m_guid(guid), m_text(text), m_lastUpdate(update) + GMTicket(uint32 guid, const std::string& text, time_t update) : m_guid(guid), m_text(text), m_lastUpdate(update) { } diff --git a/src/game/GameEvent.cpp b/src/game/GameEvent.cpp index 5981fd00c..e94d7c1d7 100644 --- a/src/game/GameEvent.cpp +++ b/src/game/GameEvent.cpp @@ -363,7 +363,7 @@ uint32 GameEvent::Update() // return the next e { uint32 nextEventDelay = max_ge_check_delay; // 1 day uint32 calcDelay; - for (uint16 itr = 1; itr < mGameEvent.size(); itr++) + for (uint16 itr = 1; itr < mGameEvent.size(); ++itr) { //sLog.outErrorDb("Checking event %u",itr); if (CheckOneGameEvent(itr)) diff --git a/src/game/GameObject.cpp b/src/game/GameObject.cpp index ab412dcf2..433493492 100644 --- a/src/game/GameObject.cpp +++ b/src/game/GameObject.cpp @@ -42,7 +42,7 @@ GameObject::GameObject() : WorldObject() m_objectType |= TYPEMASK_GAMEOBJECT; m_objectTypeId = TYPEID_GAMEOBJECT; // 2.3.2 - 0x58 - m_updateFlag = (UPDATEFLAG_LOWGUID | UPDATEFLAG_HIGHGUID | UPDATEFLAG_HASPOSITION); + m_updateFlag = (UPDATEFLAG_LOWGUID | UPDATEFLAG_HIGHGUID | UPDATEFLAG_HAS_POSITION); m_valuesCount = GAMEOBJECT_END; m_respawnTime = 0; @@ -123,10 +123,26 @@ bool GameObject::Create(uint32 guidlow, uint32 name_id, Map *map, float x, float SetFloatValue(GAMEOBJECT_POS_Z, z); SetFloatValue(GAMEOBJECT_FACING, ang); //this is not facing angle - SetFloatValue (GAMEOBJECT_ROTATION, rotation0); - SetFloatValue (GAMEOBJECT_ROTATION+1, rotation1); - SetFloatValue (GAMEOBJECT_ROTATION+2, rotation2); - SetFloatValue (GAMEOBJECT_ROTATION+3, rotation3); + int64 rotation = 0; + + float f_rot1 = sin(ang / 2.0f); + int64 i_rot1 = f_rot1 / atan(pow(2.0f, -20.0f)); + rotation |= (i_rot1 << 43 >> 43) & 0x00000000001FFFFF; + + //float f_rot2 = sin(0.0f / 2.0f); + //int64 i_rot2 = f_rot2 / atan(pow(2.0f, -20.0f)); + //rotation |= (((i_rot2 << 22) >> 32) >> 11) & 0x000003FFFFE00000; + + //float f_rot3 = sin(0.0f / 2.0f); + //int64 i_rot3 = f_rot3 / atan(pow(2.0f, -21.0f)); + //rotation |= (i_rot3 >> 42) & 0x7FFFFC0000000000; + + SetUInt64Value(GAMEOBJECT_ROTATION, rotation); + + SetFloatValue(GAMEOBJECT_PARENTROTATION+0, rotation0); + SetFloatValue(GAMEOBJECT_PARENTROTATION+1, rotation1); + SetFloatValue(GAMEOBJECT_PARENTROTATION+2, rotation2); + SetFloatValue(GAMEOBJECT_PARENTROTATION+3, rotation3); SetFloatValue(OBJECT_FIELD_SCALE_X, goinfo->size); @@ -510,10 +526,10 @@ void GameObject::SaveToDB(uint32 mapid, uint8 spawnMask) data.posY = GetFloatValue(GAMEOBJECT_POS_Y); data.posZ = GetFloatValue(GAMEOBJECT_POS_Z); data.orientation = GetFloatValue(GAMEOBJECT_FACING); - data.rotation0 = GetFloatValue(GAMEOBJECT_ROTATION+0); - data.rotation1 = GetFloatValue(GAMEOBJECT_ROTATION+1); - data.rotation2 = GetFloatValue(GAMEOBJECT_ROTATION+2); - data.rotation3 = GetFloatValue(GAMEOBJECT_ROTATION+3); + data.rotation0 = GetFloatValue(GAMEOBJECT_PARENTROTATION+0); + data.rotation1 = GetFloatValue(GAMEOBJECT_PARENTROTATION+1); + data.rotation2 = GetFloatValue(GAMEOBJECT_PARENTROTATION+2); + data.rotation3 = GetFloatValue(GAMEOBJECT_PARENTROTATION+3); data.spawntimesecs = m_spawnedByDefault ? m_respawnDelayTime : -(int32)m_respawnDelayTime; data.animprogress = GetGoAnimProgress(); data.go_state = GetGoState(); @@ -530,10 +546,10 @@ void GameObject::SaveToDB(uint32 mapid, uint8 spawnMask) << GetFloatValue(GAMEOBJECT_POS_Y) << ", " << GetFloatValue(GAMEOBJECT_POS_Z) << ", " << GetFloatValue(GAMEOBJECT_FACING) << ", " - << GetFloatValue(GAMEOBJECT_ROTATION) << ", " - << GetFloatValue(GAMEOBJECT_ROTATION+1) << ", " - << GetFloatValue(GAMEOBJECT_ROTATION+2) << ", " - << GetFloatValue(GAMEOBJECT_ROTATION+3) << ", " + << GetFloatValue(GAMEOBJECT_PARENTROTATION) << ", " + << GetFloatValue(GAMEOBJECT_PARENTROTATION+1) << ", " + << GetFloatValue(GAMEOBJECT_PARENTROTATION+2) << ", " + << GetFloatValue(GAMEOBJECT_PARENTROTATION+3) << ", " << m_respawnDelayTime << ", " << (uint32)GetGoAnimProgress() << ", " << (uint32)GetGoState() << ")"; @@ -1222,6 +1238,26 @@ void GameObject::Use(Unit* user) } break; } + case GAMEOBJECT_TYPE_BARBER_CHAIR: //32 + { + GameObjectInfo const* info = GetGOInfo(); + if(!info) + return; + + if(user->GetTypeId()!=TYPEID_PLAYER) + return; + + Player* player = (Player*)user; + + // fallback, will always work + player->TeleportTo(GetMapId(), GetPositionX(), GetPositionY(), GetPositionZ(), GetOrientation(),TELE_TO_NOT_LEAVE_TRANSPORT | TELE_TO_NOT_LEAVE_COMBAT | TELE_TO_NOT_UNSUMMON_PET); + + WorldPacket data(SMSG_ENABLE_BARBER_SHOP, 0); + player->GetSession()->SendPacket(&data); + + player->SetStandState(PLAYER_STATE_SIT_LOW_CHAIR+info->barberChair.chairheight); + return; + } default: sLog.outDebug("Unknown Object Type %u", GetGoType()); break; diff --git a/src/game/GameObject.h b/src/game/GameObject.h index 0961a9cfc..3865a23c8 100644 --- a/src/game/GameObject.h +++ b/src/game/GameObject.h @@ -334,12 +334,12 @@ struct GameObjectInfo uint32 mapID; //0 uint32 difficulty; //1 } dungeonDifficulty; - //32 GAMEOBJECT_TYPE_DO_NOT_USE_YET + //32 GAMEOBJECT_TYPE_BARBER_CHAIR struct { - uint32 mapID; //0 - uint32 difficulty; //1 - } doNotUseYet; + uint32 chairheight; //0 + uint32 heightOffset; //1 + } barberChair; //33 GAMEOBJECT_TYPE_DESTRUCTIBLE_BUILDING struct { @@ -348,6 +348,13 @@ struct GameObjectInfo uint32 state1Name; //2 uint32 state2Name; //3 } destructibleBuilding; + //34 GAMEOBJECT_TYPE_TRAPDOOR + struct + { + uint32 whenToPause; // 0 + uint32 startOpen; // 1 + uint32 autoClose; // 2 + } trapDoor; // not use for specific field access (only for output with loop by all filed), also this determinate max union size struct // GAMEOBJECT_TYPE_SPELLCASTER @@ -500,14 +507,14 @@ class MANGOS_DLL_SPEC GameObject : public WorldObject void SetSpellId(uint32 id) { m_spellId = id;} uint32 GetSpellId() const { return m_spellId;} void getFishLoot(Loot *loot); - GameobjectTypes GetGoType() const { return GameobjectTypes(GetUInt32Value(GAMEOBJECT_TYPE_ID)); } - void SetGoType(GameobjectTypes type) { SetUInt32Value(GAMEOBJECT_TYPE_ID, type); } - uint32 GetGoState() const { return GetUInt32Value(GAMEOBJECT_STATE); } - void SetGoState(uint32 state) { SetUInt32Value(GAMEOBJECT_STATE, state); } - uint32 GetGoArtKit() const { return GetUInt32Value(GAMEOBJECT_ARTKIT); } - void SetGoArtKit(uint32 artkit) { SetUInt32Value(GAMEOBJECT_ARTKIT, artkit); } - uint32 GetGoAnimProgress() const { return GetUInt32Value(GAMEOBJECT_ANIMPROGRESS); } - void SetGoAnimProgress(uint32 animprogress) { SetUInt32Value(GAMEOBJECT_ANIMPROGRESS, animprogress); } + GameobjectTypes GetGoType() const { return GameobjectTypes(GetByteValue(GAMEOBJECT_BYTES_1, 1)); } + void SetGoType(GameobjectTypes type) { SetByteValue(GAMEOBJECT_BYTES_1, 1, type); } + uint8 GetGoState() const { return GetByteValue(GAMEOBJECT_BYTES_1, 0); } + void SetGoState(uint8 state) { SetByteValue(GAMEOBJECT_BYTES_1, 0, state); } + uint8 GetGoArtKit() const { return GetByteValue(GAMEOBJECT_BYTES_1, 2); } + void SetGoArtKit(uint8 artkit) { SetByteValue(GAMEOBJECT_BYTES_1, 2, artkit); } + uint8 GetGoAnimProgress() const { return GetByteValue(GAMEOBJECT_BYTES_1, 3); } + void SetGoAnimProgress(uint8 animprogress) { SetByteValue(GAMEOBJECT_BYTES_1, 3, animprogress); } void Use(Unit* user); diff --git a/src/game/GossipDef.cpp b/src/game/GossipDef.cpp index a690254e2..c61ab5e10 100644 --- a/src/game/GossipDef.cpp +++ b/src/game/GossipDef.cpp @@ -34,7 +34,7 @@ GossipMenu::~GossipMenu() ClearMenu(); } -void GossipMenu::AddMenuItem(uint8 Icon, std::string Message, uint32 dtSender, uint32 dtAction, std::string BoxMessage, uint32 BoxMoney, bool Coded) +void GossipMenu::AddMenuItem(uint8 Icon, const std::string& Message, uint32 dtSender, uint32 dtAction, const std::string& BoxMessage, uint32 BoxMoney, bool Coded) { ASSERT( m_gItems.size() <= GOSSIP_MAX_MENU_ITEMS ); @@ -51,7 +51,7 @@ void GossipMenu::AddMenuItem(uint8 Icon, std::string Message, uint32 dtSender, u m_gItems.push_back(gItem); } -void GossipMenu::AddMenuItem(uint8 Icon, std::string Message, bool Coded) +void GossipMenu::AddMenuItem(uint8 Icon, const std::string& Message, bool Coded) { AddMenuItem( Icon, Message, 0, 0, "", 0, Coded); } @@ -341,7 +341,7 @@ void QuestMenu::ClearMenu() m_qItems.clear(); } -void PlayerMenu::SendQuestGiverQuestList( QEmote eEmote, std::string Title, uint64 npcGUID ) +void PlayerMenu::SendQuestGiverQuestList( QEmote eEmote, const std::string& Title, uint64 npcGUID ) { WorldPacket data( SMSG_QUESTGIVER_QUEST_LIST, 100 ); // guess size data << uint64(npcGUID); @@ -415,10 +415,14 @@ void PlayerMenu::SendQuestGiverQuestDetails( Quest const *pQuest, uint64 npcGUID } data << uint64(npcGUID); + data << uint64(0); // wotlk, something todo with quest sharing? data << uint32(pQuest->GetQuestId()); - data << Title << Details << Objectives; + data << Title; + data << Details; + data << Objectives; data << uint32(ActivateAccept); data << uint32(pQuest->GetSuggestedPlayers()); + data << uint8(0); // new wotlk if (pQuest->HasFlag(QUEST_FLAGS_HIDDEN_REWARDS)) { @@ -464,6 +468,7 @@ void PlayerMenu::SendQuestGiverQuestDetails( Quest const *pQuest, uint64 npcGUID data << uint32(pQuest->GetRewSpell()); // reward spell, this spell will display (icon) (casted if RewSpellCast==0) data << uint32(pQuest->GetRewSpellCast()); // casted spell data << uint32(pQuest->GetCharTitleId()); // CharTitleId, new 2.4.0, player gets this title (id from CharTitles) + data << uint32(pQuest->GetBonusTalents()); // bonus talents data << uint32(QUEST_EMOTE_COUNT); for (uint32 i=0; i < QUEST_EMOTE_COUNT; i++) @@ -540,6 +545,8 @@ void PlayerMenu::SendQuestQueryResponse( Quest const *pQuest ) data << uint32(pQuest->GetSrcItemId()); data << uint32(pQuest->GetFlags() & 0xFFFF); data << uint32(pQuest->GetCharTitleId()); // CharTitleId, new 2.4.0, player gets this title (id from CharTitles) + data << uint32(pQuest->GetPlayersSlain()); // players slain + data << uint32(pQuest->GetBonusTalents()); // bonus talents int iI; @@ -588,13 +595,14 @@ void PlayerMenu::SendQuestQueryResponse( Quest const *pQuest ) data << uint32(pQuest->ReqCreatureOrGOCount[iI]); data << uint32(pQuest->ReqItemId[iI]); data << uint32(pQuest->ReqItemCount[iI]); + data << uint32(0); // added in WotLK, dunno if offset if correct } for (iI = 0; iI < QUEST_OBJECTIVES_COUNT; iI++) data << ObjectiveText[iI]; pSession->SendPacket( &data ); - sLog.outDebug( "WORLD: Sent SMSG_QUEST_QUERY_RESPONSE questid=%u",pQuest->GetQuestId() ); + sLog.outDebug( "WORLD: Sent SMSG_QUEST_QUERY_RESPONSE questid=%u", pQuest->GetQuestId() ); } void PlayerMenu::SendQuestGiverOfferReward( Quest const* pQuest, uint64 npcGUID, bool EnbleNext ) @@ -676,9 +684,10 @@ void PlayerMenu::SendQuestGiverOfferReward( Quest const* pQuest, uint64 npcGUID, data << uint32(0x08); // unused by client? data << uint32(pQuest->GetRewSpell()); // reward spell, this spell will display (icon) (casted if RewSpellCast==0) data << uint32(pQuest->GetRewSpellCast()); // casted spell - data << uint32(0x00); // unk, NOT honor + data << uint32(0); // unknown + data << uint32(pQuest->GetBonusTalents()); // bonus talents pSession->SendPacket( &data ); - sLog.outDebug( "WORLD: Sent SMSG_QUESTGIVER_OFFER_REWARD NPCGuid=%u, questid=%u",GUID_LOPART(npcGUID),pQuest->GetQuestId() ); + sLog.outDebug( "WORLD: Sent SMSG_QUESTGIVER_OFFER_REWARD NPCGuid=%u, questid=%u", GUID_LOPART(npcGUID), pQuest->GetQuestId() ); } void PlayerMenu::SendQuestGiverRequestItems( Quest const *pQuest, uint64 npcGUID, bool Completable, bool CloseOnCancel ) diff --git a/src/game/GossipDef.h b/src/game/GossipDef.h index ba5b36008..7cde0c3b1 100644 --- a/src/game/GossipDef.h +++ b/src/game/GossipDef.h @@ -101,8 +101,8 @@ class MANGOS_DLL_SPEC GossipMenu GossipMenu(); ~GossipMenu(); - void AddMenuItem(uint8 Icon, std::string Message, bool Coded = false); - void AddMenuItem(uint8 Icon, std::string Message, uint32 dtSender, uint32 dtAction, std::string BoxMessage, uint32 BoxMoney, bool Coded = false); + void AddMenuItem(uint8 Icon, const std::string& Message, bool Coded = false); + void AddMenuItem(uint8 Icon, const std::string& Message, uint32 dtSender, uint32 dtAction, const std::string& BoxMessage, uint32 BoxMoney, bool Coded = false); // for using from scripts, don't must be inlined void AddMenuItem(uint8 Icon, char const* Message, bool Coded = false); @@ -195,7 +195,7 @@ class MANGOS_DLL_SPEC PlayerMenu /*********************************************************/ void SendQuestGiverStatus( uint8 questStatus, uint64 npcGUID ); - void SendQuestGiverQuestList( QEmote eEmote, std::string Title, uint64 npcGUID ); + void SendQuestGiverQuestList( QEmote eEmote, const std::string& Title, uint64 npcGUID ); void SendQuestQueryResponse ( Quest const *pQuest ); void SendQuestGiverQuestDetails( Quest const *pQuest, uint64 npcGUID, bool ActivateAccept); diff --git a/src/game/GridNotifiers.cpp b/src/game/GridNotifiers.cpp index 2d2d63750..8c611815b 100644 --- a/src/game/GridNotifiers.cpp +++ b/src/game/GridNotifiers.cpp @@ -134,7 +134,7 @@ VisibleNotifier::Notify() // send data at target visibility change (adding to client) for(std::set::const_iterator vItr = i_visibleNow.begin(); vItr != i_visibleNow.end(); ++vItr) if((*vItr)!=&i_player && (*vItr)->isType(TYPEMASK_UNIT)) - i_player.SendAuraDurationsForTarget((Unit*)(*vItr)); + i_player.SendAurasForTarget((Unit*)(*vItr)); } void diff --git a/src/game/Group.cpp b/src/game/Group.cpp index de97b70b3..8279f4c82 100644 --- a/src/game/Group.cpp +++ b/src/game/Group.cpp @@ -1308,6 +1308,54 @@ void Group::UpdateLooterGuid( Creature* creature, bool ifneed ) SendUpdate(); } +uint32 Group::CanJoinBattleGroundQueue(uint32 bgTypeId, uint32 bgQueueType, uint32 MinPlayerCount, uint32 MaxPlayerCount, bool isRated, uint32 arenaSlot) +{ + // check for min / max count + uint32 memberscount = GetMembersCount(); + if(memberscount < MinPlayerCount) + return BG_JOIN_ERR_GROUP_NOT_ENOUGH; + if(memberscount > MaxPlayerCount) + return BG_JOIN_ERR_GROUP_TOO_MANY; + + // get a player as reference, to compare other players' stats to (arena team id, queue id based on level, etc.) + Player * reference = GetFirstMember()->getSource(); + // no reference found, can't join this way + if(!reference) + return BG_JOIN_ERR_OFFLINE_MEMBER; + + uint32 bgQueueId = reference->GetBattleGroundQueueIdFromLevel(); + uint32 arenaTeamId = reference->GetArenaTeamId(arenaSlot); + uint32 team = reference->GetTeam(); + + // check every member of the group to be able to join + for(GroupReference *itr = GetFirstMember(); itr != NULL; itr = itr->next()) + { + Player *member = itr->getSource(); + // offline member? don't let join + if(!member) + return BG_JOIN_ERR_OFFLINE_MEMBER; + // don't allow cross-faction join as group + if(member->GetTeam() != team) + return BG_JOIN_ERR_MIXED_FACTION; + // not in the same battleground level braket, don't let join + if(member->GetBattleGroundQueueIdFromLevel() != bgQueueId) + return BG_JOIN_ERR_MIXED_LEVELS; + // don't let join rated matches if the arena team id doesn't match + if(isRated && member->GetArenaTeamId(arenaSlot) != arenaTeamId) + return BG_JOIN_ERR_MIXED_ARENATEAM; + // don't let join if someone from the group is already in that bg queue + if(member->InBattleGroundQueueForBattleGroundQueueType(bgQueueType)) + return BG_JOIN_ERR_GROUP_MEMBER_ALREADY_IN_QUEUE; + // check for deserter debuff in case not arena queue + if(bgTypeId != BATTLEGROUND_AA && !member->CanJoinToBattleground()) + return BG_JOIN_ERR_GROUP_DESERTER; + // check if member can join any more battleground queues + if(!member->HasFreeBattleGroundQueueId()) + return BG_JOIN_ERR_ALL_QUEUES_USED; + } + return BG_JOIN_ERR_OK; +} + //=================================================== //============== Roll =============================== //=================================================== diff --git a/src/game/Group.h b/src/game/Group.h index a9e6a733f..94fbb9d72 100644 --- a/src/game/Group.h +++ b/src/game/Group.h @@ -64,24 +64,25 @@ enum GroupUpdateFlags { GROUP_UPDATE_FLAG_NONE = 0x00000000, // nothing GROUP_UPDATE_FLAG_STATUS = 0x00000001, // uint16, flags - GROUP_UPDATE_FLAG_CUR_HP = 0x00000002, // uint16 - GROUP_UPDATE_FLAG_MAX_HP = 0x00000004, // uint16 + GROUP_UPDATE_FLAG_CUR_HP = 0x00000002, // uint32 + GROUP_UPDATE_FLAG_MAX_HP = 0x00000004, // uint32 GROUP_UPDATE_FLAG_POWER_TYPE = 0x00000008, // uint8 GROUP_UPDATE_FLAG_CUR_POWER = 0x00000010, // uint16 GROUP_UPDATE_FLAG_MAX_POWER = 0x00000020, // uint16 GROUP_UPDATE_FLAG_LEVEL = 0x00000040, // uint16 GROUP_UPDATE_FLAG_ZONE = 0x00000080, // uint16 GROUP_UPDATE_FLAG_POSITION = 0x00000100, // uint16, uint16 - GROUP_UPDATE_FLAG_AURAS = 0x00000200, // uint64 mask, for each bit set uint16 spellid + uint8 unk + GROUP_UPDATE_FLAG_AURAS = 0x00000200, // uint64 mask, for each bit set uint32 spellid + uint8 unk GROUP_UPDATE_FLAG_PET_GUID = 0x00000400, // uint64 pet guid GROUP_UPDATE_FLAG_PET_NAME = 0x00000800, // pet name, NULL terminated string GROUP_UPDATE_FLAG_PET_MODEL_ID = 0x00001000, // uint16, model id - GROUP_UPDATE_FLAG_PET_CUR_HP = 0x00002000, // uint16 pet cur health - GROUP_UPDATE_FLAG_PET_MAX_HP = 0x00004000, // uint16 pet max health + GROUP_UPDATE_FLAG_PET_CUR_HP = 0x00002000, // uint32 pet cur health + GROUP_UPDATE_FLAG_PET_MAX_HP = 0x00004000, // uint32 pet max health GROUP_UPDATE_FLAG_PET_POWER_TYPE = 0x00008000, // uint8 pet power type GROUP_UPDATE_FLAG_PET_CUR_POWER = 0x00010000, // uint16 pet cur power GROUP_UPDATE_FLAG_PET_MAX_POWER = 0x00020000, // uint16 pet max power - GROUP_UPDATE_FLAG_PET_AURAS = 0x00040000, // uint64 mask, for each bit set uint16 spellid + uint8 unk, pet auras... + GROUP_UPDATE_FLAG_PET_AURAS = 0x00040000, // uint64 mask, for each bit set uint32 spellid + uint8 unk, pet auras... + GROUP_UPDATE_FLAG_VEHICLE_SEAT = 0x00080000, // uint32 vehicle_seat_id (index from VehicleSeat.dbc) GROUP_UPDATE_PET = 0x0007FC00, // all pet flags GROUP_UPDATE_FULL = 0x0007FFFF, // all known flags }; @@ -247,6 +248,7 @@ class MANGOS_DLL_SPEC Group void ConvertToRaid(); void SetBattlegroundGroup(BattleGround *bg) { m_bgGroup = bg; } + uint32 CanJoinBattleGroundQueue(uint32 bgTypeId, uint32 bgQueueType, uint32 MinPlayerCount, uint32 MaxPlayerCount, bool isRated, uint32 arenaSlot); void ChangeMembersGroup(const uint64 &guid, const uint8 &group); void ChangeMembersGroup(Player *player, const uint8 &group); diff --git a/src/game/GroupHandler.cpp b/src/game/GroupHandler.cpp index 2d05e6655..851e21030 100644 --- a/src/game/GroupHandler.cpp +++ b/src/game/GroupHandler.cpp @@ -680,10 +680,10 @@ void WorldSession::BuildPartyMemberStatsChangedPacket(Player *player, WorldPacke } if (mask & GROUP_UPDATE_FLAG_CUR_HP) - *data << (uint16) player->GetHealth(); + *data << (uint32) player->GetHealth(); if (mask & GROUP_UPDATE_FLAG_MAX_HP) - *data << (uint16) player->GetMaxHealth(); + *data << (uint32) player->GetMaxHealth(); Powers powerType = player->getPowerType(); if (mask & GROUP_UPDATE_FLAG_POWER_TYPE) @@ -712,7 +712,7 @@ void WorldSession::BuildPartyMemberStatsChangedPacket(Player *player, WorldPacke { if(auramask & (uint64(1) << i)) { - *data << uint16(player->GetUInt32Value(UNIT_FIELD_AURA + i)); + *data << uint32(player->GetVisibleAura(i)); *data << uint8(1); } } @@ -746,17 +746,17 @@ void WorldSession::BuildPartyMemberStatsChangedPacket(Player *player, WorldPacke if (mask & GROUP_UPDATE_FLAG_PET_CUR_HP) { if(pet) - *data << (uint16) pet->GetHealth(); + *data << (uint32) pet->GetHealth(); else - *data << (uint16) 0; + *data << (uint32) 0; } if (mask & GROUP_UPDATE_FLAG_PET_MAX_HP) { if(pet) - *data << (uint16) pet->GetMaxHealth(); + *data << (uint32) pet->GetMaxHealth(); else - *data << (uint16) 0; + *data << (uint32) 0; } if (mask & GROUP_UPDATE_FLAG_PET_POWER_TYPE) @@ -793,7 +793,7 @@ void WorldSession::BuildPartyMemberStatsChangedPacket(Player *player, WorldPacke { if(auramask & (uint64(1) << i)) { - *data << uint16(pet->GetUInt32Value(UNIT_FIELD_AURA + i)); + *data << uint32(pet->GetVisibleAura(i)); *data << uint8(1); } } @@ -816,6 +816,7 @@ void WorldSession::HandleRequestPartyMemberStatsOpcode( WorldPacket &recv_data ) if(!player) { WorldPacket data(SMSG_PARTY_MEMBER_STATS_FULL, 3+4+2); + data << uint8(0); // only for SMSG_PARTY_MEMBER_STATS_FULL, probably arena/bg related data.appendPackGUID(Guid); data << (uint32) GROUP_UPDATE_FLAG_STATUS; data << (uint16) MEMBER_STATUS_OFFLINE; @@ -826,6 +827,7 @@ void WorldSession::HandleRequestPartyMemberStatsOpcode( WorldPacket &recv_data ) Pet *pet = player->GetPet(); WorldPacket data(SMSG_PARTY_MEMBER_STATS_FULL, 4+2+2+2+1+2*6+8+1+8); + data << uint8(0); // only for SMSG_PARTY_MEMBER_STATS_FULL, probably arena/bg related data.append(player->GetPackGUID()); uint32 mask1 = 0x00040BFF; // common mask, real flags used 0x000040BFF @@ -835,8 +837,8 @@ void WorldSession::HandleRequestPartyMemberStatsOpcode( WorldPacket &recv_data ) Powers powerType = player->getPowerType(); data << (uint32) mask1; // group update mask data << (uint16) MEMBER_STATUS_ONLINE; // member's online status - data << (uint16) player->GetHealth(); // GROUP_UPDATE_FLAG_CUR_HP - data << (uint16) player->GetMaxHealth(); // GROUP_UPDATE_FLAG_MAX_HP + data << (uint32) player->GetHealth(); // GROUP_UPDATE_FLAG_CUR_HP + data << (uint32) player->GetMaxHealth(); // GROUP_UPDATE_FLAG_MAX_HP data << (uint8) powerType; // GROUP_UPDATE_FLAG_POWER_TYPE data << (uint16) player->GetPower(powerType); // GROUP_UPDATE_FLAG_CUR_POWER data << (uint16) player->GetMaxPower(powerType); // GROUP_UPDATE_FLAG_MAX_POWER @@ -850,11 +852,11 @@ void WorldSession::HandleRequestPartyMemberStatsOpcode( WorldPacket &recv_data ) data << (uint64) auramask; // placeholder for(uint8 i = 0; i < MAX_AURAS; ++i) { - if(uint32 aura = player->GetUInt32Value(UNIT_FIELD_AURA + i)) + if(uint32 aura = player->GetVisibleAura(i)) { auramask |= (uint64(1) << i); - data << uint16(aura); - data << uint8(1); + data << (uint32) aura; + data << (uint8) 1; } } data.put(maskPos,auramask); // GROUP_UPDATE_FLAG_AURAS @@ -865,8 +867,8 @@ void WorldSession::HandleRequestPartyMemberStatsOpcode( WorldPacket &recv_data ) data << (uint64) pet->GetGUID(); // GROUP_UPDATE_FLAG_PET_GUID data << pet->GetName(); // GROUP_UPDATE_FLAG_PET_NAME data << (uint16) pet->GetDisplayId(); // GROUP_UPDATE_FLAG_PET_MODEL_ID - data << (uint16) pet->GetHealth(); // GROUP_UPDATE_FLAG_PET_CUR_HP - data << (uint16) pet->GetMaxHealth(); // GROUP_UPDATE_FLAG_PET_MAX_HP + data << (uint32) pet->GetHealth(); // GROUP_UPDATE_FLAG_PET_CUR_HP + data << (uint32) pet->GetMaxHealth(); // GROUP_UPDATE_FLAG_PET_MAX_HP data << (uint8) petpowertype; // GROUP_UPDATE_FLAG_PET_POWER_TYPE data << (uint16) pet->GetPower(petpowertype); // GROUP_UPDATE_FLAG_PET_CUR_POWER data << (uint16) pet->GetMaxPower(petpowertype); // GROUP_UPDATE_FLAG_PET_MAX_POWER @@ -876,10 +878,10 @@ void WorldSession::HandleRequestPartyMemberStatsOpcode( WorldPacket &recv_data ) data << (uint64) petauramask; // placeholder for(uint8 i = 0; i < MAX_AURAS; ++i) { - if(uint32 petaura = pet->GetUInt32Value(UNIT_FIELD_AURA + i)) + if(uint32 petaura = pet->GetVisibleAura(i)) { petauramask |= (uint64(1) << i); - data << (uint16) petaura; + data << (uint32) petaura; data << (uint8) 1; } } diff --git a/src/game/Guild.cpp b/src/game/Guild.cpp index 19f6214b8..cedfc6e6a 100644 --- a/src/game/Guild.cpp +++ b/src/game/Guild.cpp @@ -359,28 +359,41 @@ bool Guild::FillPlayerData(uint64 guid, MemberSlot* memslot) } else { - if(!objmgr.GetPlayerNameByGUID(guid, plName)) // player doesn't exist - return false; + QueryResult *result = CharacterDatabase.PQuery("SELECT name,data,zone,class FROM characters WHERE guid = '%u'", GUID_LOPART(guid)); + if(!result) + return false; // player doesn't exist - plLevel = Player::GetUInt32ValueFromDB(UNIT_FIELD_LEVEL, guid); - if(plLevel<1||plLevel>255) // can be at broken `data` field + Field *fields = result->Fetch(); + + plName = fields[0].GetCppString(); + + Tokens data = StrSplit(fields[1].GetCppString(), " "); + plLevel = Player::GetUInt32ValueFromArray(data,UNIT_FIELD_LEVEL); + + plZone = fields[2].GetUInt32(); + plClass = fields[3].GetUInt32(); + delete result; + + if(plLevel<1||plLevel>STRONG_MAX_LEVEL) // can be at broken `data` field { sLog.outError("Player (GUID: %u) has a broken data in field `characters`.`data`.",GUID_LOPART(guid)); return false; } - plZone = Player::GetZoneIdFromDB(guid); - QueryResult *result = CharacterDatabase.PQuery("SELECT class FROM characters WHERE guid='%u'", GUID_LOPART(guid)); - if(!result) - return false; - plClass = (*result)[0].GetUInt32(); + if(!plZone) + { + sLog.outError("Player (GUID: %u) has broken zone-data",GUID_LOPART(guid)); + //here it will also try the same, to get the zone from characters-table, but additional it tries to find + plZone = Player::GetZoneIdFromDB(guid); + //the zone through xy coords.. this is a bit redundant, but + //shouldn't be called often + } + if(plClass=MAX_CLASSES) // can be at broken `class` field { sLog.outError("Player (GUID: %u) has a broken data in field `characters`.`class`.",GUID_LOPART(guid)); return false; } - - delete result; } memslot->name = plName; @@ -517,7 +530,7 @@ void Guild::SetOFFNOTE(uint64 guid,std::string offnote) CharacterDatabase.PExecute("UPDATE guild_member SET offnote = '%s' WHERE guid = '%u'", offnote.c_str(), itr->first); } -void Guild::BroadcastToGuild(WorldSession *session, std::string msg, uint32 language) +void Guild::BroadcastToGuild(WorldSession *session, const std::string& msg, uint32 language) { if (session && session->GetPlayer() && HasRankRight(session->GetPlayer()->GetRank(),GR_RIGHT_GCHATSPEAK)) { @@ -534,7 +547,7 @@ void Guild::BroadcastToGuild(WorldSession *session, std::string msg, uint32 lang } } -void Guild::BroadcastToOfficers(WorldSession *session, std::string msg, uint32 language) +void Guild::BroadcastToOfficers(WorldSession *session, const std::string& msg, uint32 language) { if (session && session->GetPlayer() && HasRankRight(session->GetPlayer()->GetRank(),GR_RIGHT_OFFCHATSPEAK)) { @@ -593,7 +606,7 @@ void Guild::CreateRank(std::string name_,uint32 rights) CharacterDatabase.PExecute( "INSERT INTO guild_rank (guildid,rid,rname,rights) VALUES ('%u', '%u', '%s', '%u')", Id, m_ranks.size(), name_.c_str(), rights ); } -void Guild::AddRank(std::string name_,uint32 rights, uint32 money) +void Guild::AddRank(const std::string& name_,uint32 rights, uint32 money) { m_ranks.push_back(RankInfo(name_,rights,money)); } @@ -754,6 +767,7 @@ void Guild::Query(WorldSession *session) data << uint32(BorderStyle); data << uint32(BorderColor); data << uint32(BackgroundColor); + data << uint32(0); // something new in WotLK session->SendPacket( &data ); sLog.outDebug( "WORLD: Sent (SMSG_GUILD_QUERY_RESPONSE)" ); @@ -1571,7 +1585,21 @@ void Guild::DisplayGuildBankLogs(WorldSession *session, uint8 TabId) { data << uint8((*itr)->LogEntry); data << uint64(MAKE_NEW_GUID((*itr)->PlayerGuid,0,HIGHGUID_PLAYER)); - data << uint32((*itr)->ItemOrMoney); + if ((*itr)->LogEntry == GUILD_BANK_LOG_DEPOSIT_MONEY || + (*itr)->LogEntry == GUILD_BANK_LOG_WITHDRAW_MONEY || + (*itr)->LogEntry == GUILD_BANK_LOG_REPAIR_MONEY || + (*itr)->LogEntry == GUILD_BANK_LOG_UNK1 || + (*itr)->LogEntry == GUILD_BANK_LOG_UNK2) + { + data << uint32((*itr)->ItemOrMoney); + } + else + { + data << uint32((*itr)->ItemOrMoney); + data << uint32((*itr)->ItemStackCount); + if ((*itr)->LogEntry == GUILD_BANK_LOG_MOVE_ITEM || (*itr)->LogEntry == GUILD_BANK_LOG_MOVE_ITEM2) + data << uint8((*itr)->DestTabId); // moved tab + } data << uint32(time(NULL)-(*itr)->TimeStamp); } session->SendPacket(&data); @@ -1587,10 +1615,21 @@ void Guild::DisplayGuildBankLogs(WorldSession *session, uint8 TabId) { data << uint8((*itr)->LogEntry); data << uint64(MAKE_NEW_GUID((*itr)->PlayerGuid,0,HIGHGUID_PLAYER)); - data << uint32((*itr)->ItemOrMoney); - data << uint8((*itr)->ItemStackCount); - if ((*itr)->LogEntry == GUILD_BANK_LOG_MOVE_ITEM || (*itr)->LogEntry == GUILD_BANK_LOG_MOVE_ITEM2) - data << uint8((*itr)->DestTabId); // moved tab + if ((*itr)->LogEntry == GUILD_BANK_LOG_DEPOSIT_MONEY || + (*itr)->LogEntry == GUILD_BANK_LOG_WITHDRAW_MONEY || + (*itr)->LogEntry == GUILD_BANK_LOG_REPAIR_MONEY || + (*itr)->LogEntry == GUILD_BANK_LOG_UNK1 || + (*itr)->LogEntry == GUILD_BANK_LOG_UNK2) + { + data << uint32((*itr)->ItemOrMoney); + } + else + { + data << uint32((*itr)->ItemOrMoney); + data << uint32((*itr)->ItemStackCount); + if ((*itr)->LogEntry == GUILD_BANK_LOG_MOVE_ITEM || (*itr)->LogEntry == GUILD_BANK_LOG_MOVE_ITEM2) + data << uint8((*itr)->DestTabId); // moved tab + } data << uint32(time(NULL)-(*itr)->TimeStamp); } session->SendPacket(&data); @@ -1672,7 +1711,7 @@ void Guild::AppendDisplayGuildBankSlot( WorldPacket& data, GuildBankTab const *t // SuffixFactor +4 data << (uint32) pItem->GetItemSuffixFactor(); // +12 // ITEM_FIELD_STACK_COUNT - data << uint8(pItem->GetCount()); + data << uint32(pItem->GetCount()); data << uint32(0); // +16 // Unknown value data << uint8(0); // unknown 2.4.2 if (uint32 Enchant0 = pItem->GetEnchantmentId(PERM_ENCHANTMENT_SLOT)) diff --git a/src/game/Guild.h b/src/game/Guild.h index a97a8cfb0..1a4cdf9a5 100644 --- a/src/game/Guild.h +++ b/src/game/Guild.h @@ -54,7 +54,8 @@ enum GuildRankRights GR_RIGHT_REPAIR_FROM_GUILD = 0x00020000, // unused in 2.4.x?, Remove money withdraw capacity GR_RIGHT_WITHDRAW_REPAIR = 0x00040000, // withdraw for repair GR_RIGHT_WITHDRAW_GOLD = 0x00080000, // withdraw gold - GR_RIGHT_ALL = 0x000FF1FF + GR_RIGHT_CREATE_GUILD_EVENT = 0x00100000, // wotlk + GR_RIGHT_ALL = 0x001FF1FF }; enum Typecommand @@ -154,6 +155,8 @@ enum GuildBankLogEntries GUILD_BANK_LOG_WITHDRAW_MONEY = 5, GUILD_BANK_LOG_REPAIR_MONEY = 6, GUILD_BANK_LOG_MOVE_ITEM2 = 7, + GUILD_BANK_LOG_UNK1 = 8, + GUILD_BANK_LOG_UNK2 = 9, }; enum GuildEventLogEntryTypes @@ -242,7 +245,7 @@ struct MemberSlot struct RankInfo { - RankInfo(std::string _name, uint32 _rights, uint32 _money) : name(_name), rights(_rights), BankMoneyPerDay(_money) + RankInfo(const std::string& _name, uint32 _rights, uint32 _money) : name(_name), rights(_rights), BankMoneyPerDay(_money) { for(uint8 i = 0; i < GUILD_BANK_MAX_TABS; ++i) { @@ -307,8 +310,8 @@ class Guild bool FillPlayerData(uint64 guid, MemberSlot* memslot); void LoadPlayerStatsByGuid(uint64 guid); - void BroadcastToGuild(WorldSession *session, std::string msg, uint32 language = LANG_UNIVERSAL); - void BroadcastToOfficers(WorldSession *session, std::string msg, uint32 language = LANG_UNIVERSAL); + void BroadcastToGuild(WorldSession *session, const std::string& msg, uint32 language = LANG_UNIVERSAL); + void BroadcastToOfficers(WorldSession *session, const std::string& msg, uint32 language = LANG_UNIVERSAL); void BroadcastPacketToRank(WorldPacket *packet, uint32 rankId); void BroadcastPacket(WorldPacket *packet); @@ -405,7 +408,7 @@ class Guild bool AddGBankItemToDB(uint32 GuildId, uint32 BankTab , uint32 BankTabSlot , uint32 GUIDLow, uint32 Entry ); protected: - void AddRank(std::string name,uint32 rights,uint32 money); + void AddRank(const std::string& name,uint32 rights,uint32 money); uint32 Id; std::string name; diff --git a/src/game/GuildHandler.cpp b/src/game/GuildHandler.cpp index d40bb9b4d..8b093b808 100644 --- a/src/game/GuildHandler.cpp +++ b/src/game/GuildHandler.cpp @@ -730,7 +730,7 @@ void WorldSession::HandleGuildDelRankOpcode(WorldPacket& /*recvPacket*/) guild->Roster(this); } -void WorldSession::SendGuildCommandResult(uint32 typecmd,std::string str,uint32 cmdresult) +void WorldSession::SendGuildCommandResult(uint32 typecmd, const std::string& str,uint32 cmdresult) { WorldPacket data(SMSG_GUILD_COMMAND_RESULT, (8+str.size()+1)); data << typecmd; diff --git a/src/game/Item.cpp b/src/game/Item.cpp index 7f9f2145b..cbdcc0ca6 100644 --- a/src/game/Item.cpp +++ b/src/game/Item.cpp @@ -204,6 +204,10 @@ bool ItemCanGoIntoBag(ItemPrototype const *pProto, ItemPrototype const *pBagProt if(!(pProto->BagFamily & BAG_FAMILY_MASK_LEATHERWORKING_SUPP)) return false; return true; + case ITEM_SUBCLASS_INSCRIPTION_CONTAINER: + if(!(pProto->BagFamily & BAG_FAMILY_MASK_INSCRIPTION_SUPP)) + return false; + return true; default: return false; } @@ -448,7 +452,7 @@ uint32 Item::GetSkill() const static uint32 item_armor_skills[MAX_ITEM_SUBCLASS_ARMOR] = { - 0,SKILL_CLOTH,SKILL_LEATHER,SKILL_MAIL,SKILL_PLATE_MAIL,0,SKILL_SHIELD,0,0,0 + 0,SKILL_CLOTH,SKILL_LEATHER,SKILL_MAIL,SKILL_PLATE_MAIL,0,SKILL_SHIELD,0,0,0,0 }; ItemPrototype const* proto = GetProto(); @@ -763,9 +767,9 @@ void Item::SetEnchantment(EnchantmentSlot slot, uint32 id, uint32 duration, uint if((GetEnchantmentId(slot) == id) && (GetEnchantmentDuration(slot) == duration) && (GetEnchantmentCharges(slot) == charges)) return; - SetUInt32Value(ITEM_FIELD_ENCHANTMENT + slot*MAX_ENCHANTMENT_OFFSET + ENCHANTMENT_ID_OFFSET,id); - SetUInt32Value(ITEM_FIELD_ENCHANTMENT + slot*MAX_ENCHANTMENT_OFFSET + ENCHANTMENT_DURATION_OFFSET,duration); - SetUInt32Value(ITEM_FIELD_ENCHANTMENT + slot*MAX_ENCHANTMENT_OFFSET + ENCHANTMENT_CHARGES_OFFSET,charges); + SetUInt32Value(ITEM_FIELD_ENCHANTMENT_1_1 + slot*MAX_ENCHANTMENT_OFFSET + ENCHANTMENT_ID_OFFSET,id); + SetUInt32Value(ITEM_FIELD_ENCHANTMENT_1_1 + slot*MAX_ENCHANTMENT_OFFSET + ENCHANTMENT_DURATION_OFFSET,duration); + SetUInt32Value(ITEM_FIELD_ENCHANTMENT_1_1 + slot*MAX_ENCHANTMENT_OFFSET + ENCHANTMENT_CHARGES_OFFSET,charges); SetState(ITEM_CHANGED); } @@ -774,7 +778,7 @@ void Item::SetEnchantmentDuration(EnchantmentSlot slot, uint32 duration) if(GetEnchantmentDuration(slot) == duration) return; - SetUInt32Value(ITEM_FIELD_ENCHANTMENT + slot*MAX_ENCHANTMENT_OFFSET + ENCHANTMENT_DURATION_OFFSET,duration); + SetUInt32Value(ITEM_FIELD_ENCHANTMENT_1_1 + slot*MAX_ENCHANTMENT_OFFSET + ENCHANTMENT_DURATION_OFFSET,duration); SetState(ITEM_CHANGED); } @@ -783,7 +787,7 @@ void Item::SetEnchantmentCharges(EnchantmentSlot slot, uint32 charges) if(GetEnchantmentCharges(slot) == charges) return; - SetUInt32Value(ITEM_FIELD_ENCHANTMENT + slot*MAX_ENCHANTMENT_OFFSET + ENCHANTMENT_CHARGES_OFFSET,charges); + SetUInt32Value(ITEM_FIELD_ENCHANTMENT_1_1 + slot*MAX_ENCHANTMENT_OFFSET + ENCHANTMENT_CHARGES_OFFSET,charges); SetState(ITEM_CHANGED); } @@ -793,7 +797,7 @@ void Item::ClearEnchantment(EnchantmentSlot slot) return; for(uint8 x = 0; x < 3; ++x) - SetUInt32Value(ITEM_FIELD_ENCHANTMENT + slot*MAX_ENCHANTMENT_OFFSET + x, 0); + SetUInt32Value(ITEM_FIELD_ENCHANTMENT_1_1 + slot*MAX_ENCHANTMENT_OFFSET + x, 0); SetState(ITEM_CHANGED); } diff --git a/src/game/Item.h b/src/game/Item.h index c1430beab..de0b0c79c 100644 --- a/src/game/Item.h +++ b/src/game/Item.h @@ -146,29 +146,30 @@ enum SellFailure // -1 from client enchantment slot number enum EnchantmentSlot { - PERM_ENCHANTMENT_SLOT = 0, - TEMP_ENCHANTMENT_SLOT = 1, - SOCK_ENCHANTMENT_SLOT = 2, - SOCK_ENCHANTMENT_SLOT_2 = 3, - SOCK_ENCHANTMENT_SLOT_3 = 4, - BONUS_ENCHANTMENT_SLOT = 5, - MAX_INSPECTED_ENCHANTMENT_SLOT = 6, + PERM_ENCHANTMENT_SLOT = 0, + TEMP_ENCHANTMENT_SLOT = 1, + SOCK_ENCHANTMENT_SLOT = 2, + SOCK_ENCHANTMENT_SLOT_2 = 3, + SOCK_ENCHANTMENT_SLOT_3 = 4, + BONUS_ENCHANTMENT_SLOT = 5, + WOTLK_ENCHANTMENT_SLOT = 6, + MAX_INSPECTED_ENCHANTMENT_SLOT = 7, - PROP_ENCHANTMENT_SLOT_0 = 6, // used with RandomSuffix - PROP_ENCHANTMENT_SLOT_1 = 7, // used with RandomSuffix - PROP_ENCHANTMENT_SLOT_2 = 8, // used with RandomSuffix and RandomProperty - PROP_ENCHANTMENT_SLOT_3 = 9, // used with RandomProperty - PROP_ENCHANTMENT_SLOT_4 = 10, // used with RandomProperty - MAX_ENCHANTMENT_SLOT = 11 + PROP_ENCHANTMENT_SLOT_0 = 7, // used with RandomSuffix + PROP_ENCHANTMENT_SLOT_1 = 8, // used with RandomSuffix + PROP_ENCHANTMENT_SLOT_2 = 9, // used with RandomSuffix and RandomProperty + PROP_ENCHANTMENT_SLOT_3 = 10, // used with RandomProperty + PROP_ENCHANTMENT_SLOT_4 = 11, // used with RandomProperty + MAX_ENCHANTMENT_SLOT = 12 }; -#define MAX_VISIBLE_ITEM_OFFSET 16 // 16 fields per visible item (creator(2) + enchantments(12) + properties(1) + pad(1)) +#define MAX_VISIBLE_ITEM_OFFSET 18 // 18 fields per visible item (creator(2) + enchantments(13) + properties(1) + seed(1) + pad(1)) enum EnchantmentOffset { ENCHANTMENT_ID_OFFSET = 0, ENCHANTMENT_DURATION_OFFSET = 1, - ENCHANTMENT_CHARGES_OFFSET = 2 + ENCHANTMENT_CHARGES_OFFSET = 2 // now here not only charges, but something new in wotlk }; #define MAX_ENCHANTMENT_OFFSET 3 @@ -209,6 +210,7 @@ class MANGOS_DLL_SPEC Item : public Object void SetBinding(bool val) { ApplyModFlag(ITEM_FIELD_FLAGS,ITEM_FLAGS_BINDED,val); } bool IsSoulBound() const { return HasFlag(ITEM_FIELD_FLAGS, ITEM_FLAGS_BINDED); } + bool IsAccountBound() const { return HasFlag(ITEM_FIELD_FLAGS, ITEM_FLAGS_BOA); } bool IsBindedNotWith(uint64 guid) const { return IsSoulBound() && GetOwnerGUID()!= guid; } bool IsBoundByEnchant() const; virtual void SaveToDB(); @@ -254,9 +256,9 @@ class MANGOS_DLL_SPEC Item : public Object void SetEnchantmentDuration(EnchantmentSlot slot, uint32 duration); void SetEnchantmentCharges(EnchantmentSlot slot, uint32 charges); void ClearEnchantment(EnchantmentSlot slot); - uint32 GetEnchantmentId(EnchantmentSlot slot) const { return GetUInt32Value(ITEM_FIELD_ENCHANTMENT + slot*MAX_ENCHANTMENT_OFFSET + ENCHANTMENT_ID_OFFSET);} - uint32 GetEnchantmentDuration(EnchantmentSlot slot) const { return GetUInt32Value(ITEM_FIELD_ENCHANTMENT + slot*MAX_ENCHANTMENT_OFFSET + ENCHANTMENT_DURATION_OFFSET);} - uint32 GetEnchantmentCharges(EnchantmentSlot slot) const { return GetUInt32Value(ITEM_FIELD_ENCHANTMENT + slot*MAX_ENCHANTMENT_OFFSET + ENCHANTMENT_CHARGES_OFFSET);} + uint32 GetEnchantmentId(EnchantmentSlot slot) const { return GetUInt32Value(ITEM_FIELD_ENCHANTMENT_1_1 + slot*MAX_ENCHANTMENT_OFFSET + ENCHANTMENT_ID_OFFSET);} + uint32 GetEnchantmentDuration(EnchantmentSlot slot) const { return GetUInt32Value(ITEM_FIELD_ENCHANTMENT_1_1 + slot*MAX_ENCHANTMENT_OFFSET + ENCHANTMENT_DURATION_OFFSET);} + uint32 GetEnchantmentCharges(EnchantmentSlot slot) const { return GetUInt32Value(ITEM_FIELD_ENCHANTMENT_1_1 + slot*MAX_ENCHANTMENT_OFFSET + ENCHANTMENT_CHARGES_OFFSET);} void SendTimeUpdate(Player* owner); void UpdateDuration(Player* owner, uint32 diff); diff --git a/src/game/ItemHandler.cpp b/src/game/ItemHandler.cpp index 7d24fd5a2..795a76deb 100644 --- a/src/game/ItemHandler.cpp +++ b/src/game/ItemHandler.cpp @@ -322,7 +322,7 @@ void WorldSession::HandleItemQuerySingleOpcode( WorldPacket & recv_data ) data << pProto->ItemId; data << pProto->Class; data << pProto->SubClass; - data << uint32(-1); // new 2.0.3, not exist in wdb cache? + data << pProto->Unk0; // new 2.0.3, not exist in wdb cache? data << Name; data << uint8(0x00); //pProto->Name2; // blizz not send name there, just uint8(0x00); <-- \0 = empty string = empty name... data << uint8(0x00); //pProto->Name3; // blizz not send name there, just uint8(0x00); @@ -347,11 +347,14 @@ void WorldSession::HandleItemQuerySingleOpcode( WorldPacket & recv_data ) data << pProto->MaxCount; data << pProto->Stackable; data << pProto->ContainerSlots; - for(int i = 0; i < 10; i++) + data << pProto->StatsCount; // item stats count + for(int i = 0; i < pProto->StatsCount; i++) { data << pProto->ItemStat[i].ItemStatType; data << pProto->ItemStat[i].ItemStatValue; } + data << pProto->ScalingStatDistribution; // scaling stats distribution + data << pProto->ScalingStatValue; // some kind of flags used to determine stat values column for(int i = 0; i < 5; i++) { data << pProto->Damage[i].DamageMin; @@ -435,7 +438,8 @@ void WorldSession::HandleItemQuerySingleOpcode( WorldPacket & recv_data ) data << pProto->GemProperties; data << pProto->RequiredDisenchantSkill; data << pProto->ArmorDamageModifier; - data << uint32(0); // added in 2.4.2.8209, duration (seconds) + data << pProto->Duration; // added in 2.4.2.8209, duration (seconds) + data << pProto->ItemLimitCategory; // WotLK, ItemLimitCategory SendPacket( &data ); } else @@ -843,6 +847,7 @@ void WorldSession::HandleBuyBankSlotOpcode(WorldPacket& /*recvPacket*/) if (_player->GetMoney() < price) return; + _player->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_BUY_BANK_SLOT, slot); _player->SetByteValue(PLAYER_BYTES_2, 2, slot); _player->ModifyMoney(-int32(price)); } diff --git a/src/game/ItemPrototype.h b/src/game/ItemPrototype.h index e3dab0d57..5328308b4 100644 --- a/src/game/ItemPrototype.h +++ b/src/game/ItemPrototype.h @@ -55,10 +55,18 @@ enum ItemModType ITEM_MOD_CRIT_TAKEN_RATING = 34, ITEM_MOD_RESILIENCE_RATING = 35, ITEM_MOD_HASTE_RATING = 36, - ITEM_MOD_EXPERTISE_RATING = 37 + ITEM_MOD_EXPERTISE_RATING = 37, + ITEM_MOD_ATTACK_POWER = 38, + ITEM_MOD_RANGED_ATTACK_POWER = 39, + ITEM_MOD_FERAL_ATTACK_POWER = 40, + ITEM_MOD_SPELL_HEALING_DONE = 41, + ITEM_MOD_SPELL_DAMAGE_DONE = 42, + ITEM_MOD_MANA_REGENERATION = 43, + ITEM_MOD_ARMOR_PENETRATION_RATING = 44, + ITEM_MOD_SPELL_POWER = 45 }; -#define MAX_ITEM_MOD 38 +#define MAX_ITEM_MOD 46 enum ItemSpelltriggerType { @@ -183,10 +191,11 @@ enum ItemClass ITEM_CLASS_QUEST = 12, ITEM_CLASS_KEY = 13, ITEM_CLASS_PERMANENT = 14, - ITEM_CLASS_JUNK = 15 + ITEM_CLASS_MISC = 15, + ITEM_CLASS_GLYPH = 16 }; -#define MAX_ITEM_CLASS 16 +#define MAX_ITEM_CLASS 17 enum ItemSubclassConsumable { @@ -212,10 +221,11 @@ enum ItemSubclassContainer ITEM_SUBCLASS_ENGINEERING_CONTAINER = 4, ITEM_SUBCLASS_GEM_CONTAINER = 5, ITEM_SUBCLASS_MINING_CONTAINER = 6, - ITEM_SUBCLASS_LEATHERWORKING_CONTAINER = 7 + ITEM_SUBCLASS_LEATHERWORKING_CONTAINER = 7, + ITEM_SUBCLASS_INSCRIPTION_CONTAINER = 8 }; -#define MAX_ITEM_SUBCLASS_CONTAINER 8 +#define MAX_ITEM_SUBCLASS_CONTAINER 9 enum ItemSubclassWeapon { @@ -270,10 +280,11 @@ enum ItemSubclassArmor ITEM_SUBCLASS_ARMOR_SHIELD = 6, ITEM_SUBCLASS_ARMOR_LIBRAM = 7, ITEM_SUBCLASS_ARMOR_IDOL = 8, - ITEM_SUBCLASS_ARMOR_TOTEM = 9 + ITEM_SUBCLASS_ARMOR_TOTEM = 9, + ITEM_SUBCLASS_ARMOR_SIGIL = 10 }; -#define MAX_ITEM_SUBCLASS_ARMOR 10 +#define MAX_ITEM_SUBCLASS_ARMOR 11 enum ItemSubclassReagent { @@ -308,10 +319,12 @@ enum ItemSubclassTradeGoods ITEM_SUBCLASS_ELEMENTAL = 10, ITEM_SUBCLASS_TRADE_GOODS_OTHER = 11, ITEM_SUBCLASS_ENCHANTING = 12, - ITEM_SUBCLASS_MATERIAL = 13 // Added in 2.4.2 + ITEM_SUBCLASS_MATERIAL = 13, + ITEM_SUBCLASS_ARMOR_ENCHANTMENT = 14, + ITEM_SUBCLASS_WEAPON_ENCHANTMENT = 15 }; -#define MAX_ITEM_SUBCLASS_TRADE_GOODS 14 +#define MAX_ITEM_SUBCLASS_TRADE_GOODS 16 enum ItemSubclassGeneric { @@ -421,7 +434,8 @@ const uint32 MaxItemSubclassValues[MAX_ITEM_CLASS] = MAX_ITEM_SUBCLASS_QUEST, MAX_ITEM_SUBCLASS_KEY, MAX_ITEM_SUBCLASS_PERMANENT, - MAX_ITEM_SUBCLASS_JUNK + MAX_ITEM_SUBCLASS_JUNK, + MAX_ITEM_SUBCLASS_GLYPH }; inline uint8 ItemSubClassToDurabilityMultiplierId(uint32 ItemClass, uint32 ItemSubClass) @@ -498,7 +512,10 @@ struct ItemPrototype uint32 MaxCount; uint32 Stackable; uint32 ContainerSlots; + uint32 StatsCount; _ItemStat ItemStat[10]; + uint32 ScalingStatDistribution; // id from ScalingStatDistribution.dbc + uint32 ScalingStatValue; // mask for selecting column in ScalingStatValues.dbc _Damage Damage[5]; uint32 Armor; uint32 HolyRes; @@ -534,12 +551,13 @@ struct ItemPrototype uint32 GemProperties; // id from GemProperties.dbc uint32 RequiredDisenchantSkill; float ArmorDamageModifier; + int32 Duration; // negative = realtime, positive = ingame time + uint32 ItemLimitCategory; // id from ItemLimitCategory.dbc uint32 ScriptId; uint32 DisenchantID; uint32 FoodType; uint32 MinMoneyLoot; uint32 MaxMoneyLoot; - int32 Duration; // negative = realtime, positive = ingame time // helpers bool CanChangeEquipStateInCombat() const @@ -561,6 +579,46 @@ struct ItemPrototype return false; } + + uint32 GetScalingStatValuesColumn() const + { + if(ScalingStatValue & 0x00000001) // stat mod + return 0; + if(ScalingStatValue & 0x00000002) // stat mod + return 1; + if(ScalingStatValue & 0x00000004) // stat mod + return 2; + if(ScalingStatValue & 0x00000008) // stat mod + return 3; + if(ScalingStatValue & 0x00000010) // stat mod + return 4; + if(ScalingStatValue & 0x00000020) // armor mod + return 5; + if(ScalingStatValue & 0x00000040) // armor mod + return 6; + if(ScalingStatValue & 0x00000080) // armor mod + return 7; + if(ScalingStatValue & 0x00000100) // armor mod + return 8; + if(ScalingStatValue & 0x00000200) // damage mod + return 9; + if(ScalingStatValue & 0x00000400) // damage mod + return 10; + if(ScalingStatValue & 0x00000800) // damage mod + return 11; + if(ScalingStatValue & 0x00001000) // damage mod + return 12; + if(ScalingStatValue & 0x00002000) // damage mod + return 13; + if(ScalingStatValue & 0x00004000) // damage mod + return 14; + if(ScalingStatValue & 0x00008000) // spell power + return 15; + if(ScalingStatValue & 0x00020000) // feral AP + return 16; + + return 0; + } }; struct ItemLocale diff --git a/src/game/Language.h b/src/game/Language.h index ad5a2b43c..0c2096820 100644 --- a/src/game/Language.h +++ b/src/game/Language.h @@ -326,6 +326,8 @@ enum MangosStrings LANG_CREATURE_NOT_FOLLOW_YOU_NOW = 342, LANG_CREATURE_NON_TAMEABLE = 343, LANG_YOU_ALREADY_HAVE_PET = 344, + LANG_CUSTOMIZE_PLAYER = 345, + LANG_CUSTOMIZE_PLAYER_GUID = 346, // Room for more level 2 345-399 not used // level 3 chat @@ -641,11 +643,30 @@ enum MangosStrings LANG_BG_QUEUE_ANNOUNCE_SELF = 711, LANG_BG_QUEUE_ANNOUNCE_WORLD = 712, + LANG_YOUR_ARENA_LEVEL_REQ_ERROR = 713, - LANG_HIS_ARENA_LEVEL_REQ_ERROR = 714, +// LANG_HIS_ARENA_LEVEL_REQ_ERROR = 714, an opcode exists for this LANG_YOUR_BG_LEVEL_REQ_ERROR = 715, - LANG_YOUR_ARENA_TEAM_FULL = 716, - // Room for BG/ARENA 717-799 not used +// LANG_YOUR_ARENA_TEAM_FULL = 716, an opcode exists for this + + LANG_BG_GROUP_TOO_LARGE = 1122, // "Your group is too large for this battleground. Please regroup to join." + LANG_ARENA_GROUP_TOO_LARGE = 1123, // "Your group is too large for this arena. Please regroup to join." + LANG_ARENA_YOUR_TEAM_ONLY = 1124, // "Your group has members not in your arena team. Please regroup to join." + LANG_ARENA_NOT_ENOUGH_PLAYERS = 1125, // "Your group does not have enough players to join this match." + LANG_ARENA_GOLD_WINS = 1126, // "The Gold Team wins!" + LANG_ARENA_GREEN_WINS = 1127, // "The Green Team wins!" + LANG_BATTLEGROUND_PREMATURE_FINISH_WARNING = 1128, // The battleground will end soon, because there aren't enough players. Get more ppl or win already! + LANG_BG_GROUP_OFFLINE_MEMBER = 1129, // "Your group has an offline member. Please remove him before joining." + LANG_BG_GROUP_MIXED_FACTION = 1130, // "Your group has players from the opposing faction. You can't join the battleground as a group." + LANG_BG_GROUP_MIXED_LEVELS = 1131, // "Your group has players from different battleground brakets. You can't join as group." + LANG_BG_GROUP_MEMBER_ALREADY_IN_QUEUE = 1132, // "Someone in your party is already in this battleground queue. (S)he must leave it before joining as group." + LANG_BG_GROUP_MEMBER_DESERTER = 1133, // "Someone in your party is Deserter. You can't join as group." + LANG_BG_GROUP_MEMBER_NO_FREE_QUEUE_SLOTS = 1134, // "Someone in your party is already in three battleground queues. You cannot join as group." + + LANG_CANNOT_TELE_TO_BG = 1135, // "You cannot teleport to a battleground or arena map." + LANG_CANNOT_SUMMON_TO_BG = 1136, // "You cannot summon players to a battleground or arena map." + LANG_CANNOT_GO_TO_BG_GM = 1137, // "You must be in GM mode to teleport to a player in a battleground." + LANG_CANNOT_GO_TO_BG_FROM_BG = 1138, // "You cannot teleport to a battleground from another battleground. Please leave the current battleground first." // in game strings // = 800, not used diff --git a/src/game/Level1.cpp b/src/game/Level1.cpp index c73231635..26d5b15fe 100644 --- a/src/game/Level1.cpp +++ b/src/game/Level1.cpp @@ -351,7 +351,14 @@ bool ChatHandler::HandleNamegoCommand(const char* args) Map* pMap = m_session->GetPlayer()->GetMap(); - if(pMap->Instanceable()) + if(pMap->IsBattleGroundOrArena()) + { + // cannot summon to bg + PSendSysMessage(LANG_CANNOT_SUMMON_TO_BG,chr->GetName()); + SetSentErrorMessage(true); + return false; + } + else if(pMap->IsDungeon()) { Map* cMap = chr->GetMap(); if( cMap->Instanceable() && cMap->GetInstanceId() != pMap->GetInstanceId() ) @@ -435,6 +442,28 @@ bool ChatHandler::HandleGonameCommand(const char* args) Player *chr = objmgr.GetPlayer(name.c_str()); if (chr) { + Map* cMap = chr->GetMap(); + if(cMap->IsBattleGroundOrArena()) + { + // only allow if gm mode is on + if (!_player->isGameMaster()) + { + PSendSysMessage(LANG_CANNOT_GO_TO_BG_GM,chr->GetName()); + SetSentErrorMessage(true); + return false; + } + // if already in a bg, don't let port to other + else if (_player->GetBattleGroundId()) + { + PSendSysMessage(LANG_CANNOT_GO_TO_BG_FROM_BG,chr->GetName()); + SetSentErrorMessage(true); + return false; + } + // all's well, set bg id + // when porting out from the bg, it will be reset to 0 + _player->SetBattleGroundId(chr->GetBattleGroundId()); + } + else if(cMap->IsDungeon()) Map* cMap = chr->GetMap(); if(cMap->Instanceable()) { diff --git a/src/game/Level2.cpp b/src/game/Level2.cpp index 901d7513b..27ff8c291 100644 --- a/src/game/Level2.cpp +++ b/src/game/Level2.cpp @@ -949,7 +949,7 @@ bool ChatHandler::HandleNpcDeleteCommand(const char* args) else unit = getSelectedCreature(); - if(!unit || unit->isPet() || unit->isTotem()) + if(!unit || unit->isPet() || unit->isTotem() || unit->isVehicle()) { SendSysMessage(LANG_SELECT_CREATURE); SetSentErrorMessage(true); @@ -1062,8 +1062,8 @@ bool ChatHandler::HandleTurnObjectCommand(const char* args) obj->Relocate(obj->GetPositionX(), obj->GetPositionY(), obj->GetPositionZ(), o); obj->SetFloatValue(GAMEOBJECT_FACING, o); - obj->SetFloatValue(GAMEOBJECT_ROTATION+2, rot2); - obj->SetFloatValue(GAMEOBJECT_ROTATION+3, rot3); + obj->SetFloatValue(GAMEOBJECT_PARENTROTATION+2, rot2); + obj->SetFloatValue(GAMEOBJECT_PARENTROTATION+3, rot3); map->Add(obj); @@ -3137,7 +3137,7 @@ bool ChatHandler::HandleWpShowCommand(const char* args) } }while(result->NextRow()); // set "wpguid" column to "empty" - no visual waypoint spawned - WorldDatabase.PExecuteLog("UPDATE creature_movement SET wpguid = '0'"); + WorldDatabase.PExecuteLog("UPDATE creature_movement SET wpguid = '0' WHERE wpguid <> '0'"); if( hasError ) { @@ -3356,6 +3356,59 @@ bool ChatHandler::HandleRenameCommand(const char* args) return true; } +// customize characters +bool ChatHandler::HandleCustomizeCommand(const char* args) +{ + Player* target = NULL; + uint64 targetGUID = 0; + std::string oldname; + + char* px = strtok((char*)args, " "); + + if(px) + { + oldname = px; + + if(!normalizePlayerName(oldname)) + { + SendSysMessage(LANG_PLAYER_NOT_FOUND); + SetSentErrorMessage(true); + return false; + } + + target = objmgr.GetPlayer(oldname.c_str()); + + if (!target) + targetGUID = objmgr.GetPlayerGUIDByName(oldname); + } + + if(!target && !targetGUID) + { + target = getSelectedPlayer(); + } + + if(!target && !targetGUID) + { + SendSysMessage(LANG_PLAYER_NOT_FOUND); + SetSentErrorMessage(true); + return false; + } + + if(target) + { + PSendSysMessage(LANG_CUSTOMIZE_PLAYER, target->GetName()); + target->SetAtLoginFlag(AT_LOGIN_CUSTOMIZE); + CharacterDatabase.PExecute("UPDATE characters SET at_login = at_login | '8' WHERE guid = '%u'", target->GetGUIDLow()); + } + else + { + PSendSysMessage(LANG_CUSTOMIZE_PLAYER_GUID, oldname.c_str(), GUID_LOPART(targetGUID)); + CharacterDatabase.PExecute("UPDATE characters SET at_login = at_login | '8' WHERE guid = '%u'", GUID_LOPART(targetGUID)); + } + + return true; +} + //spawn go bool ChatHandler::HandleGameObjectCommand(const char* args) { @@ -4109,17 +4162,20 @@ bool ChatHandler::HandleNpcTameCommand(const char* /*args*/) player->GetClosePoint (x,y,z,creatureTarget->GetObjectSize (),CONTACT_DISTANCE); pet->Relocate (x,y,z,M_PI-player->GetOrientation ()); - // set pet to defensive mode by default (some classes can't control contolled pets in fact). + // set pet to defensive mode by default (some classes can't control controlled pets in fact). pet->GetCharmInfo()->SetReactState(REACT_DEFENSIVE); + // calculate proper level + uint32 level = (creatureTarget->getLevel() < (player->getLevel() - 5)) ? (player->getLevel() - 5) : creatureTarget->getLevel(); + // prepare visual effect for levelup - pet->SetUInt32Value(UNIT_FIELD_LEVEL,creatureTarget->getLevel()-1); + pet->SetUInt32Value(UNIT_FIELD_LEVEL, level - 1); // add to world pet->GetMap()->Add((Creature*)pet); // visual effect for levelup - pet->SetUInt32Value(UNIT_FIELD_LEVEL,creatureTarget->getLevel()); + pet->SetUInt32Value(UNIT_FIELD_LEVEL, level); // caster have pet now player->SetPet(pet); diff --git a/src/game/Level3.cpp b/src/game/Level3.cpp index 4b6372f53..09af98247 100644 --- a/src/game/Level3.cpp +++ b/src/game/Level3.cpp @@ -47,6 +47,7 @@ #include "Config/ConfigEnv.h" #include "Util.h" #include "ItemEnchantmentMgr.h" +#include "BattleGroundMgr.h" #include "InstanceSaveMgr.h" #include "InstanceData.h" @@ -294,6 +295,15 @@ bool ChatHandler::HandleReloadLootTemplatesItemCommand(const char*) return true; } +bool ChatHandler::HandleReloadLootTemplatesMillingCommand(const char*) +{ + sLog.outString( "Re-Loading Loot Tables... (`milling_loot_template`)" ); + LoadLootTemplates_Milling(); + LootTemplates_Milling.CheckLootRefs(); + SendGlobalSysMessage("DB table `milling_loot_template` reloaded."); + return true; +} + bool ChatHandler::HandleReloadLootTemplatesPickpocketingCommand(const char*) { sLog.outString( "Re-Loading Loot Tables... (`pickpocketing_loot_template`)" ); @@ -3805,8 +3815,8 @@ bool ChatHandler::HandleLevelUpCommand(const char* args) int32 newlevel = oldlevel + addlevel; if(newlevel < 1) newlevel = 1; - if(newlevel > 255) // hardcoded maximum level - newlevel = 255; + if(newlevel > STRONG_MAX_LEVEL) // hardcoded maximum level + newlevel = STRONG_MAX_LEVEL; if(chr) { @@ -4349,7 +4359,7 @@ static bool HandleResetStatsOrLevelHelper(Player* player) // set UNIT_FIELD_BYTES_1 to init state but preserve m_form value player->SetUInt32Value(UNIT_FIELD_BYTES_1, unitfield); - player->SetByteValue(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_UNK3 | UNIT_BYTE2_FLAG_UNK5 ); + player->SetByteValue(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_PVP ); player->SetByteValue(UNIT_FIELD_BYTES_2, 3, player->m_form); player->SetUInt32Value(UNIT_FIELD_FLAGS, UNIT_FLAG_PVP_ATTACKABLE); @@ -4394,6 +4404,7 @@ bool ChatHandler::HandleResetLevelCommand(const char * args) player->SetLevel(1); player->InitStatsForLevel(true); player->InitTaxiNodesForLevel(); + player->InitGlyphsForLevel(); player->InitTalentForLevel(); player->SetUInt32Value(PLAYER_XP,0); @@ -4437,6 +4448,7 @@ bool ChatHandler::HandleResetStatsCommand(const char * args) player->InitStatsForLevel(true); player->InitTaxiNodesForLevel(); + player->InitGlyphsForLevel(); player->InitTalentForLevel(); return true; @@ -4564,7 +4576,7 @@ bool ChatHandler::HandleResetAllCommand(const char * args) return false; } - CharacterDatabase.PExecute("UPDATE characters SET at_login = at_login | '%u'",atLogin); + CharacterDatabase.PExecute("UPDATE characters SET at_login = at_login | '%u' WHERE (at_login & '%u') = '0'",atLogin,atLogin); HashMapHolder::MapType const& plist = ObjectAccessor::Instance().GetPlayers(); for(HashMapHolder::MapType::const_iterator itr = plist.begin(); itr != plist.end(); ++itr) itr->second->SetAtLoginFlag(atLogin); @@ -6479,6 +6491,12 @@ bool ChatHandler::HandleSendMessageCommand(const char* args) return true; } +bool ChatHandler::HandleFlushArenaPointsCommand(const char * /*args*/) +{ + sBattleGroundMgr.DistributeArenaPoints(); + return true; +} + bool ChatHandler::HandleModifyGenderCommand(const char *args) { if(!*args) @@ -6493,30 +6511,27 @@ bool ChatHandler::HandleModifyGenderCommand(const char *args) return false; } + PlayerInfo const* info = objmgr.GetPlayerInfo(player->getRace(), player->getClass()); + if(!info) + return false; + char const* gender_str = (char*)args; int gender_len = strlen(gender_str); - uint32 displayId = player->GetNativeDisplayId(); - char const* gender_full = NULL; - uint32 new_displayId = displayId; Gender gender; - if(!strncmp(gender_str,"male",gender_len)) // MALE + if(!strncmp(gender_str, "male", gender_len)) // MALE { if(player->getGender() == GENDER_MALE) return true; - gender_full = "male"; - new_displayId = player->getRace() == RACE_BLOODELF ? displayId+1 : displayId-1; gender = GENDER_MALE; } - else if (!strncmp(gender_str,"female",gender_len)) // FEMALE + else if (!strncmp(gender_str, "female", gender_len)) // FEMALE { if(player->getGender() == GENDER_FEMALE) return true; - gender_full = "female"; - new_displayId = player->getRace() == RACE_BLOODELF ? displayId-1 : displayId+1; gender = GENDER_FEMALE; } else @@ -6528,13 +6543,18 @@ bool ChatHandler::HandleModifyGenderCommand(const char *args) // Set gender player->SetByteValue(UNIT_FIELD_BYTES_0, 2, gender); + player->SetByteValue(PLAYER_BYTES_3, 0, gender); // Change display ID - player->SetDisplayId(new_displayId); - player->SetNativeDisplayId(new_displayId); + player->SetDisplayId(gender ? info->displayId_f : info->displayId_m); + player->SetNativeDisplayId(gender ? info->displayId_f : info->displayId_m); + + char const* gender_full = gender ? "female" : "male"; + + PSendSysMessage(LANG_YOU_CHANGE_GENDER, player->GetName(), gender_full); - PSendSysMessage(LANG_YOU_CHANGE_GENDER, player->GetName(),gender_full); if (needReportToTarget(player)) - ChatHandler(player).PSendSysMessage(LANG_YOUR_GENDER_CHANGED, gender_full,GetName()); + ChatHandler(player).PSendSysMessage(LANG_YOUR_GENDER_CHANGED, gender_full, GetName()); + return true; } diff --git a/src/game/LootHandler.cpp b/src/game/LootHandler.cpp index 97314423f..f9c26fd29 100644 --- a/src/game/LootHandler.cpp +++ b/src/game/LootHandler.cpp @@ -142,6 +142,7 @@ void WorldSession::HandleAutostoreLootItemOpcode( WorldPacket & recv_data ) --loot->unlootedCount; player->SendNewItem(newitem, uint32(item->count), false, false, true); + player->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_LOOT_ITEM, item->itemid, item->count); } else player->SendEquipError( msg, NULL, NULL ); @@ -314,7 +315,7 @@ void WorldSession::DoLootRelease( uint64 lguid ) int32 ReqValue = 175; LockEntry const *lockInfo = sLockStore.LookupEntry(go->GetGOInfo()->chest.lockId); if(lockInfo) - ReqValue = lockInfo->requiredminingskill; + ReqValue = lockInfo->Skill[0]; float skill = float(player->GetSkillValue(SKILL_MINING))/(ReqValue+25); double chance = pow(0.8*chance_rate,4*(1/double(max_amount))*double(uses)); if(roll_chance_f(100*chance+skill)) @@ -483,6 +484,7 @@ void WorldSession::HandleLootMasterGiveOpcode( WorldPacket & recv_data ) // not move item from loot to target inventory Item * newitem = target->StoreNewItem( dest, item.itemid, true, item.randomPropertyId ); target->SendNewItem(newitem, uint32(item.count), false, false, true ); + target->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_LOOT_ITEM, item.itemid, item.count); // mark as looted item.count=0; diff --git a/src/game/LootMgr.cpp b/src/game/LootMgr.cpp index 44e9d5982..a559b7b6f 100644 --- a/src/game/LootMgr.cpp +++ b/src/game/LootMgr.cpp @@ -39,6 +39,7 @@ LootStore LootTemplates_Disenchant( "disenchant_loot_template", "item disenc LootStore LootTemplates_Fishing( "fishing_loot_template", "area id"); LootStore LootTemplates_Gameobject( "gameobject_loot_template", "gameobject entry"); LootStore LootTemplates_Item( "item_loot_template", "item entry"); +LootStore LootTemplates_Milling( "milling_loot_template", "item entry"); LootStore LootTemplates_Pickpocketing("pickpocketing_loot_template","creature pickpocket lootid"); LootStore LootTemplates_Prospecting( "prospecting_loot_template", "item entry"); LootStore LootTemplates_QuestMail( "quest_mail_loot_template", "quest id"); @@ -1135,6 +1136,21 @@ void LoadLootTemplates_Item() LootTemplates_Item.ReportUnusedIds(ids_set); } +void LoadLootTemplates_Milling() +{ + LootIdSet ids_set; + LootTemplates_Milling.LoadAndCollectLootIds(ids_set); + + // remove real entries and check existence loot + for(uint32 i = 1; i < sItemStorage.MaxEntry; ++i ) + if(ItemPrototype const* proto = sItemStorage.LookupEntry(i)) + if(ids_set.count(proto->ItemId)) + ids_set.erase(proto->ItemId); + + // output error for any still listed (not referenced from appropriate table) ids + LootTemplates_Milling.ReportUnusedIds(ids_set); +} + void LoadLootTemplates_Pickpocketing() { LootIdSet ids_set, ids_setUsed; @@ -1227,6 +1243,7 @@ void LoadLootTemplates_Reference() LootTemplates_Fishing.CheckLootRefs(&ids_set); LootTemplates_Gameobject.CheckLootRefs(&ids_set); LootTemplates_Item.CheckLootRefs(&ids_set); + LootTemplates_Milling.CheckLootRefs(&ids_set); LootTemplates_Pickpocketing.CheckLootRefs(&ids_set); LootTemplates_Skinning.CheckLootRefs(&ids_set); LootTemplates_Disenchant.CheckLootRefs(&ids_set); diff --git a/src/game/LootMgr.h b/src/game/LootMgr.h index 3c5020f53..4d218f2df 100644 --- a/src/game/LootMgr.h +++ b/src/game/LootMgr.h @@ -295,6 +295,7 @@ extern LootStore LootTemplates_Creature; extern LootStore LootTemplates_Fishing; extern LootStore LootTemplates_Gameobject; extern LootStore LootTemplates_Item; +extern LootStore LootTemplates_Milling; extern LootStore LootTemplates_Pickpocketing; extern LootStore LootTemplates_Skinning; extern LootStore LootTemplates_Disenchant; @@ -305,6 +306,7 @@ void LoadLootTemplates_Creature(); void LoadLootTemplates_Fishing(); void LoadLootTemplates_Gameobject(); void LoadLootTemplates_Item(); +void LoadLootTemplates_Milling(); void LoadLootTemplates_Pickpocketing(); void LoadLootTemplates_Skinning(); void LoadLootTemplates_Disenchant(); @@ -318,6 +320,7 @@ inline void LoadLootTables() LoadLootTemplates_Fishing(); LoadLootTemplates_Gameobject(); LoadLootTemplates_Item(); + LoadLootTemplates_Milling(); LoadLootTemplates_Pickpocketing(); LoadLootTemplates_Skinning(); LoadLootTemplates_Disenchant(); diff --git a/src/game/Mail.cpp b/src/game/Mail.cpp index 06499d15b..1bca38aac 100644 --- a/src/game/Mail.cpp +++ b/src/game/Mail.cpp @@ -352,7 +352,7 @@ void WorldSession::HandleReturnToSender(WorldPacket & recv_data ) pl->SendMailResult(mailId, MAIL_RETURNED_TO_SENDER, 0); } -void WorldSession::SendReturnToSender(uint8 messageType, uint32 sender_acc, uint32 sender_guid, uint32 receiver_guid, std::string subject, uint32 itemTextId, MailItemsInfo *mi, uint32 money, uint16 mailTemplateId ) +void WorldSession::SendReturnToSender(uint8 messageType, uint32 sender_acc, uint32 sender_guid, uint32 receiver_guid, const std::string& subject, uint32 itemTextId, MailItemsInfo *mi, uint32 money, uint16 mailTemplateId ) { if(messageType != MAIL_NORMAL) // return only to players { @@ -591,7 +591,7 @@ void WorldSession::HandleGetMail(WorldPacket & recv_data ) data << (uint32) (*itr)->mailTemplateId; // mail template (MailTemplate.dbc) data << (*itr)->subject; // Subject string - once 00, when mail type = 3 - data << (uint8) item_count; + data << (uint8) item_count; // client limit is 0x10 for(uint8 i = 0; i < item_count; ++i) { @@ -602,7 +602,7 @@ void WorldSession::HandleGetMail(WorldPacket & recv_data ) data << (uint32) (item ? item->GetGUIDLow() : 0); // entry data << (uint32) (item ? item->GetEntry() : 0); - for(uint8 j = 0; j < 6; ++j) + for(uint8 j = 0; j < 7; ++j) { // unsure data << (uint32) (item ? item->GetEnchantmentCharges((EnchantmentSlot)j) : 0); @@ -616,13 +616,15 @@ void WorldSession::HandleGetMail(WorldPacket & recv_data ) // unk data << (uint32) (item ? item->GetItemSuffixFactor() : 0); // stack count - data << (uint8) (item ? item->GetCount() : 0); + data << (uint32) (item ? item->GetCount() : 0); // charges data << (uint32) (item ? item->GetSpellCharges() : 0); // durability data << (uint32) (item ? item->GetUInt32Value(ITEM_FIELD_MAXDURABILITY) : 0); // durability data << (uint32) (item ? item->GetUInt32Value(ITEM_FIELD_DURABILITY) : 0); + // unknown wotlk + data << (uint8) 0; } mails_count += 1; diff --git a/src/game/Makefile.am b/src/game/Makefile.am index d099b35d7..5f5ce4542 100644 --- a/src/game/Makefile.am +++ b/src/game/Makefile.am @@ -30,6 +30,8 @@ noinst_LIBRARIES = libmangosgame.a libmangosgame_a_SOURCES = \ AccountMgr.cpp \ AccountMgr.h \ + AchievementMgr.h \ + AchievementMgr.cpp \ AddonHandler.cpp \ AddonHandler.h \ AggressorAI.cpp \ @@ -63,6 +65,9 @@ libmangosgame_a_SOURCES = \ BattleGroundHandler.cpp \ BattleGroundMgr.cpp \ BattleGroundMgr.h \ + Calendar.cpp \ + Calendar.h \ + CalendarHandler.cpp \ Cell.h \ CellImpl.h \ Channel.cpp \ @@ -246,6 +251,8 @@ libmangosgame_a_SOURCES = \ UpdateData.h \ UpdateFields.h \ UpdateMask.h \ + Vehicle.cpp \ + Vehicle.h \ VoiceChatHandler.cpp \ WaypointManager.cpp \ WaypointManager.h \ diff --git a/src/game/Map.cpp b/src/game/Map.cpp index b1cb12720..d2f8c06a9 100644 --- a/src/game/Map.cpp +++ b/src/game/Map.cpp @@ -43,7 +43,7 @@ #define MAX_GRID_LOAD_TIME 50 // magic *.map header -const char MAP_MAGIC[] = "MAP_2.00"; +const char MAP_MAGIC[] = "MAP_2.01"; GridState* si_GridStates[MAX_GRID_STATE]; @@ -254,7 +254,7 @@ template<> void Map::AddToGrid(Creature* obj, NGridType *grid, Cell const& cell) { // add to world object registry in grid - if(obj->isPet()) + if(obj->isPet() || obj->isVehicle()) { (*grid)(cell.CellX(), cell.CellY()).AddWorldObject(obj, obj->GetGUID()); obj->SetCurrentCell(cell); @@ -298,7 +298,7 @@ template<> void Map::RemoveFromGrid(Creature* obj, NGridType *grid, Cell const& cell) { // remove from world object registry in grid - if(obj->isPet()) + if(obj->isPet() || obj->isVehicle()) { (*grid)(cell.CellX(), cell.CellY()).RemoveWorldObject(obj, obj->GetGUID()); } diff --git a/src/game/Map.h b/src/game/Map.h index 1fe978754..70137a614 100644 --- a/src/game/Map.h +++ b/src/game/Map.h @@ -221,6 +221,17 @@ class MANGOS_DLL_SPEC Map : public GridRefManager, public MaNGOS::Obj bool IsBattleGround() const { return i_mapEntry && i_mapEntry->IsBattleGround(); } bool IsBattleArena() const { return i_mapEntry && i_mapEntry->IsBattleArena(); } bool IsBattleGroundOrArena() const { return i_mapEntry && i_mapEntry->IsBattleGroundOrArena(); } + bool GetEntrancePos(int32 &mapid, float &x, float &y) + { + if(!i_mapEntry) + return false; + if(i_mapEntry->entrance_map < 0) + return false; + mapid = i_mapEntry->entrance_map; + x = i_mapEntry->entrance_x; + y = i_mapEntry->entrance_y; + return true; + } void AddObjectToRemoveList(WorldObject *obj); void DoDelayedMovesAndRemoves(); diff --git a/src/game/MapInstanced.cpp b/src/game/MapInstanced.cpp index 8037e907d..37ce4522a 100644 --- a/src/game/MapInstanced.cpp +++ b/src/game/MapInstanced.cpp @@ -141,7 +141,17 @@ Map* MapInstanced::GetInstance(const WorldObject* obj) uint32 NewInstanceId = 0; // instanceId of the resulting map Player* player = (Player*)obj; - // TODO: battlegrounds and arenas + if(IsBattleGroundOrArena()) + { + // instantiate or find existing bg map for player + // the instance id is set in battlegroundid + NewInstanceId = player->GetBattleGroundId(); + assert(NewInstanceId); + map = _FindMap(NewInstanceId); + if(!map) + map = CreateBattleGround(NewInstanceId); + return map; + } InstancePlayerBind *pBind = player->GetBoundInstance(GetId(), player->GetDifficulty()); InstanceSave *pSave = pBind ? pBind->save : NULL; diff --git a/src/game/MapManager.cpp b/src/game/MapManager.cpp index 8833b8322..03f080dd9 100644 --- a/src/game/MapManager.cpp +++ b/src/game/MapManager.cpp @@ -107,7 +107,7 @@ MapManager::_GetBaseMap(uint32 id) Guard guard(*this); const MapEntry* entry = sMapStore.LookupEntry(id); - if (entry && entry->IsDungeon()) + if (entry && entry->Instanceable()) { m = new MapInstanced(id, i_gridCleanUpDelay); } @@ -173,7 +173,8 @@ bool MapManager::CanPlayerEnter(uint32 mapid, Player* player) //The player has a heroic mode and tries to enter into instance which has no a heroic mode if (!entry->SupportsHeroicMode() && player->GetDifficulty() == DIFFICULTY_HEROIC) { - player->SendTransferAborted(mapid, TRANSFER_ABORT_DIFFICULTY2); //Send aborted message + //Send aborted message + player->SendTransferAborted(mapid, TRANSFER_ABORT_DIFFICULTY, DIFFICULTY_HEROIC); return false; } @@ -278,7 +279,8 @@ bool MapManager::ExistMapAndVMap(uint32 mapid, float x,float y) bool MapManager::IsValidMAP(uint32 mapid) { MapEntry const* mEntry = sMapStore.LookupEntry(mapid); - return mEntry && (!mEntry->Instanceable() || objmgr.GetInstanceTemplate(mapid)); + return mEntry && (!mEntry->IsDungeon() || objmgr.GetInstanceTemplate(mapid)); + // TODO: add check for battleground template } void MapManager::LoadGrid(int mapid, float x, float y, const WorldObject* obj, bool no_unload) diff --git a/src/game/MiscHandler.cpp b/src/game/MiscHandler.cpp index b2c7d7d5a..885af56fc 100644 --- a/src/game/MiscHandler.cpp +++ b/src/game/MiscHandler.cpp @@ -41,6 +41,7 @@ #include "SpellAuras.h" #include "Pet.h" #include "SocialMgr.h" +#include "Tools.h" void WorldSession::HandleRepopRequestOpcode( WorldPacket & /*recv_data*/ ) { @@ -80,7 +81,7 @@ void WorldSession::HandleWhoOpcode( WorldPacket & recv_data ) std::string player_name, guild_name; recv_data >> level_min; // maximal player level, default 0 - recv_data >> level_max; // minimal player level, default 100 + recv_data >> level_max; // minimal player level, default 100 (MAX_LEVEL) recv_data >> player_name; // player name, case sensitive... // recheck @@ -145,8 +146,8 @@ void WorldSession::HandleWhoOpcode( WorldPacket & recv_data ) // client send in case not set max level value 100 but mangos support 255 max level, // update it to show GMs with characters after 100 level - if(level_max >= 100) - level_max = 255; + if(level_max >= MAX_LEVEL) + level_max = STRONG_MAX_LEVEL; uint32 team = _player->GetTeam(); uint32 security = GetSecurity(); @@ -306,7 +307,7 @@ void WorldSession::HandleLogoutRequestOpcode( WorldPacket & /*recv_data*/ ) data.append(GetPlayer()->GetPackGUID()); data << (uint32)2; SendPacket( &data ); - GetPlayer()->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_ROTATE); + GetPlayer()->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_STUNNED); } WorldPacket data( SMSG_LOGOUT_RESPONSE, 5 ); @@ -343,7 +344,7 @@ void WorldSession::HandleLogoutCancelOpcode( WorldPacket & /*recv_data*/ ) GetPlayer()->SetStandState(PLAYER_STATE_NONE); //! DISABLE_ROTATE - GetPlayer()->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_ROTATE); + GetPlayer()->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_STUNNED); } sLog.outDebug( "WORLD: sent SMSG_LOGOUT_CANCEL_ACK Message" ); @@ -357,10 +358,12 @@ void WorldSession::HandleTogglePvP( WorldPacket & recv_data ) bool newPvPStatus; recv_data >> newPvPStatus; GetPlayer()->ApplyModFlag(PLAYER_FLAGS, PLAYER_FLAGS_IN_PVP, newPvPStatus); + GetPlayer()->ApplyModFlag(PLAYER_FLAGS, PLAYER_FLAGS_PVP_TIMER, !newPvPStatus); } else { GetPlayer()->ToggleFlag(PLAYER_FLAGS, PLAYER_FLAGS_IN_PVP); + GetPlayer()->ToggleFlag(PLAYER_FLAGS, PLAYER_FLAGS_PVP_TIMER); } if(GetPlayer()->HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_IN_PVP)) @@ -866,7 +869,7 @@ void WorldSession::HandleAreaTriggerOpcode(WorldPacket & recv_data) if(missingItem) SendAreaTriggerMessage(GetMangosString(LANG_LEVEL_MINREQUIRED_AND_ITEM), at->requiredLevel, objmgr.GetItemPrototype(missingItem)->Name1); else if(missingKey) - GetPlayer()->SendTransferAborted(at->target_mapId, TRANSFER_ABORT_DIFFICULTY2); + GetPlayer()->SendTransferAborted(at->target_mapId, TRANSFER_ABORT_DIFFICULTY, DIFFICULTY_HEROIC); else if(missingQuest) SendAreaTriggerMessage(at->requiredFailedText.c_str()); else if(missingLevel) @@ -878,16 +881,96 @@ void WorldSession::HandleAreaTriggerOpcode(WorldPacket & recv_data) GetPlayer()->TeleportTo(at->target_mapId,at->target_X,at->target_Y,at->target_Z,at->target_Orientation,TELE_TO_NOT_LEAVE_TRANSPORT); } -void WorldSession::HandleUpdateAccountData(WorldPacket &/*recv_data*/) +void WorldSession::HandleUpdateAccountData(WorldPacket &recv_data) { sLog.outDetail("WORLD: Received CMSG_UPDATE_ACCOUNT_DATA"); - //recv_data.hexlike(); + + CHECK_PACKET_SIZE(recv_data, 4+4+4); + + uint32 type, timestamp, decompressedSize; + recv_data >> type >> timestamp >> decompressedSize; + + sLog.outDebug("UAD: type %u, time %u, decompressedSize %u", type, timestamp, decompressedSize); + + if(type > NUM_ACCOUNT_DATA_TYPES) + return; + + if(decompressedSize == 0) // erase + { + SetAccountData(type, timestamp, ""); + + WorldPacket data(SMSG_UPDATE_ACCOUNT_DATA_COMPLETE, 4+4); + data << uint32(type); + data << uint32(0); + SendPacket(&data); + + return; + } + + if(decompressedSize > 0xFFFF) + { + sLog.outError("UAD: Account data packet too big, size %u", decompressedSize); + return; + } + + ByteBuffer dest; + dest.resize(decompressedSize); + + uLongf realSize = decompressedSize; + if(uncompress(const_cast(dest.contents()), &realSize, const_cast(recv_data.contents() + recv_data.rpos()), recv_data.size() - recv_data.rpos()) != Z_OK) + { + sLog.outError("UAD: Failed to decompress account data"); + return; + } + + std::string adata; + dest >> adata; + + SetAccountData(type, timestamp, adata); + + WorldPacket data(SMSG_UPDATE_ACCOUNT_DATA_COMPLETE, 4+4); + data << uint32(type); + data << uint32(0); + SendPacket(&data); } -void WorldSession::HandleRequestAccountData(WorldPacket& /*recv_data*/) +void WorldSession::HandleRequestAccountData(WorldPacket& recv_data) { sLog.outDetail("WORLD: Received CMSG_REQUEST_ACCOUNT_DATA"); - //recv_data.hexlike(); + + CHECK_PACKET_SIZE(recv_data, 4); + + uint32 type; + recv_data >> type; + + sLog.outDebug("RAD: type %u", type); + + if(type > NUM_ACCOUNT_DATA_TYPES) + return; + + AccountData *adata = GetAccountData(type); + + uint32 size = adata->Data.size(); + + ByteBuffer dest; + dest.resize(size); + + uLongf destSize = size; + if(compress(const_cast(dest.contents()), &destSize, (uint8*)adata->Data.c_str(), size) != Z_OK) + { + sLog.outDebug("RAD: Failed to compress account data"); + return; + } + + dest.resize(destSize); + + WorldPacket data (SMSG_UPDATE_ACCOUNT_DATA, 8+4+4+4+destSize); + data << uint64(_player->GetGUID()); // player guid + data << uint32(type); // type (0-7) + data << uint32(adata->Time); // unix time + data << uint32(size); // decompressed length + data.append(dest); // compressed data + SendPacket(&data); } void WorldSession::HandleSetActionButtonOpcode(WorldPacket& recv_data) @@ -1406,11 +1489,11 @@ void WorldSession::HandleChooseTitleOpcode( WorldPacket & recv_data ) GetPlayer()->SetUInt32Value(PLAYER_CHOSEN_TITLE, title); } -void WorldSession::HandleAllowMoveAckOpcode( WorldPacket & recv_data ) +void WorldSession::HandleTimeSyncResp( WorldPacket & recv_data ) { CHECK_PACKET_SIZE(recv_data, 4+4); - sLog.outDebug("CMSG_ALLOW_MOVE_ACK"); + sLog.outDebug("CMSG_TIME_SYNC_RESP"); uint32 counter, time_; recv_data >> counter >> time_; @@ -1480,26 +1563,6 @@ void WorldSession::HandleDungeonDifficultyOpcode( WorldPacket & recv_data ) } } -void WorldSession::HandleNewUnknownOpcode( WorldPacket & recv_data ) -{ - sLog.outDebug("New Unknown Opcode %u", recv_data.GetOpcode()); - recv_data.hexlike(); - /* - New Unknown Opcode 837 - STORAGE_SIZE: 60 - 02 00 00 00 00 00 00 00 | 00 00 00 00 01 20 00 00 - 89 EB 33 01 71 5C 24 C4 | 15 03 35 45 74 47 8B 42 - BA B8 1B 40 00 00 00 00 | 00 00 00 00 77 66 42 BF - 23 91 26 3F 00 00 60 41 | 00 00 00 00 - - New Unknown Opcode 837 - STORAGE_SIZE: 44 - 02 00 00 00 00 00 00 00 | 00 00 00 00 00 00 80 00 - 7B 80 34 01 84 EA 2B C4 | 5F A1 36 45 C9 39 1C 42 - BA B8 1B 40 CE 06 00 00 | 00 00 80 3F - */ -} - void WorldSession::HandleDismountOpcode( WorldPacket & /*recv_data*/ ) { sLog.outDebug("WORLD: CMSG_CANCEL_MOUNT_AURA"); @@ -1566,3 +1629,32 @@ void WorldSession::HandleSetTaxiBenchmarkOpcode( WorldPacket & recv_data ) sLog.outDebug("Client used \"/timetest %d\" command", mode); } + +void WorldSession::HandleSpellClick( WorldPacket & recv_data ) +{ + CHECK_PACKET_SIZE(recv_data, 8); + + uint64 guid; + recv_data >> guid; + + Vehicle *vehicle = ObjectAccessor::GetVehicle(guid); + + if(!vehicle) + return; + + _player->EnterVehicle(vehicle); +} + +void WorldSession::HandleInspectAchievements( WorldPacket & recv_data ) +{ + CHECK_PACKET_SIZE(recv_data, 1); + uint64 guid; + if(!readGUID(recv_data, guid)) + return; + + Player *player = objmgr.GetPlayer(guid); + if(!player) + return; + + player->GetAchievementMgr().SendRespondInspectAchievements(_player); +} diff --git a/src/game/MotionMaster.cpp b/src/game/MotionMaster.cpp index 2dc42cd4d..23beef949 100644 --- a/src/game/MotionMaster.cpp +++ b/src/game/MotionMaster.cpp @@ -150,8 +150,17 @@ MotionMaster::MoveTargetedHome() } else if(i_owner->GetTypeId()==TYPEID_UNIT && ((Creature*)i_owner)->GetCharmerOrOwnerGUID()) { - sLog.outError("Pet or controlled creature (Entry: %u GUID: %u) attempt targeted home", + DEBUG_LOG("Pet or controlled creature (Entry: %u GUID: %u) targeting home", i_owner->GetEntry(), i_owner->GetGUIDLow() ); + Unit *target = ((Creature*)i_owner)->GetCharmerOrOwner(); + if(target) + { + i_owner->addUnitState(UNIT_STAT_FOLLOW); + DEBUG_LOG("Following %s (GUID: %u)", + target->GetTypeId()==TYPEID_PLAYER ? "player" : "creature", + target->GetTypeId()==TYPEID_PLAYER ? target->GetGUIDLow() : ((Creature*)target)->GetDBTableGUIDLow() ); + Mutate(new TargetedMovementGenerator(*target,PET_FOLLOW_DIST,PET_FOLLOW_ANGLE)); + } } else { diff --git a/src/game/MovementHandler.cpp b/src/game/MovementHandler.cpp index 922b39e50..8d34e7ec7 100644 --- a/src/game/MovementHandler.cpp +++ b/src/game/MovementHandler.cpp @@ -130,22 +130,28 @@ void WorldSession::HandleMoveWorldportAckOpcode() _player->RemoveSpellsCausingAura(SPELL_AURA_MOUNTED); // battleground state prepare - if(_player->InBattleGround()) + // only add to bg group and object, if the player was invited (else he entered through command) + if(_player->InBattleGround() && _player->IsInvitedForBattleGroundInstance(_player->GetBattleGroundId())) { BattleGround *bg = _player->GetBattleGround(); if(bg) { + bg->AddPlayer(_player); if(bg->GetMapId() == _player->GetMapId()) // we teleported to bg { - if(!bg->GetBgRaid(_player->GetTeam())) // first player joined + // get the team this way, because arenas might 'override' the teams. + uint32 team = bg->GetPlayerTeam(_player->GetGUID()); + if(!team) + team = _player->GetTeam(); + if(!bg->GetBgRaid(team)) // first player joined { Group *group = new Group; - bg->SetBgRaid(_player->GetTeam(), group); + bg->SetBgRaid(team, group); group->Create(_player->GetGUIDLow(), _player->GetName()); } else // raid already exist { - bg->GetBgRaid(_player->GetTeam())->AddMember(_player->GetGUID(), _player->GetName()); + bg->GetBgRaid(team)->AddMember(_player->GetGUID(), _player->GetName()); } } } @@ -170,70 +176,15 @@ void WorldSession::HandleMoveWorldportAckOpcode() void WorldSession::HandleMovementOpcodes( WorldPacket & recv_data ) { - CHECK_PACKET_SIZE(recv_data, 4+1+4+4+4+4+4); + uint32 opcode = recv_data.GetOpcode(); + sLog.outDebug("WORLD: Recvd %s (%u, 0x%X) opcode", LookupOpcodeName(opcode), opcode, opcode); if(GetPlayer()->GetDontMove()) return; /* extract packet */ MovementInfo movementInfo; - uint32 MovementFlags; - - recv_data >> MovementFlags; - recv_data >> movementInfo.unk1; - recv_data >> movementInfo.time; - recv_data >> movementInfo.x; - recv_data >> movementInfo.y; - recv_data >> movementInfo.z; - recv_data >> movementInfo.o; - - //Save movement flags - _player->SetUnitMovementFlags(MovementFlags); - - if(MovementFlags & MOVEMENTFLAG_ONTRANSPORT) - { - // recheck - CHECK_PACKET_SIZE(recv_data, recv_data.rpos()+8+4+4+4+4+4); - - recv_data >> movementInfo.t_guid; - recv_data >> movementInfo.t_x; - recv_data >> movementInfo.t_y; - recv_data >> movementInfo.t_z; - recv_data >> movementInfo.t_o; - recv_data >> movementInfo.t_time; - } - - if(MovementFlags & (MOVEMENTFLAG_SWIMMING | MOVEMENTFLAG_FLYING2)) - { - // recheck - CHECK_PACKET_SIZE(recv_data, recv_data.rpos()+4); - - recv_data >> movementInfo.s_pitch; // pitch, -1.55=looking down, 0=looking straight forward, +1.55=looking up - } - - // recheck - CHECK_PACKET_SIZE(recv_data, recv_data.rpos()+4); - - recv_data >> movementInfo.fallTime; // duration of last jump (when in jump duration from jump begin to now) - - if(MovementFlags & MOVEMENTFLAG_JUMPING) - { - // recheck - CHECK_PACKET_SIZE(recv_data, recv_data.rpos()+4+4+4+4); - - recv_data >> movementInfo.j_unk; // constant, but different when jumping in water and on land? - recv_data >> movementInfo.j_sinAngle; // sin of angle between orientation0 and players orientation - recv_data >> movementInfo.j_cosAngle; // cos of angle between orientation0 and players orientation - recv_data >> movementInfo.j_xyspeed; // speed of xy movement - } - - if(MovementFlags & MOVEMENTFLAG_SPLINE) - { - // recheck - CHECK_PACKET_SIZE(recv_data, recv_data.rpos()+4); - - recv_data >> movementInfo.u_unk1; // unknown - } + ReadMovementInfo(recv_data, &movementInfo); /*----------------*/ if(recv_data.size() != recv_data.rpos()) @@ -247,7 +198,7 @@ void WorldSession::HandleMovementOpcodes( WorldPacket & recv_data ) return; /* handle special cases */ - if (MovementFlags & MOVEMENTFLAG_ONTRANSPORT) + if (movementInfo.flags & MOVEMENTFLAG_ONTRANSPORT) { // transports size limited // (also received at zeppelin leave by some reason with t_* as absolute in continent coordinates, can be safely skipped) @@ -266,9 +217,6 @@ void WorldSession::HandleMovementOpcodes( WorldPacket & recv_data ) { if ((*iter)->GetGUID() == movementInfo.t_guid) { - // unmount before boarding - _player->RemoveSpellsCausingAura(SPELL_AURA_MOUNTED); - GetPlayer()->m_transport = (*iter); (*iter)->AddPassenger(GetPlayer()); break; @@ -285,10 +233,11 @@ void WorldSession::HandleMovementOpcodes( WorldPacket & recv_data ) movementInfo.t_z = 0.0f; movementInfo.t_o = 0.0f; movementInfo.t_time = 0; + movementInfo.t_seat = -1; } // fall damage generation (ignore in flight case that can be triggered also at lags in moment teleportation to another map). - if (recv_data.GetOpcode() == MSG_MOVE_FALL_LAND && !GetPlayer()->isInFlight()) + if (opcode == MSG_MOVE_FALL_LAND && !GetPlayer()->isInFlight()) { // calculate total z distance of the fall float z_diff = GetPlayer()->m_lastFallZ - movementInfo.z; @@ -324,28 +273,19 @@ void WorldSession::HandleMovementOpcodes( WorldPacket & recv_data ) damage = target->GetMaxHealth()/2; target->EnvironmentalDamage(target->GetGUID(), DAMAGE_FALL, damage); + + // recheck alive, might have died of EnvironmentalDamage + if (target->isAlive()) + target->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_FALL_WITHOUT_DYING, uint32(z_diff*100)); } //Z given by moveinfo, LastZ, FallTime, WaterZ, MapZ, Damage, Safefall reduction DEBUG_LOG("FALLDAMAGE z=%f sz=%f pZ=%f FallTime=%d mZ=%f damage=%d SF=%d" , movementInfo.z, height, target->GetPositionZ(), movementInfo.fallTime, height, damage, safe_fall); } } - - //handle fall and logout at the same time (logout started before fall finished) - /* outdated and create problems with sit at stun sometime - if (target->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_ROTATE)) - { - target->SetStandState(PLAYER_STATE_SIT); - // Can't move - WorldPacket data( SMSG_FORCE_MOVE_ROOT, 12 ); - data.append(target->GetPackGUID()); - data << (uint32)2; - SendPacket( &data ); - } - */ } - if(((MovementFlags & MOVEMENTFLAG_SWIMMING) != 0) != GetPlayer()->IsInWater()) + if(((movementInfo.flags & MOVEMENTFLAG_SWIMMING) != 0) != GetPlayer()->IsInWater()) { // now client not include swimming flag in case jumping under water GetPlayer()->SetInWater( !GetPlayer()->IsInWater() || GetPlayer()->GetBaseMap()->IsUnderWater(movementInfo.x, movementInfo.y, movementInfo.z) ); @@ -354,15 +294,36 @@ void WorldSession::HandleMovementOpcodes( WorldPacket & recv_data ) /*----------------------*/ /* process position-change */ - recv_data.put(5, getMSTime()); // offset flags(4) + unk(1) - WorldPacket data(recv_data.GetOpcode(), (GetPlayer()->GetPackGUID().size()+recv_data.size())); - data.append(GetPlayer()->GetPackGUID()); + Unit *mover = _player->m_mover; + recv_data.put(6, getMSTime()); // fix time, offset flags(4) + unk(2) + WorldPacket data(recv_data.GetOpcode(), (mover->GetPackGUID().size()+recv_data.size())); + data.append(_player->m_mover->GetPackGUID()); // use mover guid data.append(recv_data.contents(), recv_data.size()); GetPlayer()->SendMessageToSet(&data, false); - GetPlayer()->SetPosition(movementInfo.x, movementInfo.y, movementInfo.z, movementInfo.o); - GetPlayer()->m_movementInfo = movementInfo; - if (GetPlayer()->m_lastFallTime >= movementInfo.fallTime || GetPlayer()->m_lastFallZ <=movementInfo.z) + if(!_player->GetCharmGUID()) // nothing is charmed + { + _player->SetPosition(movementInfo.x, movementInfo.y, movementInfo.z, movementInfo.o); + _player->m_movementInfo = movementInfo; + _player->SetUnitMovementFlags(movementInfo.flags); + } + else + { + if(mover->GetTypeId() != TYPEID_PLAYER) // unit, creature, pet, vehicle... + { + if(Map *map = mover->GetMap()) + map->CreatureRelocation((Creature*)mover, movementInfo.x, movementInfo.y, movementInfo.z, movementInfo.o); + mover->SetUnitMovementFlags(movementInfo.flags); + } + else // player + { + ((Player*)mover)->SetPosition(movementInfo.x, movementInfo.y, movementInfo.z, movementInfo.o); + ((Player*)mover)->m_movementInfo = movementInfo; + ((Player*)mover)->SetUnitMovementFlags(movementInfo.flags); + } + } + + if (GetPlayer()->m_lastFallTime >= movementInfo.fallTime || GetPlayer()->m_lastFallZ <=movementInfo.z || recv_data.GetOpcode() == MSG_MOVE_FALL_LAND) GetPlayer()->SetFallInformation(movementInfo.fallTime, movementInfo.z); if(GetPlayer()->isMovingOrTurning()) @@ -370,39 +331,41 @@ void WorldSession::HandleMovementOpcodes( WorldPacket & recv_data ) if(movementInfo.z < -500.0f) { - // NOTE: this is actually called many times while falling - // even after the player has been teleported away - // TODO: discard movement packets after the player is rooted - if(GetPlayer()->isAlive()) + if(GetPlayer()->InBattleGround() + && GetPlayer()->GetBattleGround() + && GetPlayer()->GetBattleGround()->HandlePlayerUnderMap(_player)) { - GetPlayer()->EnvironmentalDamage(GetPlayer()->GetGUID(),DAMAGE_FALL_TO_VOID, GetPlayer()->GetMaxHealth()); - // change the death state to CORPSE to prevent the death timer from - // starting in the next player update - GetPlayer()->KillPlayer(); - GetPlayer()->BuildPlayerRepop(); + // do nothing, the handle already did if returned true } + else + { + // NOTE: this is actually called many times while falling + // even after the player has been teleported away + // TODO: discard movement packets after the player is rooted + if(GetPlayer()->isAlive()) + { + GetPlayer()->EnvironmentalDamage(GetPlayer()->GetGUID(),DAMAGE_FALL_TO_VOID, GetPlayer()->GetMaxHealth()); + // change the death state to CORPSE to prevent the death timer from + // starting in the next player update + GetPlayer()->KillPlayer(); + GetPlayer()->BuildPlayerRepop(); + } - // cancel the death timer here if started - GetPlayer()->RepopAtGraveyard(); + // cancel the death timer here if started + GetPlayer()->RepopAtGraveyard(); + } } } void WorldSession::HandleForceSpeedChangeAck(WorldPacket &recv_data) { - CHECK_PACKET_SIZE(recv_data, 8+4+4+1+4+4+4+4+4); + sLog.outDebug("WORLD: Recvd %s (%u, 0x%X) opcode", LookupOpcodeName(recv_data.GetOpcode()), recv_data.GetOpcode(), recv_data.GetOpcode()); + + CHECK_PACKET_SIZE(recv_data, recv_data.rpos()+8+4); /* extract packet */ uint64 guid; - uint8 unkB; - uint32 unk1, flags, time, fallTime; - float x, y, z, orientation; - - uint64 t_GUID; - float t_x, t_y, t_z, t_o; - uint32 t_time; - float s_pitch; - float j_unk1, j_sinAngle, j_cosAngle, j_xyspeed; - float u_unk1; + uint32 unk1; float newspeed; recv_data >> guid; @@ -413,47 +376,10 @@ void WorldSession::HandleForceSpeedChangeAck(WorldPacket &recv_data) // continue parse packet - recv_data >> unk1; - recv_data >> flags >> unkB >> time; - recv_data >> x >> y >> z >> orientation; - if (flags & MOVEMENTFLAG_ONTRANSPORT) - { - // recheck - CHECK_PACKET_SIZE(recv_data, recv_data.rpos()+8+4+4+4+4+4); + recv_data >> unk1; // counter or moveEvent - recv_data >> t_GUID; - recv_data >> t_x >> t_y >> t_z >> t_o >> t_time; - } - if (flags & (MOVEMENTFLAG_SWIMMING | MOVEMENTFLAG_FLYING2)) - { - // recheck - CHECK_PACKET_SIZE(recv_data, recv_data.rpos()+4); - - recv_data >> s_pitch; // pitch, -1.55=looking down, 0=looking straight forward, +1.55=looking up - } - - // recheck - CHECK_PACKET_SIZE(recv_data, recv_data.rpos()+4); - - recv_data >> fallTime; // duration of last jump (when in jump duration from jump begin to now) - - if ((flags & MOVEMENTFLAG_JUMPING) || (flags & MOVEMENTFLAG_FALLING)) - { - // recheck - CHECK_PACKET_SIZE(recv_data, recv_data.rpos()+4+4+4+4); - - recv_data >> j_unk1; // ?constant, but different when jumping in water and on land? - recv_data >> j_sinAngle >> j_cosAngle; // sin + cos of angle between orientation0 and players orientation - recv_data >> j_xyspeed; // speed of xy movement - } - - if(flags & MOVEMENTFLAG_SPLINE) - { - // recheck - CHECK_PACKET_SIZE(recv_data, recv_data.rpos()+4); - - recv_data >> u_unk1; // unknown - } + MovementInfo movementInfo; + ReadMovementInfo(recv_data, &movementInfo); // recheck CHECK_PACKET_SIZE(recv_data, recv_data.rpos()+4); @@ -466,7 +392,7 @@ void WorldSession::HandleForceSpeedChangeAck(WorldPacket &recv_data) UnitMoveType move_type; UnitMoveType force_move_type; - static char const* move_type_name[MAX_MOVE_TYPE] = { "Walk", "Run", "RunBack", "Swim", "SwimBack", "TurnRate", "Flight", "FlightBack" }; + static char const* move_type_name[MAX_MOVE_TYPE] = { "Walk", "Run", "RunBack", "Swim", "SwimBack", "TurnRate", "Flight", "FlightBack", "PitchRate" }; uint16 opcode = recv_data.GetOpcode(); switch(opcode) @@ -479,6 +405,7 @@ void WorldSession::HandleForceSpeedChangeAck(WorldPacket &recv_data) case CMSG_FORCE_TURN_RATE_CHANGE_ACK: move_type = MOVE_TURN_RATE; force_move_type = MOVE_TURN_RATE; break; case CMSG_FORCE_FLIGHT_SPEED_CHANGE_ACK: move_type = MOVE_FLIGHT; force_move_type = MOVE_FLIGHT; break; case CMSG_FORCE_FLIGHT_BACK_SPEED_CHANGE_ACK: move_type = MOVE_FLIGHT_BACK; force_move_type = MOVE_FLIGHT_BACK; break; + case CMSG_FORCE_PITCH_RATE_CHANGE_ACK: move_type = MOVE_PITCH_RATE; force_move_type = MOVE_PITCH_RATE; break; default: sLog.outError("WorldSession::HandleForceSpeedChangeAck: Unknown move type opcode: %u", opcode); return; @@ -513,15 +440,61 @@ void WorldSession::HandleForceSpeedChangeAck(WorldPacket &recv_data) void WorldSession::HandleSetActiveMoverOpcode(WorldPacket &recv_data) { sLog.outDebug("WORLD: Recvd CMSG_SET_ACTIVE_MOVER"); + recv_data.hexlike(); - CHECK_PACKET_SIZE(recv_data,8); + CHECK_PACKET_SIZE(recv_data, 8); uint64 guid; recv_data >> guid; - WorldPacket data(SMSG_TIME_SYNC_REQ, 4); // new 2.0.x, enable movement - data << uint32(0x00000000); // on blizz it increments periodically - SendPacket(&data); + if(_player->m_mover->GetGUID() != guid) + { + sLog.outError("HandleSetActiveMoverOpcode: incorrect mover guid: mover is " I64FMT " and should be " I64FMT, _player->m_mover->GetGUID(), guid); + return; + } +} + +void WorldSession::HandleMoveNotActiveMover(WorldPacket &recv_data) +{ + sLog.outDebug("WORLD: Recvd CMSG_MOVE_NOT_ACTIVE_MOVER"); + recv_data.hexlike(); + + CHECK_PACKET_SIZE(recv_data, recv_data.rpos()+8); + + uint64 old_mover_guid; + recv_data >> old_mover_guid; + + if(_player->m_mover->GetGUID() == old_mover_guid) + { + sLog.outError("HandleMoveNotActiveMover: incorrect mover guid: mover is " I64FMT " and should be " I64FMT " instead of " I64FMT, _player->m_mover->GetGUID(), _player->GetGUID(), old_mover_guid); + return; + } + + MovementInfo mi; + ReadMovementInfo(recv_data, &mi); + _player->m_movementInfo = mi; +} + +void WorldSession::HandleDismissControlledVehicle(WorldPacket &recv_data) +{ + sLog.outDebug("WORLD: Recvd CMSG_DISMISS_CONTROLLED_VEHICLE"); + recv_data.hexlike(); + + uint64 vehicleGUID = _player->GetCharmGUID(); + + if(!vehicleGUID) // something wrong here... + return; + + MovementInfo mi; + ReadMovementInfo(recv_data, &mi); + _player->m_movementInfo = mi; + + // using charm guid, because we don't have vehicle guid... + if(Vehicle *vehicle = ObjectAccessor::GetVehicle(vehicleGUID)) + { + _player->ExitVehicle(vehicle); + vehicle->Dismiss(); + } } void WorldSession::HandleMountSpecialAnimOpcode(WorldPacket& /*recvdata*/) diff --git a/src/game/NPCHandler.cpp b/src/game/NPCHandler.cpp index 4303e1a6c..e7ac60265 100644 --- a/src/game/NPCHandler.cpp +++ b/src/game/NPCHandler.cpp @@ -114,7 +114,7 @@ void WorldSession::SendTrainerList( uint64 guid ) SendTrainerList( guid, str ); } -void WorldSession::SendTrainerList( uint64 guid,std::string strTitle ) +void WorldSession::SendTrainerList( uint64 guid, const std::string& strTitle ) { sLog.outDebug( "WORLD: SendTrainerList" ); @@ -518,13 +518,12 @@ void WorldSession::SendStablePet(uint64 guid ) data << uint32(pet->GetEntry()); data << uint32(pet->getLevel()); data << pet->GetName(); // petname - data << uint32(pet->GetLoyaltyLevel()); // loyalty - data << uint8(0x01); // client slot 1 == current pet (0) + data << uint8(0x01); // flags?, client slot 1 == current pet (0) ++num; } - // 0 1 2 3 4 5 6 - QueryResult* result = CharacterDatabase.PQuery("SELECT owner, slot, id, entry, level, loyalty, name FROM character_pet WHERE owner = '%u' AND slot > 0 AND slot < 3",_player->GetGUIDLow()); + // 0 1 2 3 4 5 + QueryResult* result = CharacterDatabase.PQuery("SELECT owner, slot, id, entry, level, name FROM character_pet WHERE owner = '%u' AND slot > 0 AND slot < 5",_player->GetGUIDLow()); if(result) { @@ -535,8 +534,7 @@ void WorldSession::SendStablePet(uint64 guid ) data << uint32(fields[2].GetUInt32()); // petnumber data << uint32(fields[3].GetUInt32()); // creature entry data << uint32(fields[4].GetUInt32()); // level - data << fields[6].GetString(); // name - data << uint32(fields[5].GetUInt32()); // loyalty + data << fields[5].GetString(); // name data << uint8(fields[1].GetUInt32()+1); // slot ++num; @@ -586,7 +584,7 @@ void WorldSession::HandleStablePet( WorldPacket & recv_data ) uint32 free_slot = 1; - QueryResult *result = CharacterDatabase.PQuery("SELECT owner,slot,id FROM character_pet WHERE owner = '%u' AND slot > 0 AND slot < 3 ORDER BY slot ",_player->GetGUIDLow()); + QueryResult *result = CharacterDatabase.PQuery("SELECT owner,slot,id FROM character_pet WHERE owner = '%u' AND slot > 0 AND slot < 5 ORDER BY slot ",_player->GetGUIDLow()); if(result) { do @@ -650,7 +648,7 @@ void WorldSession::HandleUnstablePet( WorldPacket & recv_data ) Pet *newpet = NULL; - QueryResult *result = CharacterDatabase.PQuery("SELECT entry FROM character_pet WHERE owner = '%u' AND id = '%u' AND slot > 0 AND slot < 3",_player->GetGUIDLow(),petnumber); + QueryResult *result = CharacterDatabase.PQuery("SELECT entry FROM character_pet WHERE owner = '%u' AND id = '%u' AND slot > 0 AND slot < 5",_player->GetGUIDLow(),petnumber); if(result) { Field *fields = result->Fetch(); @@ -694,7 +692,7 @@ void WorldSession::HandleBuyStableSlot( WorldPacket & recv_data ) WorldPacket data(SMSG_STABLE_RESULT, 200); - if(GetPlayer()->m_stableSlots < 2) // max slots amount = 2 + if(GetPlayer()->m_stableSlots < 4) // max slots amount = 4 { StableSlotPricesEntry const *SlotPrice = sStableSlotPricesStore.LookupEntry(GetPlayer()->m_stableSlots+1); if(_player->GetMoney() >= SlotPrice->Price) diff --git a/src/game/Object.cpp b/src/game/Object.cpp index b8f758cbd..ebd2279b7 100644 --- a/src/game/Object.cpp +++ b/src/game/Object.cpp @@ -146,15 +146,9 @@ void Object::BuildCreateUpdateBlockForPlayer(UpdateData *data, Player *target) c /** lower flag1 **/ if(target == this) // building packet for oneself - { flags |= UPDATEFLAG_SELF; - /*** temporary reverted - until real source of stack corruption will not found - updatetype = UPDATETYPE_CREATE_OBJECT2; - ****/ - } - - if(flags & UPDATEFLAG_HASPOSITION) + if(flags & UPDATEFLAG_HAS_POSITION) { // UPDATETYPE_CREATE_OBJECT2 dynamic objects, corpses... if(isType(TYPEMASK_DYNAMICOBJECT) || isType(TYPEMASK_CORPSE) || isType(TYPEMASK_PLAYER)) @@ -180,6 +174,12 @@ void Object::BuildCreateUpdateBlockForPlayer(UpdateData *data, Player *target) c break; } } + + if(isType(TYPEMASK_UNIT)) + { + if(((Unit*)this)->getVictim()) + flags |= UPDATEFLAG_HAS_TARGET; + } } //sLog.outDebug("BuildCreateUpdate: update-type: %u, object-type: %u got flags: %X, flags2: %X", updatetype, m_objectTypeId, flags, flags2); @@ -251,11 +251,18 @@ void Object::DestroyForPlayer(Player *target) const WorldPacket data(SMSG_DESTROY_OBJECT, 8); data << GetGUID(); + data << uint8(0); // WotLK (bool) target->GetSession()->SendPacket( &data ); } -void Object::_BuildMovementUpdate(ByteBuffer * data, uint8 flags, uint32 flags2 ) const +void Object::_BuildMovementUpdate(ByteBuffer * data, uint8 flags, uint32 flags2) const { + uint16 unk_flags = ((GetTypeId() == TYPEID_PLAYER) ? ((Player*)this)->m_movementInfo.unk1 : 0); + + if(GetTypeId() == TYPEID_UNIT) + if(((Creature*)this)->isVehicle()) + unk_flags |= 0x20; // always allow pitch + *data << (uint8)flags; // update flags // 0x20 @@ -290,12 +297,12 @@ void Object::_BuildMovementUpdate(ByteBuffer * data, uint8 flags, uint32 flags2 } *data << uint32(flags2); // movement flags - *data << uint8(0); // unk 2.3.0 + *data << uint16(unk_flags); // unknown 2.3.0 *data << uint32(getMSTime()); // time (in milliseconds) } // 0x40 - if (flags & UPDATEFLAG_HASPOSITION) + if (flags & UPDATEFLAG_HAS_POSITION) { // 0x02 if(flags & UPDATEFLAG_TRANSPORT && ((GameObject*)this)->GetGoType() == GAMEOBJECT_TYPE_MO_TRANSPORT) @@ -328,12 +335,13 @@ void Object::_BuildMovementUpdate(ByteBuffer * data, uint8 flags, uint32 flags2 *data << (float)((Player*)this)->GetTransOffsetZ(); *data << (float)((Player*)this)->GetTransOffsetO(); *data << (uint32)((Player*)this)->GetTransTime(); + *data << (int8)((Player*)this)->GetTransSeat(); } //MaNGOS currently not have support for other than player on transport } // 0x02200000 - if(flags2 & (MOVEMENTFLAG_SWIMMING | MOVEMENTFLAG_FLYING2)) + if((flags2 & (MOVEMENTFLAG_SWIMMING | MOVEMENTFLAG_FLYING2)) || (unk_flags & 0x20)) { if(GetTypeId() == TYPEID_PLAYER) *data << (float)((Player*)this)->m_movementInfo.s_pitch; @@ -382,6 +390,7 @@ void Object::_BuildMovementUpdate(ByteBuffer * data, uint8 flags, uint32 flags2 *data << ((Unit*)this)->GetSpeed( MOVE_FLIGHT ); *data << ((Unit*)this)->GetSpeed( MOVE_FLIGHT_BACK ); *data << ((Unit*)this)->GetSpeed( MOVE_TURN_RATE ); + *data << ((Unit*)this)->GetSpeed( MOVE_PITCH_RATE ); // 0x08000000 if(flags2 & MOVEMENTFLAG_SPLINE2) @@ -483,7 +492,7 @@ void Object::_BuildMovementUpdate(ByteBuffer * data, uint8 flags, uint32 flags2 break; case TYPEID_PLAYER: if(flags & UPDATEFLAG_SELF) - *data << uint32(0x00000015); // unk, can be 0x15 or 0x22 + *data << uint32(0x0000002F); // unk, can be 0x15 or 0x22 else *data << uint32(0x00000008); // unk, can be 0x7 or 0x8 break; @@ -506,6 +515,15 @@ void Object::_BuildMovementUpdate(ByteBuffer * data, uint8 flags, uint32 flags2 case TYPEID_CORPSE: *data << uint32(GetGUIDHigh()); // GetGUIDHigh() break; + case TYPEID_UNIT: + *data << uint32(0x0000000B); // unk, can be 0xB or 0xC + break; + case TYPEID_PLAYER: + if(flags & UPDATEFLAG_SELF) + *data << uint32(0x0000002F); // unk, can be 0x15 or 0x22 + else + *data << uint32(0x00000008); // unk, can be 0x7 or 0x8 + break; default: *data << uint32(0x00000000); // unk break; @@ -513,9 +531,12 @@ void Object::_BuildMovementUpdate(ByteBuffer * data, uint8 flags, uint32 flags2 } // 0x4 - if(flags & UPDATEFLAG_FULLGUID) + if(flags & UPDATEFLAG_HAS_TARGET) // packed guid (current target guid) { - *data << uint8(0); // packed guid (probably target guid) + if(Unit *victim = ((Unit*)this)->getVictim()) + data->append(victim->GetPackGUID()); + else + *data << uint8(0); } // 0x2 @@ -523,6 +544,13 @@ void Object::_BuildMovementUpdate(ByteBuffer * data, uint8 flags, uint32 flags2 { *data << uint32(getMSTime()); // ms time } + + // 0x80 + if(flags & UPDATEFLAG_VEHICLE) // unused for now + { + *data << uint32(((Vehicle*)this)->GetVehicleId()); // vehicle id + *data << float(0); // facing adjustment + } } void Object::_BuildValuesUpdate(uint8 updatetype, ByteBuffer * data, UpdateMask *updateMask, Player *target) const @@ -538,7 +566,7 @@ void Object::_BuildValuesUpdate(uint8 updatetype, ByteBuffer * data, UpdateMask if ( ((GameObject*)this)->ActivateToQuest(target) || target->isGameMaster()) { IsActivateToQuest = true; - updateMask->SetBit(GAMEOBJECT_DYN_FLAGS); + updateMask->SetBit(GAMEOBJECT_DYNAMIC); } } } @@ -550,8 +578,8 @@ void Object::_BuildValuesUpdate(uint8 updatetype, ByteBuffer * data, UpdateMask { IsActivateToQuest = true; } - updateMask->SetBit(GAMEOBJECT_DYN_FLAGS); - updateMask->SetBit(GAMEOBJECT_ANIMPROGRESS); + updateMask->SetBit(GAMEOBJECT_DYNAMIC); + updateMask->SetBit(GAMEOBJECT_BYTES_1); } } @@ -612,7 +640,7 @@ void Object::_BuildValuesUpdate(uint8 updatetype, ByteBuffer * data, UpdateMask if( updateMask->GetBit( index ) ) { // send in current format (float as float, uint32 as uint32) - if ( index == GAMEOBJECT_DYN_FLAGS ) + if ( index == GAMEOBJECT_DYNAMIC ) { if(IsActivateToQuest ) { @@ -1371,7 +1399,7 @@ void WorldObject::BuildHeartBeatMsg(WorldPacket *data) const data->Initialize(MSG_MOVE_HEARTBEAT, 32); data->append(GetPackGUID()); *data << uint32(((Unit*)this)->GetUnitMovementFlags()); // movement flags - *data << uint8(0); // 2.3.0 + *data << uint16(0); // 2.3.0 *data << getMSTime(); // time *data << m_positionX; *data << m_positionY; @@ -1390,7 +1418,7 @@ void WorldObject::BuildTeleportAckMsg(WorldPacket *data, float x, float y, float data->append(GetPackGUID()); *data << uint32(0); // this value increments every time *data << uint32(((Unit*)this)->GetUnitMovementFlags()); // movement flags - *data << uint8(0); // 2.3.0 + *data << uint16(0); // 2.3.0 *data << getMSTime(); // time *data << x; *data << y; diff --git a/src/game/Object.h b/src/game/Object.h index 16e1fbfdf..6abd05203 100644 --- a/src/game/Object.h +++ b/src/game/Object.h @@ -407,7 +407,7 @@ class MANGOS_DLL_SPEC WorldObject : public Object InstanceData* GetInstanceData(); const char* GetName() const { return m_name.c_str(); } - void SetName(std::string newname) { m_name=newname; } + void SetName(const std::string& newname) { m_name=newname; } virtual const char* GetNameForLocaleIdx(int32 /*locale_idx*/) const { return GetName(); } diff --git a/src/game/ObjectAccessor.cpp b/src/game/ObjectAccessor.cpp index 5ce16ca3c..a1305e7f7 100644 --- a/src/game/ObjectAccessor.cpp +++ b/src/game/ObjectAccessor.cpp @@ -132,6 +132,9 @@ ObjectAccessor::GetCreatureOrPet(WorldObject const &u, uint64 guid) if(Creature *unit = GetPet(guid)) return unit; + if(Creature *unit = GetVehicle(guid)) + return unit; + return GetCreature(u, guid); } @@ -349,6 +352,12 @@ ObjectAccessor::GetPet(uint64 guid) return GetObjectInWorld(guid, (Pet*)NULL); } +Vehicle* +ObjectAccessor::GetVehicle(uint64 guid) +{ + return GetObjectInWorld(guid, (Vehicle*)NULL); +} + Corpse* ObjectAccessor::GetCorpseForPlayerGUID(uint64 guid) { @@ -554,6 +563,7 @@ template ZThread::FastMutex HashMapHolder::i_lock; template class HashMapHolder; template class HashMapHolder; +template class HashMapHolder; template class HashMapHolder; template class HashMapHolder; template class HashMapHolder; @@ -561,6 +571,7 @@ template class HashMapHolder; template Player* ObjectAccessor::GetObjectInWorld(uint32 mapid, float x, float y, uint64 guid, Player* /*fake*/); template Pet* ObjectAccessor::GetObjectInWorld(uint32 mapid, float x, float y, uint64 guid, Pet* /*fake*/); +template Vehicle* ObjectAccessor::GetObjectInWorld(uint32 mapid, float x, float y, uint64 guid, Vehicle* /*fake*/); template Creature* ObjectAccessor::GetObjectInWorld(uint32 mapid, float x, float y, uint64 guid, Creature* /*fake*/); template Corpse* ObjectAccessor::GetObjectInWorld(uint32 mapid, float x, float y, uint64 guid, Corpse* /*fake*/); template GameObject* ObjectAccessor::GetObjectInWorld(uint32 mapid, float x, float y, uint64 guid, GameObject* /*fake*/); diff --git a/src/game/ObjectAccessor.h b/src/game/ObjectAccessor.h index e5b0f61f7..ff33a9f6c 100644 --- a/src/game/ObjectAccessor.h +++ b/src/game/ObjectAccessor.h @@ -31,6 +31,7 @@ #include "GridDefines.h" #include "Object.h" #include "Player.h" +#include "Vehicle.h" #include @@ -148,6 +149,7 @@ class MANGOS_DLL_DECL ObjectAccessor : public MaNGOS::SingletongetSource(); - assert(!c->isPet() && "ObjectGridRespawnMover don't must be called for pets"); + assert((!c->isPet() || !c->isVehicle()) && "ObjectGridRespawnMover don't must be called for pets"); Cell const& cur_cell = c->GetCurrentCell(); diff --git a/src/game/ObjectMgr.cpp b/src/game/ObjectMgr.cpp index a936c0cc2..f0332aa00 100644 --- a/src/game/ObjectMgr.cpp +++ b/src/game/ObjectMgr.cpp @@ -112,6 +112,7 @@ ObjectMgr::ObjectMgr() m_hiCharGuid = 1; m_hiCreatureGuid = 1; m_hiPetGuid = 1; + m_hiVehicleGuid = 1; m_hiItemGuid = 1; m_hiGoGuid = 1; m_hiDoGuid = 1; @@ -137,13 +138,13 @@ ObjectMgr::ObjectMgr() ObjectMgr::~ObjectMgr() { - for( QuestMap::iterator i = mQuestTemplates.begin( ); i != mQuestTemplates.end( ); ++ i ) + for( QuestMap::iterator i = mQuestTemplates.begin( ); i != mQuestTemplates.end( ); ++i ) { delete i->second; } mQuestTemplates.clear( ); - for( GossipTextMap::iterator i = mGossipText.begin( ); i != mGossipText.end( ); ++ i ) + for( GossipTextMap::iterator i = mGossipText.begin( ); i != mGossipText.end( ); ++i ) { delete i->second; } @@ -151,7 +152,7 @@ ObjectMgr::~ObjectMgr() mAreaTriggers.clear(); - for(PetLevelInfoMap::iterator i = petInfo.begin( ); i != petInfo.end( ); ++ i ) + for(PetLevelInfoMap::iterator i = petInfo.begin( ); i != petInfo.end( ); ++i ) { delete[] i->second; } @@ -199,7 +200,7 @@ Guild * ObjectMgr::GetGuildById(const uint32 GuildId) const return NULL; } -Guild * ObjectMgr::GetGuildByName(std::string guildname) const +Guild * ObjectMgr::GetGuildByName(const std::string& guildname) const { for(GuildSet::const_iterator itr = mGuildSet.begin(); itr != mGuildSet.end(); ++itr) if ((*itr)->GetName() == guildname) @@ -226,33 +227,43 @@ Guild* ObjectMgr::GetGuildByLeader(const uint64 &guid) const return NULL; } -ArenaTeam* ObjectMgr::GetArenaTeamById(const uint32 ArenaTeamId) const +ArenaTeam* ObjectMgr::GetArenaTeamById(const uint32 arenateamid) const { - for(ArenaTeamSet::const_iterator itr = mArenaTeamSet.begin(); itr != mArenaTeamSet.end(); ++itr) - if ((*itr)->GetId() == ArenaTeamId) - return *itr; + ArenaTeamMap::const_iterator itr = mArenaTeamMap.find(arenateamid); + if (itr != mArenaTeamMap.end()) + return itr->second; return NULL; } -ArenaTeam* ObjectMgr::GetArenaTeamByName(std::string arenateamname) const +ArenaTeam* ObjectMgr::GetArenaTeamByName(const std::string& arenateamname) const { - for(ArenaTeamSet::const_iterator itr = mArenaTeamSet.begin(); itr != mArenaTeamSet.end(); ++itr) - if ((*itr)->GetName() == arenateamname) - return *itr; + for(ArenaTeamMap::const_iterator itr = mArenaTeamMap.begin(); itr != mArenaTeamMap.end(); ++itr) + if (itr->second->GetName() == arenateamname) + return itr->second; return NULL; } -ArenaTeam* ObjectMgr::GetArenaTeamByCapitan(uint64 const& guid) const +ArenaTeam* ObjectMgr::GetArenaTeamByCaptain(uint64 const& guid) const { - for(ArenaTeamSet::const_iterator itr = mArenaTeamSet.begin(); itr != mArenaTeamSet.end(); ++itr) - if ((*itr)->GetCaptain() == guid) - return *itr; + for(ArenaTeamMap::const_iterator itr = mArenaTeamMap.begin(); itr != mArenaTeamMap.end(); ++itr) + if (itr->second->GetCaptain() == guid) + return itr->second; return NULL; } +void ObjectMgr::AddArenaTeam(ArenaTeam* arenaTeam) +{ + mArenaTeamMap[arenaTeam->GetId()] = arenaTeam; +} + +void ObjectMgr::RemoveArenaTeam(ArenaTeam* arenaTeam) +{ + mArenaTeamMap.erase( arenaTeam->GetId() ); +} + AuctionHouseObject * ObjectMgr::GetAuctionsMap( uint32 location ) { switch ( location ) @@ -568,7 +579,23 @@ void ObjectMgr::LoadCreatureLocales() sLog.outString(); sLog.outString( ">> Loaded %u creature locale strings", mCreatureLocaleMap.size() ); } - + +void ObjectMgr::LoadCompletedAchievements() +{ + QueryResult *result = CharacterDatabase.Query("SELECT achievement FROM character_achievement GROUP BY achievement"); + + if(!result) + return; + + do + { + Field *fields = result->Fetch(); + allCompletedAchievements.insert(fields[0].GetUInt32()); + } while(result->NextRow()); + + delete result; +} + void ObjectMgr::LoadNpcOptionLocales() { mNpcOptionLocaleMap.clear(); // need for reload case @@ -915,8 +942,47 @@ void ObjectMgr::LoadEquipmentTemplates() { sEquipmentStorage.Load(); + for(uint32 i=0; i< sEquipmentStorage.MaxEntry; ++i) + { + EquipmentInfo const* eqInfo = sEquipmentStorage.LookupEntry(i); + + if(!eqInfo) + continue; + + for(uint8 j=0; j<3; j++) + { + if(!eqInfo->equipentry[j]) + continue; + + ItemEntry const *dbcitem = sItemStore.LookupEntry(eqInfo->equipentry[j]); + + if(!dbcitem) + { + sLog.outErrorDb("Unknown item (entry=%u) in creature_equip_template.equipentry%u for entry = %u, forced to 0.", eqInfo->equipentry[j], j+1, i); + const_cast(eqInfo)->equipentry[j] = 0; + continue; + } + + if(dbcitem->InventoryType != INVTYPE_WEAPON && + dbcitem->InventoryType != INVTYPE_SHIELD && + dbcitem->InventoryType != INVTYPE_RANGED && + dbcitem->InventoryType != INVTYPE_2HWEAPON && + dbcitem->InventoryType != INVTYPE_WEAPONMAINHAND && + dbcitem->InventoryType != INVTYPE_WEAPONOFFHAND && + dbcitem->InventoryType != INVTYPE_HOLDABLE && + dbcitem->InventoryType != INVTYPE_THROWN && + dbcitem->InventoryType != INVTYPE_RANGEDRIGHT) + { + sLog.outErrorDb("Item (entry=%u) in creature_equip_template.equipentry%u for entry = %u is not equipable in a hand, forced to 0.", eqInfo->equipentry[j], j+1, i); + const_cast(eqInfo)->equipentry[j] = 0; + } + } + } sLog.outString( ">> Loaded %u equipment template", sEquipmentStorage.RecordCount ); sLog.outString(); + + // This DBC is currently only used for item templates and creature equipments checks. + sItemStore.Clear(); } CreatureModelInfo const* ObjectMgr::GetCreatureModelInfo(uint32 modelid) @@ -1380,7 +1446,7 @@ uint32 ObjectMgr::GetPlayerAccountIdByGUID(const uint64 &guid) const return 0; } -uint32 ObjectMgr::GetPlayerAccountIdByPlayerName(std::string name) const +uint32 ObjectMgr::GetPlayerAccountIdByPlayerName(const std::string& name) const { QueryResult *result = CharacterDatabase.PQuery("SELECT account FROM characters WHERE name = '%s'", name.c_str()); if(result) @@ -1573,7 +1639,7 @@ void ObjectMgr::LoadItemPrototypes() if(proto->Class >= MAX_ITEM_CLASS) { sLog.outErrorDb("Item (Entry: %u) has wrong Class value (%u)",i,proto->Class); - const_cast(proto)->Class = ITEM_CLASS_JUNK; + const_cast(proto)->Class = ITEM_CLASS_MISC; } if(proto->SubClass >= MaxItemSubclassValues[proto->Class]) @@ -1670,7 +1736,7 @@ void ObjectMgr::LoadItemPrototypes() } // special format - if(proto->Spells[0].SpellId == SPELL_ID_GENERIC_LEARN) + if((proto->Spells[0].SpellId == SPELL_ID_GENERIC_LEARN) || (proto->Spells[0].SpellId == SPELL_ID_GENERIC_LEARN_PET)) { // spell_1 if(proto->Spells[0].SpellTrigger != ITEM_SPELLTRIGGER_ON_USE) @@ -1707,7 +1773,7 @@ void ObjectMgr::LoadItemPrototypes() const_cast(proto)->Spells[1].SpellTrigger = ITEM_SPELLTRIGGER_ON_USE; } // allowed only in special format - else if(proto->Spells[1].SpellId==SPELL_ID_GENERIC_LEARN) + else if((proto->Spells[1].SpellId==SPELL_ID_GENERIC_LEARN) || (proto->Spells[1].SpellId==SPELL_ID_GENERIC_LEARN_PET)) { sLog.outErrorDb("Item (Entry: %u) has broken spell in spellid_%d (%u)",i,1+1,proto->Spells[1].SpellId); const_cast(proto)->Spells[0].SpellId = 0; @@ -1753,7 +1819,7 @@ void ObjectMgr::LoadItemPrototypes() const_cast(proto)->Spells[j].SpellId = 0; } // allowed only in special format - else if(proto->Spells[j].SpellId==SPELL_ID_GENERIC_LEARN) + else if((proto->Spells[j].SpellId==SPELL_ID_GENERIC_LEARN) || (proto->Spells[j].SpellId==SPELL_ID_GENERIC_LEARN_PET)) { sLog.outErrorDb("Item (Entry: %u) has broken spell in spellid_%d (%u)",i,j+1,proto->Spells[j].SpellId); const_cast(proto)->Spells[j].SpellId = 0; @@ -1822,9 +1888,6 @@ void ObjectMgr::LoadItemPrototypes() const_cast(proto)->FoodType = 0; } } - - // this DBC used currently only for check item templates in DB. - sItemStore.Clear(); } void ObjectMgr::LoadAuctionItems() @@ -1909,8 +1972,8 @@ void ObjectMgr::LoadPetLevelInfo() uint32 current_level = fields[1].GetUInt32(); if(current_level > sWorld.getConfig(CONFIG_MAX_PLAYER_LEVEL)) { - if(current_level > 255) // hardcoded level maximum - sLog.outErrorDb("Wrong (> 255) level %u in `pet_levelstats` table, ignoring.",current_level); + if(current_level > STRONG_MAX_LEVEL) // hardcoded level maximum + sLog.outErrorDb("Wrong (> %u) level %u in `pet_levelstats` table, ignoring.",STRONG_MAX_LEVEL,current_level); else sLog.outDetail("Unused (> MaxPlayerLevel in mangosd.conf) level %u in `pet_levelstats` table, ignoring.",current_level); continue; @@ -2089,6 +2152,8 @@ void ObjectMgr::LoadPlayerInfo() { barGoLink bar( 1 ); + bar.step(); + sLog.outString(); sLog.outString( ">> Loaded %u custom player create items", count ); } @@ -2286,8 +2351,8 @@ void ObjectMgr::LoadPlayerInfo() uint32 current_level = fields[1].GetUInt32(); if(current_level > sWorld.getConfig(CONFIG_MAX_PLAYER_LEVEL)) { - if(current_level > 255) // hardcoded level maximum - sLog.outErrorDb("Wrong (> 255) level %u in `player_classlevelstats` table, ignoring.",current_level); + if(current_level > STRONG_MAX_LEVEL) // hardcoded level maximum + sLog.outErrorDb("Wrong (> %u) level %u in `player_classlevelstats` table, ignoring.",STRONG_MAX_LEVEL,current_level); else sLog.outDetail("Unused (> MaxPlayerLevel in mangosd.conf) level %u in `player_classlevelstats` table, ignoring.",current_level); continue; @@ -2381,8 +2446,8 @@ void ObjectMgr::LoadPlayerInfo() uint32 current_level = fields[2].GetUInt32(); if(current_level > sWorld.getConfig(CONFIG_MAX_PLAYER_LEVEL)) { - if(current_level > 255) // hardcoded level maximum - sLog.outErrorDb("Wrong (> 255) level %u in `player_levelstats` table, ignoring.",current_level); + if(current_level > STRONG_MAX_LEVEL) // hardcoded level maximum + sLog.outErrorDb("Wrong (> %u) level %u in `player_levelstats` table, ignoring.",STRONG_MAX_LEVEL,current_level); else sLog.outDetail("Unused (> MaxPlayerLevel in mangosd.conf) level %u in `player_levelstats` table, ignoring.",current_level); continue; @@ -2808,31 +2873,31 @@ void ObjectMgr::LoadQuests() QueryResult *result = WorldDatabase.Query("SELECT entry, Method, ZoneOrSort, SkillOrClass, MinLevel, QuestLevel, Type, RequiredRaces, RequiredSkillValue," // 9 10 11 12 13 14 15 16 "RepObjectiveFaction, RepObjectiveValue, RequiredMinRepFaction, RequiredMinRepValue, RequiredMaxRepFaction, RequiredMaxRepValue, SuggestedPlayers, LimitTime," - // 17 18 19 20 21 22 23 24 25 26 - "QuestFlags, SpecialFlags, CharTitleId, PrevQuestId, NextQuestId, ExclusiveGroup, NextQuestInChain, SrcItemId, SrcItemCount, SrcSpell," - // 27 28 29 30 31 32 33 34 35 36 + // 17 18 19 20 21 22 23 24 25 26 27 28 + "QuestFlags, SpecialFlags, CharTitleId, PlayersSlain, BonusTalents, PrevQuestId, NextQuestId, ExclusiveGroup, NextQuestInChain, SrcItemId, SrcItemCount, SrcSpell," + // 29 30 31 32 33 34 35 36 37 38 "Title, Details, Objectives, OfferRewardText, RequestItemsText, EndText, ObjectiveText1, ObjectiveText2, ObjectiveText3, ObjectiveText4," - // 37 38 39 40 41 42 43 44 + // 39 40 41 42 43 44 45 46 "ReqItemId1, ReqItemId2, ReqItemId3, ReqItemId4, ReqItemCount1, ReqItemCount2, ReqItemCount3, ReqItemCount4," - // 45 46 47 48 49 50 51 52 53 54 54 55 + // 47 48 49 50 51 52 53 54 55 56 57 58 "ReqSourceId1, ReqSourceId2, ReqSourceId3, ReqSourceId4, ReqSourceCount1, ReqSourceCount2, ReqSourceCount3, ReqSourceCount4, ReqSourceRef1, ReqSourceRef2, ReqSourceRef3, ReqSourceRef4," - // 57 58 59 60 61 62 63 64 + // 59 60 61 62 63 64 65 66 "ReqCreatureOrGOId1, ReqCreatureOrGOId2, ReqCreatureOrGOId3, ReqCreatureOrGOId4, ReqCreatureOrGOCount1, ReqCreatureOrGOCount2, ReqCreatureOrGOCount3, ReqCreatureOrGOCount4," - // 65 66 67 68 + // 67 68 69 70 "ReqSpellCast1, ReqSpellCast2, ReqSpellCast3, ReqSpellCast4," - // 69 70 71 72 73 74 + // 71 72 73 74 75 76 "RewChoiceItemId1, RewChoiceItemId2, RewChoiceItemId3, RewChoiceItemId4, RewChoiceItemId5, RewChoiceItemId6," - // 75 76 77 78 79 80 + // 77 78 79 80 81 82 "RewChoiceItemCount1, RewChoiceItemCount2, RewChoiceItemCount3, RewChoiceItemCount4, RewChoiceItemCount5, RewChoiceItemCount6," - // 81 82 83 84 85 86 87 88 + // 83 84 85 86 87 88 89 90 "RewItemId1, RewItemId2, RewItemId3, RewItemId4, RewItemCount1, RewItemCount2, RewItemCount3, RewItemCount4," - // 89 90 91 92 93 94 95 96 97 98 + // 91 92 93 94 95 96 97 98 99 100 "RewRepFaction1, RewRepFaction2, RewRepFaction3, RewRepFaction4, RewRepFaction5, RewRepValue1, RewRepValue2, RewRepValue3, RewRepValue4, RewRepValue5," - // 99 100 101 102 103 104 105 106 107 108 109 + // 101 102 103 104 105 106 107 108 109 110 111 "RewHonorableKills, RewOrReqMoney, RewMoneyMaxLevel, RewSpell, RewSpellCast, RewMailTemplateId, RewMailDelaySecs, PointMapId, PointX, PointY, PointOpt," - // 110 111 112 113 114 115 116 117 118 119 + // 112 113 114 115 116 117 118 119 120 121 "DetailsEmote1, DetailsEmote2, DetailsEmote3, DetailsEmote4,IncompleteEmote, CompleteEmote, OfferRewardEmote1, OfferRewardEmote2, OfferRewardEmote3, OfferRewardEmote4," - // 120 121 + // 122 123 "StartScript, CompleteScript" " FROM quest_template"); if(result == NULL) @@ -4203,7 +4268,7 @@ void ObjectMgr::AddGossipText(GossipText *pGText) GossipText *ObjectMgr::GetGossipText(uint32 Text_ID) { GossipTextMap::const_iterator itr; - for (itr = mGossipText.begin(); itr != mGossipText.end(); itr++) + for (itr = mGossipText.begin(); itr != mGossipText.end(); ++itr) { if(itr->second->Text_ID == Text_ID) return itr->second; @@ -4654,14 +4719,14 @@ uint16 ObjectMgr::GetTaxiMount( uint32 id, uint32 team ) { if (team == ALLIANCE) { - mount_entry = node->alliance_mount_type; + mount_entry = node->MountCreatureID[1]; CreatureInfo const *ci = GetCreatureTemplate(mount_entry); if(ci) mount_id = ci->DisplayID_A; } if (team == HORDE) { - mount_entry = node->horde_mount_type; + mount_entry = node->MountCreatureID[0]; CreatureInfo const *ci = GetCreatureTemplate(mount_entry); if(ci) mount_id = ci->DisplayID_H; @@ -5095,6 +5160,8 @@ void ObjectMgr::SetHighestGuids() // pet guids are not saved to DB, set to 0 (pet guid != pet id) m_hiPetGuid = 0; + // same for vehicles + m_hiVehicleGuid = 0; result = CharacterDatabase.Query( "SELECT MAX(guid) FROM item_instance" ); if( result ) @@ -5248,6 +5315,14 @@ uint32 ObjectMgr::GenerateLowGuid(HighGuid guidhigh) World::StopNow(ERROR_EXIT_CODE); } return m_hiPetGuid++; + case HIGHGUID_VEHICLE: + ++m_hiVehicleGuid; + if(m_hiVehicleGuid>=0x00FFFFFF) + { + sLog.outError("Vehicle guid overflow!! Can't continue, shutting down server. "); + World::StopNow(ERROR_EXIT_CODE); + } + return m_hiVehicleGuid++; case HIGHGUID_PLAYER: if(m_hiCharGuid>=0xFFFFFFFE) { @@ -6135,7 +6210,7 @@ bool isValidString(std::wstring wstr, uint32 strictMask, bool numericOrSpace, bo return false; } -bool ObjectMgr::IsValidName( std::string name, bool create ) +bool ObjectMgr::IsValidName( const std::string& name, bool create ) { std::wstring wname; if(!Utf8toWStr(name,wname)) @@ -6149,7 +6224,7 @@ bool ObjectMgr::IsValidName( std::string name, bool create ) return isValidString(wname,strictMask,false,create); } -bool ObjectMgr::IsValidCharterName( std::string name ) +bool ObjectMgr::IsValidCharterName( const std::string& name ) { std::wstring wname; if(!Utf8toWStr(name,wname)) @@ -6163,7 +6238,7 @@ bool ObjectMgr::IsValidCharterName( std::string name ) return isValidString(wname,strictMask,true); } -bool ObjectMgr::IsValidPetName( std::string name ) +bool ObjectMgr::IsValidPetName( const std::string& name ) { std::wstring wname; if(!Utf8toWStr(name,wname)) @@ -6210,6 +6285,23 @@ int ObjectMgr::GetOrNewIndexForLocale( LocaleConstant loc ) return m_LocalForIndex.size()-1; } +AchievementCriteriaEntryList const& ObjectMgr::GetAchievementCriteriaByType(AchievementCriteriaTypes type) +{ + return m_AchievementCriteriasByType[type]; +} + +void ObjectMgr::LoadAchievementCriteriaList() +{ + for (uint32 entryId = 0; entryIdrequiredType].push_back(criteria); + } +} + void ObjectMgr::LoadBattleMastersEntry() { mBattleMastersMap.clear(); // need for reload case @@ -6541,7 +6633,7 @@ bool PlayerCondition::Meets(Player const * player) const { Unit::AuraMap const& auras = player->GetAuras(); for(Unit::AuraMap::const_iterator itr = auras.begin(); itr != auras.end(); ++itr) - if((itr->second->GetSpellProto()->Attributes & 0x1000010) && itr->second->GetSpellProto()->SpellVisual==3580) + if((itr->second->GetSpellProto()->Attributes & 0x1000010) && itr->second->GetSpellProto()->SpellVisual[0]==3580) return true; return false; } @@ -6709,7 +6801,7 @@ SkillRangeType GetSkillRangeType(SkillLineEntry const *pSkill, bool racial) return SKILL_RANGE_MONO; case SKILL_CATEGORY_ARMOR: case SKILL_CATEGORY_CLASS: - if(pSkill->id != SKILL_POISONS && pSkill->id != SKILL_LOCKPICKING) + if(pSkill->id != SKILL_LOCKPICKING) return SKILL_RANGE_MONO; else return SKILL_RANGE_LEVEL; @@ -6724,7 +6816,7 @@ SkillRangeType GetSkillRangeType(SkillLineEntry const *pSkill, bool racial) return SKILL_RANGE_MONO; default: case SKILL_CATEGORY_ATTRIBUTES: //not found in dbc - case SKILL_CATEGORY_NOT_DISPLAYED: //only GENEREC(DND) + case SKILL_CATEGORY_GENERIC: //only GENERIC(DND) return SKILL_RANGE_NONE; } } @@ -6792,7 +6884,7 @@ void ObjectMgr::LoadGameTele() sLog.outString( ">> Loaded %u game tele's", count ); } -GameTele const* ObjectMgr::GetGameTele(std::string name) const +GameTele const* ObjectMgr::GetGameTele(const std::string& name) const { // explicit name case std::wstring wname; @@ -6835,7 +6927,7 @@ bool ObjectMgr::AddGameTele(GameTele& tele) new_id,tele.position_x,tele.position_y,tele.position_z,tele.orientation,tele.mapId,tele.name.c_str()); } -bool ObjectMgr::DeleteGameTele(std::string name) +bool ObjectMgr::DeleteGameTele(const std::string& name) { // explicit name case std::wstring wname; @@ -7243,7 +7335,7 @@ uint32 ObjectMgr::GetScriptId(const char *name) if(!name) return 0; ScriptNameMap::const_iterator itr = std::lower_bound(m_scriptNames.begin(), m_scriptNames.end(), name); - if(itr == m_scriptNames.end()) return 0; + if(itr == m_scriptNames.end() || *itr != name) return 0; return itr - m_scriptNames.begin(); } diff --git a/src/game/ObjectMgr.h b/src/game/ObjectMgr.h index 1c408ce63..825237bfc 100644 --- a/src/game/ObjectMgr.h +++ b/src/game/ObjectMgr.h @@ -242,6 +242,8 @@ typedef std::list CacheNpcOptionList; typedef UNORDERED_MAP CacheVendorItemMap; typedef UNORDERED_MAP CacheTrainerSpellMap; +typedef std::list AchievementCriteriaEntryList; + enum SkillRangeType { SKILL_RANGE_LANGUAGE, // 300..300 @@ -282,11 +284,11 @@ class ObjectMgr typedef std::set< Group * > GroupSet; typedef std::set< Guild * > GuildSet; - typedef std::set< ArenaTeam * > ArenaTeamSet; + + typedef UNORDERED_MAP ArenaTeamMap; typedef UNORDERED_MAP QuestMap; - typedef UNORDERED_MAP AreaTriggerMap; typedef UNORDERED_MAP AreaTriggerScriptMap; @@ -313,16 +315,18 @@ class ObjectMgr Guild* GetGuildByLeader(uint64 const&guid) const; Guild* GetGuildById(const uint32 GuildId) const; - Guild* GetGuildByName(std::string guildname) const; + Guild* GetGuildByName(const std::string& guildname) const; std::string GetGuildNameById(const uint32 GuildId) const; void AddGuild(Guild* guild) { mGuildSet.insert( guild ); } void RemoveGuild(Guild* guild) { mGuildSet.erase( guild ); } - ArenaTeam* GetArenaTeamById(const uint32 ArenaTeamId) const; - ArenaTeam* GetArenaTeamByName(std::string ArenaTeamName) const; - ArenaTeam* GetArenaTeamByCapitan(uint64 const& guid) const; - void AddArenaTeam(ArenaTeam* arenateam) { mArenaTeamSet.insert( arenateam ); } - void RemoveArenaTeam(ArenaTeam* arenateam) { mArenaTeamSet.erase( arenateam ); } + ArenaTeam* GetArenaTeamById(const uint32 arenateamid) const; + ArenaTeam* GetArenaTeamByName(const std::string& arenateamname) const; + ArenaTeam* GetArenaTeamByCaptain(uint64 const& guid) const; + void AddArenaTeam(ArenaTeam* arenaTeam); + void RemoveArenaTeam(ArenaTeam* arenaTeam); + ArenaTeamMap::iterator GetArenaTeamMapBegin() { return mArenaTeamMap.begin(); } + ArenaTeamMap::iterator GetArenaTeamMapEnd() { return mArenaTeamMap.end(); } static CreatureInfo const *GetCreatureTemplate( uint32 id ); CreatureModelInfo const *GetCreatureModelInfo( uint32 modelid ); @@ -405,7 +409,7 @@ class ObjectMgr bool GetPlayerNameByGUID(const uint64 &guid, std::string &name) const; uint32 GetPlayerTeamByGUID(const uint64 &guid) const; uint32 GetPlayerAccountIdByGUID(const uint64 &guid) const; - uint32 GetPlayerAccountIdByPlayerName(std::string name) const; + uint32 GetPlayerAccountIdByPlayerName(const std::string& name) const; uint32 GetNearestTaxiNode( float x, float y, float z, uint32 mapid ); void GetTaxiPath( uint32 source, uint32 destination, uint32 &path, uint32 &cost); @@ -562,6 +566,7 @@ class ObjectMgr void LoadNpcTextId(); void LoadVendors(); void LoadTrainerSpell(); + void LoadCompletedAchievements(); std::string GeneratePetName(uint32 entry); uint32 GetBaseXP(uint32 level); @@ -698,15 +703,15 @@ class ObjectMgr // reserved names void LoadReservedPlayersNames(); - bool IsReservedName(std::string name) const + bool IsReservedName(const std::string& name) const { return m_ReservedNames.find(name) != m_ReservedNames.end(); } // name with valid structure and symbols - static bool IsValidName( std::string name, bool create = false ); - static bool IsValidCharterName( std::string name ); - static bool IsValidPetName( std::string name ); + static bool IsValidName( const std::string& name, bool create = false ); + static bool IsValidCharterName( const std::string& name ); + static bool IsValidPetName( const std::string& name ); static bool CheckDeclinedNames(std::wstring mainpart, DeclinedName const& names); @@ -730,10 +735,10 @@ class ObjectMgr if(itr==m_GameTeleMap.end()) return NULL; return &itr->second; } - GameTele const* GetGameTele(std::string name) const; + GameTele const* GetGameTele(const std::string& name) const; GameTeleMap const& GetGameTeleMap() const { return m_GameTeleMap; } bool AddGameTele(GameTele& data); - bool DeleteGameTele(std::string name); + bool DeleteGameTele(const std::string& name); CacheNpcOptionList const& GetNpcOptions() const { return m_mCacheNpcOptionList; } @@ -766,6 +771,9 @@ class ObjectMgr void AddVendorItem(uint32 entry,uint32 item, uint32 maxcount, uint32 incrtime, uint32 ExtendedCost); bool RemoveVendorItem(uint32 entry,uint32 item); bool IsVendorItemValid( uint32 vendor_entry, uint32 item, uint32 maxcount, uint32 ptime, uint32 ExtendedCost, Player* pl = NULL, std::set* skip_vendors = NULL ) const; + void LoadAchievementCriteriaList(); + AchievementCriteriaEntryList const& GetAchievementCriteriaByType(AchievementCriteriaTypes type); + std::set allCompletedAchievements; void LoadScriptNames(); ScriptNameMap &GetScriptNames() { return m_scriptNames; } @@ -785,6 +793,7 @@ class ObjectMgr uint32 m_hiCharGuid; uint32 m_hiCreatureGuid; uint32 m_hiPetGuid; + uint32 m_hiVehicleGuid; uint32 m_hiItemGuid; uint32 m_hiGoGuid; uint32 m_hiDoGuid; @@ -801,7 +810,7 @@ class ObjectMgr GroupSet mGroupSet; GuildSet mGuildSet; - ArenaTeamSet mArenaTeamSet; + ArenaTeamMap mArenaTeamMap; ItemMap mItems; ItemMap mAitems; @@ -892,6 +901,9 @@ class ObjectMgr CacheNpcTextIdMap m_mCacheNpcTextIdMap; CacheVendorItemMap m_mCacheVendorItemMap; CacheTrainerSpellMap m_mCacheTrainerSpellMap; + + // store achievement criterias by type to speed up lookup + AchievementCriteriaEntryList m_AchievementCriteriasByType[ACHIEVEMENT_CRITERIA_TYPE_TOTAL]; }; #define objmgr MaNGOS::Singleton::Instance() diff --git a/src/game/Opcodes.cpp b/src/game/Opcodes.cpp index fba347199..37f1bd344 100644 --- a/src/game/Opcodes.cpp +++ b/src/game/Opcodes.cpp @@ -26,1064 +26,1194 @@ /// Correspondence between opcodes and their names OpcodeHandler opcodeTable[NUM_MSG_TYPES] = { - /*0x000*/ { "MSG_NULL_ACTION", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x001*/ { "CMSG_BOOTME", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x002*/ { "CMSG_DBLOOKUP", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x003*/ { "SMSG_DBLOOKUP", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x004*/ { "CMSG_QUERY_OBJECT_POSITION", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x005*/ { "SMSG_QUERY_OBJECT_POSITION", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x006*/ { "CMSG_QUERY_OBJECT_ROTATION", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x007*/ { "SMSG_QUERY_OBJECT_ROTATION", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x008*/ { "CMSG_WORLD_TELEPORT", STATUS_LOGGEDIN, &WorldSession::HandleWorldTeleportOpcode }, - /*0x009*/ { "CMSG_TELEPORT_TO_UNIT", STATUS_LOGGEDIN, &WorldSession::Handle_NULL }, - /*0x00A*/ { "CMSG_ZONE_MAP", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x00B*/ { "SMSG_ZONE_MAP", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x00C*/ { "CMSG_DEBUG_CHANGECELLZONE", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x00D*/ { "CMSG_EMBLAZON_TABARD_OBSOLETE", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x00E*/ { "CMSG_UNEMBLAZON_TABARD_OBSOLETE", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x00F*/ { "CMSG_RECHARGE", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x010*/ { "CMSG_LEARN_SPELL", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x011*/ { "CMSG_CREATEMONSTER", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x012*/ { "CMSG_DESTROYMONSTER", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x013*/ { "CMSG_CREATEITEM", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x014*/ { "CMSG_CREATEGAMEOBJECT", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x015*/ { "SMSG_CHECK_FOR_BOTS", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x016*/ { "CMSG_MAKEMONSTERATTACKGUID", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x017*/ { "CMSG_BOT_DETECTED2", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x018*/ { "CMSG_FORCEACTION", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x019*/ { "CMSG_FORCEACTIONONOTHER", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x01A*/ { "CMSG_FORCEACTIONSHOW", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x01B*/ { "SMSG_FORCEACTIONSHOW", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x01C*/ { "CMSG_PETGODMODE", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x01D*/ { "SMSG_PETGODMODE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x01E*/ { "SMSG_DEBUGINFOSPELLMISS_OBSOLETE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x01F*/ { "CMSG_WEATHER_SPEED_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x020*/ { "CMSG_UNDRESSPLAYER", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x021*/ { "CMSG_BEASTMASTER", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x022*/ { "CMSG_GODMODE", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x023*/ { "SMSG_GODMODE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x024*/ { "CMSG_CHEAT_SETMONEY", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x025*/ { "CMSG_LEVEL_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x026*/ { "CMSG_PET_LEVEL_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x027*/ { "CMSG_SET_WORLDSTATE", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x028*/ { "CMSG_COOLDOWN_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x029*/ { "CMSG_USE_SKILL_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x02A*/ { "CMSG_FLAG_QUEST", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x02B*/ { "CMSG_FLAG_QUEST_FINISH", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x02C*/ { "CMSG_CLEAR_QUEST", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x02D*/ { "CMSG_SEND_EVENT", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x02E*/ { "CMSG_DEBUG_AISTATE", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x02F*/ { "SMSG_DEBUG_AISTATE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x030*/ { "CMSG_DISABLE_PVP_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x031*/ { "CMSG_ADVANCE_SPAWN_TIME", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x032*/ { "CMSG_PVP_PORT_OBSOLETE", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x033*/ { "CMSG_AUTH_SRP6_BEGIN", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x034*/ { "CMSG_AUTH_SRP6_PROOF", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x035*/ { "CMSG_AUTH_SRP6_RECODE", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x036*/ { "CMSG_CHAR_CREATE", STATUS_AUTHED, &WorldSession::HandleCharCreateOpcode }, - /*0x037*/ { "CMSG_CHAR_ENUM", STATUS_AUTHED, &WorldSession::HandleCharEnumOpcode }, - /*0x038*/ { "CMSG_CHAR_DELETE", STATUS_AUTHED, &WorldSession::HandleCharDeleteOpcode }, - /*0x039*/ { "SMSG_AUTH_SRP6_RESPONSE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x03A*/ { "SMSG_CHAR_CREATE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x03B*/ { "SMSG_CHAR_ENUM", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x03C*/ { "SMSG_CHAR_DELETE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x03D*/ { "CMSG_PLAYER_LOGIN", STATUS_AUTHED, &WorldSession::HandlePlayerLoginOpcode }, - /*0x03E*/ { "SMSG_NEW_WORLD", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x03F*/ { "SMSG_TRANSFER_PENDING", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x040*/ { "SMSG_TRANSFER_ABORTED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x041*/ { "SMSG_CHARACTER_LOGIN_FAILED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x042*/ { "SMSG_LOGIN_SETTIMESPEED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x043*/ { "SMSG_GAMETIME_UPDATE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x044*/ { "CMSG_GAMETIME_SET", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x045*/ { "SMSG_GAMETIME_SET", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x046*/ { "CMSG_GAMESPEED_SET", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x047*/ { "SMSG_GAMESPEED_SET", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x048*/ { "CMSG_SERVERTIME", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x049*/ { "SMSG_SERVERTIME", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x04A*/ { "CMSG_PLAYER_LOGOUT", STATUS_LOGGEDIN, &WorldSession::HandlePlayerLogoutOpcode }, - /*0x04B*/ { "CMSG_LOGOUT_REQUEST", STATUS_LOGGEDIN, &WorldSession::HandleLogoutRequestOpcode }, - /*0x04C*/ { "SMSG_LOGOUT_RESPONSE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x04D*/ { "SMSG_LOGOUT_COMPLETE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x04E*/ { "CMSG_LOGOUT_CANCEL", STATUS_LOGGEDIN, &WorldSession::HandleLogoutCancelOpcode }, - /*0x04F*/ { "SMSG_LOGOUT_CANCEL_ACK", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x050*/ { "CMSG_NAME_QUERY", STATUS_LOGGEDIN, &WorldSession::HandleNameQueryOpcode }, - /*0x051*/ { "SMSG_NAME_QUERY_RESPONSE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x052*/ { "CMSG_PET_NAME_QUERY", STATUS_LOGGEDIN, &WorldSession::HandlePetNameQuery }, - /*0x053*/ { "SMSG_PET_NAME_QUERY_RESPONSE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x054*/ { "CMSG_GUILD_QUERY", STATUS_AUTHED, &WorldSession::HandleGuildQueryOpcode }, - /*0x055*/ { "SMSG_GUILD_QUERY_RESPONSE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x056*/ { "CMSG_ITEM_QUERY_SINGLE", STATUS_LOGGEDIN, &WorldSession::HandleItemQuerySingleOpcode }, - /*0x057*/ { "CMSG_ITEM_QUERY_MULTIPLE", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x058*/ { "SMSG_ITEM_QUERY_SINGLE_RESPONSE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x059*/ { "SMSG_ITEM_QUERY_MULTIPLE_RESPONSE",STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x05A*/ { "CMSG_PAGE_TEXT_QUERY", STATUS_LOGGEDIN, &WorldSession::HandlePageQueryOpcode }, - /*0x05B*/ { "SMSG_PAGE_TEXT_QUERY_RESPONSE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x05C*/ { "CMSG_QUEST_QUERY", STATUS_LOGGEDIN, &WorldSession::HandleQuestQueryOpcode }, - /*0x05D*/ { "SMSG_QUEST_QUERY_RESPONSE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x05E*/ { "CMSG_GAMEOBJECT_QUERY", STATUS_LOGGEDIN, &WorldSession::HandleGameObjectQueryOpcode }, - /*0x05F*/ { "SMSG_GAMEOBJECT_QUERY_RESPONSE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x060*/ { "CMSG_CREATURE_QUERY", STATUS_LOGGEDIN, &WorldSession::HandleCreatureQueryOpcode }, - /*0x061*/ { "SMSG_CREATURE_QUERY_RESPONSE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x062*/ { "CMSG_WHO", STATUS_LOGGEDIN, &WorldSession::HandleWhoOpcode }, - /*0x063*/ { "SMSG_WHO", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x064*/ { "CMSG_WHOIS", STATUS_LOGGEDIN, &WorldSession::HandleWhoisOpcode }, - /*0x065*/ { "SMSG_WHOIS", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x066*/ { "CMSG_CONTACT_LIST", STATUS_LOGGEDIN, &WorldSession::HandleFriendListOpcode }, - /*0x067*/ { "SMSG_CONTACT_LIST", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x068*/ { "SMSG_FRIEND_STATUS", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x069*/ { "CMSG_ADD_FRIEND", STATUS_LOGGEDIN, &WorldSession::HandleAddFriendOpcode }, - /*0x06A*/ { "CMSG_DEL_FRIEND", STATUS_LOGGEDIN, &WorldSession::HandleDelFriendOpcode }, - /*0x06B*/ { "CMSG_SET_CONTACT_NOTES", STATUS_LOGGEDIN, &WorldSession::HandleSetFriendNoteOpcode }, - /*0x06C*/ { "CMSG_ADD_IGNORE", STATUS_LOGGEDIN, &WorldSession::HandleAddIgnoreOpcode }, - /*0x06D*/ { "CMSG_DEL_IGNORE", STATUS_LOGGEDIN, &WorldSession::HandleDelIgnoreOpcode }, - /*0x06E*/ { "CMSG_GROUP_INVITE", STATUS_LOGGEDIN, &WorldSession::HandleGroupInviteOpcode }, - /*0x06F*/ { "SMSG_GROUP_INVITE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x070*/ { "CMSG_GROUP_CANCEL", STATUS_LOGGEDIN, &WorldSession::Handle_Deprecated }, - /*0x071*/ { "SMSG_GROUP_CANCEL", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x072*/ { "CMSG_GROUP_ACCEPT", STATUS_LOGGEDIN, &WorldSession::HandleGroupAcceptOpcode }, - /*0x073*/ { "CMSG_GROUP_DECLINE", STATUS_LOGGEDIN, &WorldSession::HandleGroupDeclineOpcode }, - /*0x074*/ { "SMSG_GROUP_DECLINE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x075*/ { "CMSG_GROUP_UNINVITE", STATUS_LOGGEDIN, &WorldSession::HandleGroupUninviteNameOpcode }, - /*0x076*/ { "CMSG_GROUP_UNINVITE_GUID", STATUS_LOGGEDIN, &WorldSession::HandleGroupUninviteGuidOpcode }, - /*0x077*/ { "SMSG_GROUP_UNINVITE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x078*/ { "CMSG_GROUP_SET_LEADER", STATUS_LOGGEDIN, &WorldSession::HandleGroupSetLeaderOpcode }, - /*0x079*/ { "SMSG_GROUP_SET_LEADER", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x07A*/ { "CMSG_LOOT_METHOD", STATUS_LOGGEDIN, &WorldSession::HandleLootMethodOpcode }, - /*0x07B*/ { "CMSG_GROUP_DISBAND", STATUS_LOGGEDIN, &WorldSession::HandleGroupLeaveOpcode }, - /*0x07C*/ { "SMSG_GROUP_DESTROYED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x07D*/ { "SMSG_GROUP_LIST", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x07E*/ { "SMSG_PARTY_MEMBER_STATS", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x07F*/ { "SMSG_PARTY_COMMAND_RESULT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x080*/ { "UMSG_UPDATE_GROUP_MEMBERS", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x081*/ { "CMSG_GUILD_CREATE", STATUS_LOGGEDIN, &WorldSession::HandleGuildCreateOpcode }, - /*0x082*/ { "CMSG_GUILD_INVITE", STATUS_LOGGEDIN, &WorldSession::HandleGuildInviteOpcode }, - /*0x083*/ { "SMSG_GUILD_INVITE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x084*/ { "CMSG_GUILD_ACCEPT", STATUS_LOGGEDIN, &WorldSession::HandleGuildAcceptOpcode }, - /*0x085*/ { "CMSG_GUILD_DECLINE", STATUS_LOGGEDIN, &WorldSession::HandleGuildDeclineOpcode }, - /*0x086*/ { "SMSG_GUILD_DECLINE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x087*/ { "CMSG_GUILD_INFO", STATUS_LOGGEDIN, &WorldSession::HandleGuildInfoOpcode }, - /*0x088*/ { "SMSG_GUILD_INFO", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x089*/ { "CMSG_GUILD_ROSTER", STATUS_LOGGEDIN, &WorldSession::HandleGuildRosterOpcode }, - /*0x08A*/ { "SMSG_GUILD_ROSTER", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x08B*/ { "CMSG_GUILD_PROMOTE", STATUS_LOGGEDIN, &WorldSession::HandleGuildPromoteOpcode }, - /*0x08C*/ { "CMSG_GUILD_DEMOTE", STATUS_LOGGEDIN, &WorldSession::HandleGuildDemoteOpcode }, - /*0x08D*/ { "CMSG_GUILD_LEAVE", STATUS_LOGGEDIN, &WorldSession::HandleGuildLeaveOpcode }, - /*0x08E*/ { "CMSG_GUILD_REMOVE", STATUS_LOGGEDIN, &WorldSession::HandleGuildRemoveOpcode }, - /*0x08F*/ { "CMSG_GUILD_DISBAND", STATUS_LOGGEDIN, &WorldSession::HandleGuildDisbandOpcode }, - /*0x090*/ { "CMSG_GUILD_LEADER", STATUS_LOGGEDIN, &WorldSession::HandleGuildLeaderOpcode }, - /*0x091*/ { "CMSG_GUILD_MOTD", STATUS_LOGGEDIN, &WorldSession::HandleGuildMOTDOpcode }, - /*0x092*/ { "SMSG_GUILD_EVENT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x093*/ { "SMSG_GUILD_COMMAND_RESULT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x094*/ { "UMSG_UPDATE_GUILD", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x095*/ { "CMSG_MESSAGECHAT", STATUS_LOGGEDIN, &WorldSession::HandleMessagechatOpcode }, - /*0x096*/ { "SMSG_MESSAGECHAT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x097*/ { "CMSG_JOIN_CHANNEL", STATUS_LOGGEDIN, &WorldSession::HandleChannelJoin }, - /*0x098*/ { "CMSG_LEAVE_CHANNEL", STATUS_LOGGEDIN, &WorldSession::HandleChannelLeave }, - /*0x099*/ { "SMSG_CHANNEL_NOTIFY", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x09A*/ { "CMSG_CHANNEL_LIST", STATUS_LOGGEDIN, &WorldSession::HandleChannelList }, - /*0x09B*/ { "SMSG_CHANNEL_LIST", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x09C*/ { "CMSG_CHANNEL_PASSWORD", STATUS_LOGGEDIN, &WorldSession::HandleChannelPassword }, - /*0x09D*/ { "CMSG_CHANNEL_SET_OWNER", STATUS_LOGGEDIN, &WorldSession::HandleChannelSetOwner }, - /*0x09E*/ { "CMSG_CHANNEL_OWNER", STATUS_LOGGEDIN, &WorldSession::HandleChannelOwner }, - /*0x09F*/ { "CMSG_CHANNEL_MODERATOR", STATUS_LOGGEDIN, &WorldSession::HandleChannelModerator }, - /*0x0A0*/ { "CMSG_CHANNEL_UNMODERATOR", STATUS_LOGGEDIN, &WorldSession::HandleChannelUnmoderator }, - /*0x0A1*/ { "CMSG_CHANNEL_MUTE", STATUS_LOGGEDIN, &WorldSession::HandleChannelMute }, - /*0x0A2*/ { "CMSG_CHANNEL_UNMUTE", STATUS_LOGGEDIN, &WorldSession::HandleChannelUnmute }, - /*0x0A3*/ { "CMSG_CHANNEL_INVITE", STATUS_LOGGEDIN, &WorldSession::HandleChannelInvite }, - /*0x0A4*/ { "CMSG_CHANNEL_KICK", STATUS_LOGGEDIN, &WorldSession::HandleChannelKick }, - /*0x0A5*/ { "CMSG_CHANNEL_BAN", STATUS_LOGGEDIN, &WorldSession::HandleChannelBan }, - /*0x0A6*/ { "CMSG_CHANNEL_UNBAN", STATUS_LOGGEDIN, &WorldSession::HandleChannelUnban }, - /*0x0A7*/ { "CMSG_CHANNEL_ANNOUNCEMENTS", STATUS_LOGGEDIN, &WorldSession::HandleChannelAnnounce }, - /*0x0A8*/ { "CMSG_CHANNEL_MODERATE", STATUS_LOGGEDIN, &WorldSession::HandleChannelModerate }, - /*0x0A9*/ { "SMSG_UPDATE_OBJECT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x0AA*/ { "SMSG_DESTROY_OBJECT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x0AB*/ { "CMSG_USE_ITEM", STATUS_LOGGEDIN, &WorldSession::HandleUseItemOpcode }, - /*0x0AC*/ { "CMSG_OPEN_ITEM", STATUS_LOGGEDIN, &WorldSession::HandleOpenItemOpcode }, - /*0x0AD*/ { "CMSG_READ_ITEM", STATUS_LOGGEDIN, &WorldSession::HandleReadItem }, - /*0x0AE*/ { "SMSG_READ_ITEM_OK", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x0AF*/ { "SMSG_READ_ITEM_FAILED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x0B0*/ { "SMSG_ITEM_COOLDOWN", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x0B1*/ { "CMSG_GAMEOBJ_USE", STATUS_LOGGEDIN, &WorldSession::HandleGameObjectUseOpcode }, - /*0x0B2*/ { "CMSG_GAMEOBJ_CHAIR_USE_OBSOLETE", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x0B3*/ { "SMSG_GAMEOBJECT_CUSTOM_ANIM", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x0B4*/ { "CMSG_AREATRIGGER", STATUS_LOGGEDIN, &WorldSession::HandleAreaTriggerOpcode }, - /*0x0B5*/ { "MSG_MOVE_START_FORWARD", STATUS_LOGGEDIN, &WorldSession::HandleMovementOpcodes }, - /*0x0B6*/ { "MSG_MOVE_START_BACKWARD", STATUS_LOGGEDIN, &WorldSession::HandleMovementOpcodes }, - /*0x0B7*/ { "MSG_MOVE_STOP", STATUS_LOGGEDIN, &WorldSession::HandleMovementOpcodes }, - /*0x0B8*/ { "MSG_MOVE_START_STRAFE_LEFT", STATUS_LOGGEDIN, &WorldSession::HandleMovementOpcodes }, - /*0x0B9*/ { "MSG_MOVE_START_STRAFE_RIGHT", STATUS_LOGGEDIN, &WorldSession::HandleMovementOpcodes }, - /*0x0BA*/ { "MSG_MOVE_STOP_STRAFE", STATUS_LOGGEDIN, &WorldSession::HandleMovementOpcodes }, - /*0x0BB*/ { "MSG_MOVE_JUMP", STATUS_LOGGEDIN, &WorldSession::HandleMovementOpcodes }, - /*0x0BC*/ { "MSG_MOVE_START_TURN_LEFT", STATUS_LOGGEDIN, &WorldSession::HandleMovementOpcodes }, - /*0x0BD*/ { "MSG_MOVE_START_TURN_RIGHT", STATUS_LOGGEDIN, &WorldSession::HandleMovementOpcodes }, - /*0x0BE*/ { "MSG_MOVE_STOP_TURN", STATUS_LOGGEDIN, &WorldSession::HandleMovementOpcodes }, - /*0x0BF*/ { "MSG_MOVE_START_PITCH_UP", STATUS_LOGGEDIN, &WorldSession::HandleMovementOpcodes }, - /*0x0C0*/ { "MSG_MOVE_START_PITCH_DOWN", STATUS_LOGGEDIN, &WorldSession::HandleMovementOpcodes }, - /*0x0C1*/ { "MSG_MOVE_STOP_PITCH", STATUS_LOGGEDIN, &WorldSession::HandleMovementOpcodes }, - /*0x0C2*/ { "MSG_MOVE_SET_RUN_MODE", STATUS_LOGGEDIN, &WorldSession::HandleMovementOpcodes }, - /*0x0C3*/ { "MSG_MOVE_SET_WALK_MODE", STATUS_LOGGEDIN, &WorldSession::HandleMovementOpcodes }, - /*0x0C4*/ { "MSG_MOVE_TOGGLE_LOGGING", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x0C5*/ { "MSG_MOVE_TELEPORT", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x0C6*/ { "MSG_MOVE_TELEPORT_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x0C7*/ { "MSG_MOVE_TELEPORT_ACK", STATUS_LOGGEDIN, &WorldSession::HandleMoveTeleportAck }, - /*0x0C8*/ { "MSG_MOVE_TOGGLE_FALL_LOGGING", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x0C9*/ { "MSG_MOVE_FALL_LAND", STATUS_LOGGEDIN, &WorldSession::HandleMovementOpcodes }, - /*0x0CA*/ { "MSG_MOVE_START_SWIM", STATUS_LOGGEDIN, &WorldSession::HandleMovementOpcodes }, - /*0x0CB*/ { "MSG_MOVE_STOP_SWIM", STATUS_LOGGEDIN, &WorldSession::HandleMovementOpcodes }, - /*0x0CC*/ { "MSG_MOVE_SET_RUN_SPEED_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x0CD*/ { "MSG_MOVE_SET_RUN_SPEED", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x0CE*/ { "MSG_MOVE_SET_RUN_BACK_SPEED_CHEAT",STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x0CF*/ { "MSG_MOVE_SET_RUN_BACK_SPEED", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x0D0*/ { "MSG_MOVE_SET_WALK_SPEED_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x0D1*/ { "MSG_MOVE_SET_WALK_SPEED", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x0D2*/ { "MSG_MOVE_SET_SWIM_SPEED_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x0D3*/ { "MSG_MOVE_SET_SWIM_SPEED", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x0D4*/ { "MSG_MOVE_SET_SWIM_BACK_SPEED_CHEAT",STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x0D5*/ { "MSG_MOVE_SET_SWIM_BACK_SPEED", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x0D6*/ { "MSG_MOVE_SET_ALL_SPEED_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x0D7*/ { "MSG_MOVE_SET_TURN_RATE_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x0D8*/ { "MSG_MOVE_SET_TURN_RATE", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x0D9*/ { "MSG_MOVE_TOGGLE_COLLISION_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x0DA*/ { "MSG_MOVE_SET_FACING", STATUS_LOGGEDIN, &WorldSession::HandleMovementOpcodes }, - /*0x0DB*/ { "MSG_MOVE_SET_PITCH", STATUS_LOGGEDIN, &WorldSession::HandleMovementOpcodes }, - /*0x0DC*/ { "MSG_MOVE_WORLDPORT_ACK", STATUS_TRANSFER_PENDING, &WorldSession::HandleMoveWorldportAckOpcode}, - /*0x0DD*/ { "SMSG_MONSTER_MOVE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x0DE*/ { "SMSG_MOVE_WATER_WALK", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x0DF*/ { "SMSG_MOVE_LAND_WALK", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x0E0*/ { "MSG_MOVE_SET_RAW_POSITION_ACK", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x0E1*/ { "CMSG_MOVE_SET_RAW_POSITION", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x0E2*/ { "SMSG_FORCE_RUN_SPEED_CHANGE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x0E3*/ { "CMSG_FORCE_RUN_SPEED_CHANGE_ACK", STATUS_LOGGEDIN, &WorldSession::HandleForceSpeedChangeAck }, - /*0x0E4*/ { "SMSG_FORCE_RUN_BACK_SPEED_CHANGE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x0E5*/ { "CMSG_FORCE_RUN_BACK_SPEED_CHANGE_ACK",STATUS_LOGGEDIN,&WorldSession::HandleForceSpeedChangeAck }, - /*0x0E6*/ { "SMSG_FORCE_SWIM_SPEED_CHANGE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x0E7*/ { "CMSG_FORCE_SWIM_SPEED_CHANGE_ACK", STATUS_LOGGEDIN, &WorldSession::HandleForceSpeedChangeAck }, - /*0x0E8*/ { "SMSG_FORCE_MOVE_ROOT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x0E9*/ { "CMSG_FORCE_MOVE_ROOT_ACK", STATUS_LOGGEDIN, &WorldSession::HandleMoveRootAck }, - /*0x0EA*/ { "SMSG_FORCE_MOVE_UNROOT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x0EB*/ { "CMSG_FORCE_MOVE_UNROOT_ACK", STATUS_LOGGEDIN, &WorldSession::HandleMoveUnRootAck }, - /*0x0EC*/ { "MSG_MOVE_ROOT", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x0ED*/ { "MSG_MOVE_UNROOT", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x0EE*/ { "MSG_MOVE_HEARTBEAT", STATUS_LOGGEDIN, &WorldSession::HandleMovementOpcodes }, - /*0x0EF*/ { "SMSG_MOVE_KNOCK_BACK", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x0F0*/ { "CMSG_MOVE_KNOCK_BACK_ACK", STATUS_LOGGEDIN, &WorldSession::HandleMoveKnockBackAck }, - /*0x0F1*/ { "MSG_MOVE_KNOCK_BACK", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x0F2*/ { "SMSG_MOVE_FEATHER_FALL", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x0F3*/ { "SMSG_MOVE_NORMAL_FALL", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x0F4*/ { "SMSG_MOVE_SET_HOVER", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x0F5*/ { "SMSG_MOVE_UNSET_HOVER", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x0F6*/ { "CMSG_MOVE_HOVER_ACK", STATUS_LOGGEDIN, &WorldSession::HandleMoveHoverAck }, - /*0x0F7*/ { "MSG_MOVE_HOVER", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x0F8*/ { "CMSG_TRIGGER_CINEMATIC_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x0F9*/ { "CMSG_OPENING_CINEMATIC", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x0FA*/ { "SMSG_TRIGGER_CINEMATIC", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x0FB*/ { "CMSG_NEXT_CINEMATIC_CAMERA", STATUS_LOGGEDIN, &WorldSession::HandleNextCinematicCamera }, - /*0x0FC*/ { "CMSG_COMPLETE_CINEMATIC", STATUS_LOGGEDIN, &WorldSession::HandleCompleteCinema }, - /*0x0FD*/ { "SMSG_TUTORIAL_FLAGS", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x0FE*/ { "CMSG_TUTORIAL_FLAG", STATUS_LOGGEDIN, &WorldSession::HandleTutorialFlag }, - /*0x0FF*/ { "CMSG_TUTORIAL_CLEAR", STATUS_LOGGEDIN, &WorldSession::HandleTutorialClear }, - /*0x100*/ { "CMSG_TUTORIAL_RESET", STATUS_LOGGEDIN, &WorldSession::HandleTutorialReset }, - /*0x101*/ { "CMSG_STANDSTATECHANGE", STATUS_LOGGEDIN, &WorldSession::HandleStandStateChangeOpcode }, - /*0x102*/ { "CMSG_EMOTE", STATUS_LOGGEDIN, &WorldSession::HandleEmoteOpcode }, - /*0x103*/ { "SMSG_EMOTE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x104*/ { "CMSG_TEXT_EMOTE", STATUS_LOGGEDIN, &WorldSession::HandleTextEmoteOpcode }, - /*0x105*/ { "SMSG_TEXT_EMOTE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x106*/ { "CMSG_AUTOEQUIP_GROUND_ITEM", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x107*/ { "CMSG_AUTOSTORE_GROUND_ITEM", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x108*/ { "CMSG_AUTOSTORE_LOOT_ITEM", STATUS_LOGGEDIN, &WorldSession::HandleAutostoreLootItemOpcode }, - /*0x109*/ { "CMSG_STORE_LOOT_IN_SLOT", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x10A*/ { "CMSG_AUTOEQUIP_ITEM", STATUS_LOGGEDIN, &WorldSession::HandleAutoEquipItemOpcode }, - /*0x10B*/ { "CMSG_AUTOSTORE_BAG_ITEM", STATUS_LOGGEDIN, &WorldSession::HandleAutoStoreBagItemOpcode }, - /*0x10C*/ { "CMSG_SWAP_ITEM", STATUS_LOGGEDIN, &WorldSession::HandleSwapItem }, - /*0x10D*/ { "CMSG_SWAP_INV_ITEM", STATUS_LOGGEDIN, &WorldSession::HandleSwapInvItemOpcode }, - /*0x10E*/ { "CMSG_SPLIT_ITEM", STATUS_LOGGEDIN, &WorldSession::HandleSplitItemOpcode }, - /*0x10F*/ { "CMSG_AUTOEQUIP_ITEM_SLOT", STATUS_LOGGEDIN, &WorldSession::HandleAutoEquipItemSlotOpcode }, - /*0x110*/ { "OBSOLETE_DROP_ITEM", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x111*/ { "CMSG_DESTROYITEM", STATUS_LOGGEDIN, &WorldSession::HandleDestroyItemOpcode }, - /*0x112*/ { "SMSG_INVENTORY_CHANGE_FAILURE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x113*/ { "SMSG_OPEN_CONTAINER", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x114*/ { "CMSG_INSPECT", STATUS_LOGGEDIN, &WorldSession::HandleInspectOpcode }, - /*0x115*/ { "SMSG_INSPECT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x116*/ { "CMSG_INITIATE_TRADE", STATUS_LOGGEDIN, &WorldSession::HandleInitiateTradeOpcode }, - /*0x117*/ { "CMSG_BEGIN_TRADE", STATUS_LOGGEDIN, &WorldSession::HandleBeginTradeOpcode }, - /*0x118*/ { "CMSG_BUSY_TRADE", STATUS_LOGGEDIN, &WorldSession::HandleBusyTradeOpcode }, - /*0x119*/ { "CMSG_IGNORE_TRADE", STATUS_LOGGEDIN, &WorldSession::HandleIgnoreTradeOpcode }, - /*0x11A*/ { "CMSG_ACCEPT_TRADE", STATUS_LOGGEDIN, &WorldSession::HandleAcceptTradeOpcode }, - /*0x11B*/ { "CMSG_UNACCEPT_TRADE", STATUS_LOGGEDIN, &WorldSession::HandleUnacceptTradeOpcode }, - /*0x11C*/ { "CMSG_CANCEL_TRADE", STATUS_AUTHED, &WorldSession::HandleCancelTradeOpcode }, - /*0x11D*/ { "CMSG_SET_TRADE_ITEM", STATUS_LOGGEDIN, &WorldSession::HandleSetTradeItemOpcode }, - /*0x11E*/ { "CMSG_CLEAR_TRADE_ITEM", STATUS_LOGGEDIN, &WorldSession::HandleClearTradeItemOpcode }, - /*0x11F*/ { "CMSG_SET_TRADE_GOLD", STATUS_LOGGEDIN, &WorldSession::HandleSetTradeGoldOpcode }, - /*0x120*/ { "SMSG_TRADE_STATUS", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x121*/ { "SMSG_TRADE_STATUS_EXTENDED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x122*/ { "SMSG_INITIALIZE_FACTIONS", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x123*/ { "SMSG_SET_FACTION_VISIBLE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x124*/ { "SMSG_SET_FACTION_STANDING", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x125*/ { "CMSG_SET_FACTION_ATWAR", STATUS_LOGGEDIN, &WorldSession::HandleSetFactionAtWar }, - /*0x126*/ { "CMSG_SET_FACTION_CHEAT", STATUS_LOGGEDIN, &WorldSession::HandleSetFactionCheat }, - /*0x127*/ { "SMSG_SET_PROFICIENCY", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x128*/ { "CMSG_SET_ACTION_BUTTON", STATUS_LOGGEDIN, &WorldSession::HandleSetActionButtonOpcode }, - /*0x129*/ { "SMSG_ACTION_BUTTONS", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x12A*/ { "SMSG_INITIAL_SPELLS", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x12B*/ { "SMSG_LEARNED_SPELL", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x12C*/ { "SMSG_SUPERCEDED_SPELL", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x12D*/ { "CMSG_NEW_SPELL_SLOT", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x12E*/ { "CMSG_CAST_SPELL", STATUS_LOGGEDIN, &WorldSession::HandleCastSpellOpcode }, - /*0x12F*/ { "CMSG_CANCEL_CAST", STATUS_LOGGEDIN, &WorldSession::HandleCancelCastOpcode }, - /*0x130*/ { "SMSG_CAST_FAILED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x131*/ { "SMSG_SPELL_START", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x132*/ { "SMSG_SPELL_GO", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x133*/ { "SMSG_SPELL_FAILURE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x134*/ { "SMSG_SPELL_COOLDOWN", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x135*/ { "SMSG_COOLDOWN_EVENT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x136*/ { "CMSG_CANCEL_AURA", STATUS_LOGGEDIN, &WorldSession::HandleCancelAuraOpcode }, - /*0x137*/ { "SMSG_UPDATE_AURA_DURATION", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x138*/ { "SMSG_PET_CAST_FAILED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x139*/ { "MSG_CHANNEL_START", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x13A*/ { "MSG_CHANNEL_UPDATE", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x13B*/ { "CMSG_CANCEL_CHANNELLING", STATUS_LOGGEDIN, &WorldSession::HandleCancelChanneling }, - /*0x13C*/ { "SMSG_AI_REACTION", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x13D*/ { "CMSG_SET_SELECTION", STATUS_LOGGEDIN, &WorldSession::HandleSetSelectionOpcode }, - /*0x13E*/ { "CMSG_SET_TARGET_OBSOLETE", STATUS_LOGGEDIN, &WorldSession::HandleSetTargetOpcode }, - /*0x13F*/ { "CMSG_UNUSED", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x140*/ { "CMSG_UNUSED2", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x141*/ { "CMSG_ATTACKSWING", STATUS_LOGGEDIN, &WorldSession::HandleAttackSwingOpcode }, - /*0x142*/ { "CMSG_ATTACKSTOP", STATUS_LOGGEDIN, &WorldSession::HandleAttackStopOpcode }, - /*0x143*/ { "SMSG_ATTACKSTART", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x144*/ { "SMSG_ATTACKSTOP", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x145*/ { "SMSG_ATTACKSWING_NOTINRANGE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x146*/ { "SMSG_ATTACKSWING_BADFACING", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x147*/ { "SMSG_ATTACKSWING_NOTSTANDING", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x148*/ { "SMSG_ATTACKSWING_DEADTARGET", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x149*/ { "SMSG_ATTACKSWING_CANT_ATTACK", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x14A*/ { "SMSG_ATTACKERSTATEUPDATE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x14B*/ { "SMSG_VICTIMSTATEUPDATE_OBSOLETE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x14C*/ { "SMSG_DAMAGE_DONE_OBSOLETE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x14D*/ { "SMSG_DAMAGE_TAKEN_OBSOLETE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x14E*/ { "SMSG_CANCEL_COMBAT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x14F*/ { "SMSG_PLAYER_COMBAT_XP_GAIN_OBSOLETE",STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x150*/ { "SMSG_SPELLHEALLOG", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x151*/ { "SMSG_SPELLENERGIZELOG", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x152*/ { "CMSG_SHEATHE_OBSOLETE", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x153*/ { "CMSG_SAVE_PLAYER", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x154*/ { "CMSG_SETDEATHBINDPOINT", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x155*/ { "SMSG_BINDPOINTUPDATE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x156*/ { "CMSG_GETDEATHBINDZONE", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x157*/ { "SMSG_BINDZONEREPLY", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x158*/ { "SMSG_PLAYERBOUND", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x159*/ { "SMSG_CLIENT_CONTROL_UPDATE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x15A*/ { "CMSG_REPOP_REQUEST", STATUS_LOGGEDIN, &WorldSession::HandleRepopRequestOpcode }, - /*0x15B*/ { "SMSG_RESURRECT_REQUEST", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x15C*/ { "CMSG_RESURRECT_RESPONSE", STATUS_LOGGEDIN, &WorldSession::HandleResurrectResponseOpcode }, - /*0x15D*/ { "CMSG_LOOT", STATUS_LOGGEDIN, &WorldSession::HandleLootOpcode }, - /*0x15E*/ { "CMSG_LOOT_MONEY", STATUS_LOGGEDIN, &WorldSession::HandleLootMoneyOpcode }, - /*0x15F*/ { "CMSG_LOOT_RELEASE", STATUS_LOGGEDIN, &WorldSession::HandleLootReleaseOpcode }, - /*0x160*/ { "SMSG_LOOT_RESPONSE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x161*/ { "SMSG_LOOT_RELEASE_RESPONSE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x162*/ { "SMSG_LOOT_REMOVED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x163*/ { "SMSG_LOOT_MONEY_NOTIFY", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x164*/ { "SMSG_LOOT_ITEM_NOTIFY", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x165*/ { "SMSG_LOOT_CLEAR_MONEY", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x166*/ { "SMSG_ITEM_PUSH_RESULT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x167*/ { "SMSG_DUEL_REQUESTED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x168*/ { "SMSG_DUEL_OUTOFBOUNDS", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x169*/ { "SMSG_DUEL_INBOUNDS", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x16A*/ { "SMSG_DUEL_COMPLETE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x16B*/ { "SMSG_DUEL_WINNER", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x16C*/ { "CMSG_DUEL_ACCEPTED", STATUS_LOGGEDIN, &WorldSession::HandleDuelAcceptedOpcode }, - /*0x16D*/ { "CMSG_DUEL_CANCELLED", STATUS_LOGGEDIN, &WorldSession::HandleDuelCancelledOpcode }, - /*0x16E*/ { "SMSG_MOUNTRESULT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x16F*/ { "SMSG_DISMOUNTRESULT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x170*/ { "SMSG_PUREMOUNT_CANCELLED_OBSOLETE",STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x171*/ { "CMSG_MOUNTSPECIAL_ANIM", STATUS_LOGGEDIN, &WorldSession::HandleMountSpecialAnimOpcode }, - /*0x172*/ { "SMSG_MOUNTSPECIAL_ANIM", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x173*/ { "SMSG_PET_TAME_FAILURE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x174*/ { "CMSG_PET_SET_ACTION", STATUS_LOGGEDIN, &WorldSession::HandlePetSetAction }, - /*0x175*/ { "CMSG_PET_ACTION", STATUS_LOGGEDIN, &WorldSession::HandlePetAction }, - /*0x176*/ { "CMSG_PET_ABANDON", STATUS_LOGGEDIN, &WorldSession::HandlePetAbandon }, - /*0x177*/ { "CMSG_PET_RENAME", STATUS_LOGGEDIN, &WorldSession::HandlePetRename }, - /*0x178*/ { "SMSG_PET_NAME_INVALID", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x179*/ { "SMSG_PET_SPELLS", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x17A*/ { "SMSG_PET_MODE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x17B*/ { "CMSG_GOSSIP_HELLO", STATUS_LOGGEDIN, &WorldSession::HandleGossipHelloOpcode }, - /*0x17C*/ { "CMSG_GOSSIP_SELECT_OPTION", STATUS_LOGGEDIN, &WorldSession::HandleGossipSelectOptionOpcode }, - /*0x17D*/ { "SMSG_GOSSIP_MESSAGE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x17E*/ { "SMSG_GOSSIP_COMPLETE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x17F*/ { "CMSG_NPC_TEXT_QUERY", STATUS_LOGGEDIN, &WorldSession::HandleNpcTextQueryOpcode }, - /*0x180*/ { "SMSG_NPC_TEXT_UPDATE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x181*/ { "SMSG_NPC_WONT_TALK", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x182*/ { "CMSG_QUESTGIVER_STATUS_QUERY", STATUS_LOGGEDIN, &WorldSession::HandleQuestgiverStatusQueryOpcode}, - /*0x183*/ { "SMSG_QUESTGIVER_STATUS", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x184*/ { "CMSG_QUESTGIVER_HELLO", STATUS_LOGGEDIN, &WorldSession::HandleQuestgiverHelloOpcode }, - /*0x185*/ { "SMSG_QUESTGIVER_QUEST_LIST", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x186*/ { "CMSG_QUESTGIVER_QUERY_QUEST", STATUS_LOGGEDIN, &WorldSession::HandleQuestgiverQuestQueryOpcode}, - /*0x187*/ { "CMSG_QUESTGIVER_QUEST_AUTOLAUNCH", STATUS_LOGGEDIN, &WorldSession::HandleQuestAutoLaunch }, - /*0x188*/ { "SMSG_QUESTGIVER_QUEST_DETAILS", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x189*/ { "CMSG_QUESTGIVER_ACCEPT_QUEST", STATUS_LOGGEDIN, &WorldSession::HandleQuestgiverAcceptQuestOpcode}, - /*0x18A*/ { "CMSG_QUESTGIVER_COMPLETE_QUEST", STATUS_LOGGEDIN, &WorldSession::HandleQuestComplete }, - /*0x18B*/ { "SMSG_QUESTGIVER_REQUEST_ITEMS", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x18C*/ { "CMSG_QUESTGIVER_REQUEST_REWARD", STATUS_LOGGEDIN, &WorldSession::HandleQuestgiverRequestRewardOpcode}, - /*0x18D*/ { "SMSG_QUESTGIVER_OFFER_REWARD", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x18E*/ { "CMSG_QUESTGIVER_CHOOSE_REWARD", STATUS_LOGGEDIN, &WorldSession::HandleQuestgiverChooseRewardOpcode}, - /*0x18F*/ { "SMSG_QUESTGIVER_QUEST_INVALID", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x190*/ { "CMSG_QUESTGIVER_CANCEL", STATUS_LOGGEDIN, &WorldSession::HandleQuestgiverCancel }, - /*0x191*/ { "SMSG_QUESTGIVER_QUEST_COMPLETE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x192*/ { "SMSG_QUESTGIVER_QUEST_FAILED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x193*/ { "CMSG_QUESTLOG_SWAP_QUEST", STATUS_LOGGEDIN, &WorldSession::HandleQuestLogSwapQuest }, - /*0x194*/ { "CMSG_QUESTLOG_REMOVE_QUEST", STATUS_LOGGEDIN, &WorldSession::HandleQuestLogRemoveQuest }, - /*0x195*/ { "SMSG_QUESTLOG_FULL", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x196*/ { "SMSG_QUESTUPDATE_FAILED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x197*/ { "SMSG_QUESTUPDATE_FAILEDTIMER", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x198*/ { "SMSG_QUESTUPDATE_COMPLETE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x199*/ { "SMSG_QUESTUPDATE_ADD_KILL", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x19A*/ { "SMSG_QUESTUPDATE_ADD_ITEM", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x19B*/ { "CMSG_QUEST_CONFIRM_ACCEPT", STATUS_LOGGEDIN, &WorldSession::HandleQuestConfirmAccept }, - /*0x19C*/ { "SMSG_QUEST_CONFIRM_ACCEPT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x19D*/ { "CMSG_PUSHQUESTTOPARTY", STATUS_LOGGEDIN, &WorldSession::HandleQuestPushToParty }, - /*0x19E*/ { "CMSG_LIST_INVENTORY", STATUS_LOGGEDIN, &WorldSession::HandleListInventoryOpcode }, - /*0x19F*/ { "SMSG_LIST_INVENTORY", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x1A0*/ { "CMSG_SELL_ITEM", STATUS_LOGGEDIN, &WorldSession::HandleSellItemOpcode }, - /*0x1A1*/ { "SMSG_SELL_ITEM", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x1A2*/ { "CMSG_BUY_ITEM", STATUS_LOGGEDIN, &WorldSession::HandleBuyItemOpcode }, - /*0x1A3*/ { "CMSG_BUY_ITEM_IN_SLOT", STATUS_LOGGEDIN, &WorldSession::HandleBuyItemInSlotOpcode }, - /*0x1A4*/ { "SMSG_BUY_ITEM", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x1A5*/ { "SMSG_BUY_FAILED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x1A6*/ { "CMSG_TAXICLEARALLNODES", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x1A7*/ { "CMSG_TAXIENABLEALLNODES", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x1A8*/ { "CMSG_TAXISHOWNODES", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x1A9*/ { "SMSG_SHOWTAXINODES", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x1AA*/ { "CMSG_TAXINODE_STATUS_QUERY", STATUS_LOGGEDIN, &WorldSession::HandleTaxiNodeStatusQueryOpcode }, - /*0x1AB*/ { "SMSG_TAXINODE_STATUS", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x1AC*/ { "CMSG_TAXIQUERYAVAILABLENODES", STATUS_LOGGEDIN, &WorldSession::HandleTaxiQueryAvailableNodesOpcode}, - /*0x1AD*/ { "CMSG_ACTIVATETAXI", STATUS_LOGGEDIN, &WorldSession::HandleActivateTaxiOpcode }, - /*0x1AE*/ { "SMSG_ACTIVATETAXIREPLY", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x1AF*/ { "SMSG_NEW_TAXI_PATH", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x1B0*/ { "CMSG_TRAINER_LIST", STATUS_LOGGEDIN, &WorldSession::HandleTrainerListOpcode }, - /*0x1B1*/ { "SMSG_TRAINER_LIST", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x1B2*/ { "CMSG_TRAINER_BUY_SPELL", STATUS_LOGGEDIN, &WorldSession::HandleTrainerBuySpellOpcode }, - /*0x1B3*/ { "SMSG_TRAINER_BUY_SUCCEEDED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x1B4*/ { "SMSG_TRAINER_BUY_FAILED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x1B5*/ { "CMSG_BINDER_ACTIVATE", STATUS_LOGGEDIN, &WorldSession::HandleBinderActivateOpcode }, - /*0x1B6*/ { "SMSG_PLAYERBINDERROR", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x1B7*/ { "CMSG_BANKER_ACTIVATE", STATUS_LOGGEDIN, &WorldSession::HandleBankerActivateOpcode }, - /*0x1B8*/ { "SMSG_SHOW_BANK", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x1B9*/ { "CMSG_BUY_BANK_SLOT", STATUS_LOGGEDIN, &WorldSession::HandleBuyBankSlotOpcode }, - /*0x1BA*/ { "SMSG_BUY_BANK_SLOT_RESULT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x1BB*/ { "CMSG_PETITION_SHOWLIST", STATUS_LOGGEDIN, &WorldSession::HandlePetitionShowListOpcode }, - /*0x1BC*/ { "SMSG_PETITION_SHOWLIST", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x1BD*/ { "CMSG_PETITION_BUY", STATUS_LOGGEDIN, &WorldSession::HandlePetitionBuyOpcode }, - /*0x1BE*/ { "CMSG_PETITION_SHOW_SIGNATURES", STATUS_LOGGEDIN, &WorldSession::HandlePetitionShowSignOpcode }, - /*0x1BF*/ { "SMSG_PETITION_SHOW_SIGNATURES", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x1C0*/ { "CMSG_PETITION_SIGN", STATUS_LOGGEDIN, &WorldSession::HandlePetitionSignOpcode }, - /*0x1C1*/ { "SMSG_PETITION_SIGN_RESULTS", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x1C2*/ { "MSG_PETITION_DECLINE", STATUS_LOGGEDIN, &WorldSession::HandlePetitionDeclineOpcode }, - /*0x1C3*/ { "CMSG_OFFER_PETITION", STATUS_LOGGEDIN, &WorldSession::HandleOfferPetitionOpcode }, - /*0x1C4*/ { "CMSG_TURN_IN_PETITION", STATUS_LOGGEDIN, &WorldSession::HandleTurnInPetitionOpcode }, - /*0x1C5*/ { "SMSG_TURN_IN_PETITION_RESULTS", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x1C6*/ { "CMSG_PETITION_QUERY", STATUS_LOGGEDIN, &WorldSession::HandlePetitionQueryOpcode }, - /*0x1C7*/ { "SMSG_PETITION_QUERY_RESPONSE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x1C8*/ { "SMSG_FISH_NOT_HOOKED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x1C9*/ { "SMSG_FISH_ESCAPED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x1CA*/ { "CMSG_BUG", STATUS_LOGGEDIN, &WorldSession::HandleBugOpcode }, - /*0x1CB*/ { "SMSG_NOTIFICATION", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x1CC*/ { "CMSG_PLAYED_TIME", STATUS_LOGGEDIN, &WorldSession::HandlePlayedTime }, - /*0x1CD*/ { "SMSG_PLAYED_TIME", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x1CE*/ { "CMSG_QUERY_TIME", STATUS_LOGGEDIN, &WorldSession::HandleQueryTimeOpcode }, - /*0x1CF*/ { "SMSG_QUERY_TIME_RESPONSE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x1D0*/ { "SMSG_LOG_XPGAIN", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x1D1*/ { "SMSG_AURACASTLOG", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x1D2*/ { "CMSG_RECLAIM_CORPSE", STATUS_LOGGEDIN, &WorldSession::HandleCorpseReclaimOpcode }, - /*0x1D3*/ { "CMSG_WRAP_ITEM", STATUS_LOGGEDIN, &WorldSession::HandleWrapItemOpcode }, - /*0x1D4*/ { "SMSG_LEVELUP_INFO", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x1D5*/ { "MSG_MINIMAP_PING", STATUS_LOGGEDIN, &WorldSession::HandleMinimapPingOpcode }, - /*0x1D6*/ { "SMSG_RESISTLOG", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x1D7*/ { "SMSG_ENCHANTMENTLOG", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x1D8*/ { "CMSG_SET_SKILL_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x1D9*/ { "SMSG_START_MIRROR_TIMER", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x1DA*/ { "SMSG_PAUSE_MIRROR_TIMER", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x1DB*/ { "SMSG_STOP_MIRROR_TIMER", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x1DC*/ { "CMSG_PING", STATUS_NEVER, &WorldSession::Handle_EarlyProccess }, - /*0x1DD*/ { "SMSG_PONG", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x1DE*/ { "SMSG_CLEAR_COOLDOWN", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x1DF*/ { "SMSG_GAMEOBJECT_PAGETEXT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x1E0*/ { "CMSG_SETSHEATHED", STATUS_LOGGEDIN, &WorldSession::HandleSetSheathedOpcode }, - /*0x1E1*/ { "SMSG_COOLDOWN_CHEAT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x1E2*/ { "SMSG_SPELL_DELAYED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x1E3*/ { "CMSG_PLAYER_MACRO_OBSOLETE", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x1E4*/ { "SMSG_PLAYER_MACRO_OBSOLETE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x1E5*/ { "CMSG_GHOST", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x1E6*/ { "CMSG_GM_INVIS", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x1E7*/ { "SMSG_INVALID_PROMOTION_CODE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x1E8*/ { "MSG_GM_BIND_OTHER", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x1E9*/ { "MSG_GM_SUMMON", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x1EA*/ { "SMSG_ITEM_TIME_UPDATE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x1EB*/ { "SMSG_ITEM_ENCHANT_TIME_UPDATE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x1EC*/ { "SMSG_AUTH_CHALLENGE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x1ED*/ { "CMSG_AUTH_SESSION", STATUS_NEVER, &WorldSession::Handle_EarlyProccess }, - /*0x1EE*/ { "SMSG_AUTH_RESPONSE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x1EF*/ { "MSG_GM_SHOWLABEL", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x1F0*/ { "CMSG_PET_CAST_SPELL", STATUS_LOGGEDIN, &WorldSession::HandlePetCastSpellOpcode }, - /*0x1F1*/ { "MSG_SAVE_GUILD_EMBLEM", STATUS_LOGGEDIN, &WorldSession::HandleGuildSaveEmblemOpcode }, - /*0x1F2*/ { "MSG_TABARDVENDOR_ACTIVATE", STATUS_LOGGEDIN, &WorldSession::HandleTabardVendorActivateOpcode}, - /*0x1F3*/ { "SMSG_PLAY_SPELL_VISUAL", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x1F4*/ { "CMSG_ZONEUPDATE", STATUS_LOGGEDIN, &WorldSession::HandleZoneUpdateOpcode }, - /*0x1F5*/ { "SMSG_PARTYKILLLOG", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x1F6*/ { "SMSG_COMPRESSED_UPDATE_OBJECT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x1F7*/ { "SMSG_PLAY_SPELL_IMPACT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x1F8*/ { "SMSG_EXPLORATION_EXPERIENCE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x1F9*/ { "CMSG_GM_SET_SECURITY_GROUP", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x1FA*/ { "CMSG_GM_NUKE", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x1FB*/ { "MSG_RANDOM_ROLL", STATUS_LOGGEDIN, &WorldSession::HandleRandomRollOpcode }, - /*0x1FC*/ { "SMSG_ENVIRONMENTALDAMAGELOG", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x1FD*/ { "CMSG_RWHOIS_OBSOLETE", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x1FE*/ { "SMSG_RWHOIS", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x1FF*/ { "MSG_LOOKING_FOR_GROUP", STATUS_LOGGEDIN, &WorldSession::HandleLookingForGroup }, - /*0x200*/ { "CMSG_SET_LOOKING_FOR_GROUP", STATUS_LOGGEDIN, &WorldSession::HandleSetLfgOpcode }, - /*0x201*/ { "CMSG_UNLEARN_SPELL", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x202*/ { "CMSG_UNLEARN_SKILL", STATUS_LOGGEDIN, &WorldSession::HandleUnlearnSkillOpcode }, - /*0x203*/ { "SMSG_REMOVED_SPELL", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x204*/ { "CMSG_DECHARGE", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x205*/ { "CMSG_GMTICKET_CREATE", STATUS_LOGGEDIN, &WorldSession::HandleGMTicketCreateOpcode }, - /*0x206*/ { "SMSG_GMTICKET_CREATE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x207*/ { "CMSG_GMTICKET_UPDATETEXT", STATUS_LOGGEDIN, &WorldSession::HandleGMTicketUpdateTextOpcode }, - /*0x208*/ { "SMSG_GMTICKET_UPDATETEXT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x209*/ { "SMSG_ACCOUNT_DATA_TIMES", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x20A*/ { "CMSG_REQUEST_ACCOUNT_DATA", STATUS_LOGGEDIN, &WorldSession::HandleRequestAccountData }, - /*0x20B*/ { "CMSG_UPDATE_ACCOUNT_DATA", STATUS_LOGGEDIN, &WorldSession::HandleUpdateAccountData }, - /*0x20C*/ { "SMSG_UPDATE_ACCOUNT_DATA", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x20D*/ { "SMSG_CLEAR_FAR_SIGHT_IMMEDIATE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x20E*/ { "SMSG_POWERGAINLOG_OBSOLETE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x20F*/ { "CMSG_GM_TEACH", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x210*/ { "CMSG_GM_CREATE_ITEM_TARGET", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x211*/ { "CMSG_GMTICKET_GETTICKET", STATUS_LOGGEDIN, &WorldSession::HandleGMTicketGetTicketOpcode }, - /*0x212*/ { "SMSG_GMTICKET_GETTICKET", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x213*/ { "CMSG_UNLEARN_TALENTS", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x214*/ { "SMSG_GAMEOBJECT_SPAWN_ANIM_OBSOLETE",STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x215*/ { "SMSG_GAMEOBJECT_DESPAWN_ANIM", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x216*/ { "MSG_CORPSE_QUERY", STATUS_LOGGEDIN, &WorldSession::HandleCorpseQueryOpcode }, - /*0x217*/ { "CMSG_GMTICKET_DELETETICKET", STATUS_LOGGEDIN, &WorldSession::HandleGMTicketDeleteOpcode }, - /*0x218*/ { "SMSG_GMTICKET_DELETETICKET", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x219*/ { "SMSG_CHAT_WRONG_FACTION", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x21A*/ { "CMSG_GMTICKET_SYSTEMSTATUS", STATUS_LOGGEDIN, &WorldSession::HandleGMTicketSystemStatusOpcode}, - /*0x21B*/ { "SMSG_GMTICKET_SYSTEMSTATUS", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x21C*/ { "CMSG_SPIRIT_HEALER_ACTIVATE", STATUS_LOGGEDIN, &WorldSession::HandleSpiritHealerActivateOpcode}, - /*0x21D*/ { "CMSG_SET_STAT_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x21E*/ { "SMSG_SET_REST_START", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x21F*/ { "CMSG_SKILL_BUY_STEP", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x220*/ { "CMSG_SKILL_BUY_RANK", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x221*/ { "CMSG_XP_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x222*/ { "SMSG_SPIRIT_HEALER_CONFIRM", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x223*/ { "CMSG_CHARACTER_POINT_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x224*/ { "SMSG_GOSSIP_POI", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x225*/ { "CMSG_CHAT_IGNORED", STATUS_LOGGEDIN, &WorldSession::HandleChatIgnoredOpcode }, - /*0x226*/ { "CMSG_GM_VISION", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x227*/ { "CMSG_SERVER_COMMAND", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x228*/ { "CMSG_GM_SILENCE", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x229*/ { "CMSG_GM_REVEALTO", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x22A*/ { "CMSG_GM_RESURRECT", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x22B*/ { "CMSG_GM_SUMMONMOB", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x22C*/ { "CMSG_GM_MOVECORPSE", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x22D*/ { "CMSG_GM_FREEZE", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x22E*/ { "CMSG_GM_UBERINVIS", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x22F*/ { "CMSG_GM_REQUEST_PLAYER_INFO", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x230*/ { "SMSG_GM_PLAYER_INFO", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x231*/ { "CMSG_GUILD_RANK", STATUS_LOGGEDIN, &WorldSession::HandleGuildRankOpcode }, - /*0x232*/ { "CMSG_GUILD_ADD_RANK", STATUS_LOGGEDIN, &WorldSession::HandleGuildAddRankOpcode }, - /*0x233*/ { "CMSG_GUILD_DEL_RANK", STATUS_LOGGEDIN, &WorldSession::HandleGuildDelRankOpcode }, - /*0x234*/ { "CMSG_GUILD_SET_PUBLIC_NOTE", STATUS_LOGGEDIN, &WorldSession::HandleGuildSetPublicNoteOpcode }, - /*0x235*/ { "CMSG_GUILD_SET_OFFICER_NOTE", STATUS_LOGGEDIN, &WorldSession::HandleGuildSetOfficerNoteOpcode }, - /*0x236*/ { "SMSG_LOGIN_VERIFY_WORLD", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x237*/ { "CMSG_CLEAR_EXPLORATION", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x238*/ { "CMSG_SEND_MAIL", STATUS_LOGGEDIN, &WorldSession::HandleSendMail }, - /*0x239*/ { "SMSG_SEND_MAIL_RESULT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x23A*/ { "CMSG_GET_MAIL_LIST", STATUS_LOGGEDIN, &WorldSession::HandleGetMail }, - /*0x23B*/ { "SMSG_MAIL_LIST_RESULT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x23C*/ { "CMSG_BATTLEFIELD_LIST", STATUS_LOGGEDIN, &WorldSession::HandleBattleGroundListOpcode }, - /*0x23D*/ { "SMSG_BATTLEFIELD_LIST", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x23E*/ { "CMSG_BATTLEFIELD_JOIN", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x23F*/ { "SMSG_BATTLEFIELD_WIN_OBSOLETE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x240*/ { "SMSG_BATTLEFIELD_LOSE_OBSOLETE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x241*/ { "CMSG_TAXICLEARNODE", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x242*/ { "CMSG_TAXIENABLENODE", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x243*/ { "CMSG_ITEM_TEXT_QUERY", STATUS_LOGGEDIN, &WorldSession::HandleItemTextQuery }, - /*0x244*/ { "SMSG_ITEM_TEXT_QUERY_RESPONSE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x245*/ { "CMSG_MAIL_TAKE_MONEY", STATUS_LOGGEDIN, &WorldSession::HandleTakeMoney }, - /*0x246*/ { "CMSG_MAIL_TAKE_ITEM", STATUS_LOGGEDIN, &WorldSession::HandleTakeItem }, - /*0x247*/ { "CMSG_MAIL_MARK_AS_READ", STATUS_LOGGEDIN, &WorldSession::HandleMarkAsRead }, - /*0x248*/ { "CMSG_MAIL_RETURN_TO_SENDER", STATUS_LOGGEDIN, &WorldSession::HandleReturnToSender }, - /*0x249*/ { "CMSG_MAIL_DELETE", STATUS_LOGGEDIN, &WorldSession::HandleMailDelete }, - /*0x24A*/ { "CMSG_MAIL_CREATE_TEXT_ITEM", STATUS_LOGGEDIN, &WorldSession::HandleMailCreateTextItem }, - /*0x24B*/ { "SMSG_SPELLLOGMISS", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x24C*/ { "SMSG_SPELLLOGEXECUTE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x24D*/ { "SMSG_DEBUGAURAPROC", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x24E*/ { "SMSG_PERIODICAURALOG", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x24F*/ { "SMSG_SPELLDAMAGESHIELD", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x250*/ { "SMSG_SPELLNONMELEEDAMAGELOG", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x251*/ { "CMSG_LEARN_TALENT", STATUS_LOGGEDIN, &WorldSession::HandleLearnTalentOpcode }, - /*0x252*/ { "SMSG_RESURRECT_FAILED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x253*/ { "CMSG_TOGGLE_PVP", STATUS_LOGGEDIN, &WorldSession::HandleTogglePvP }, - /*0x254*/ { "SMSG_ZONE_UNDER_ATTACK", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x255*/ { "MSG_AUCTION_HELLO", STATUS_LOGGEDIN, &WorldSession::HandleAuctionHelloOpcode }, - /*0x256*/ { "CMSG_AUCTION_SELL_ITEM", STATUS_LOGGEDIN, &WorldSession::HandleAuctionSellItem }, - /*0x257*/ { "CMSG_AUCTION_REMOVE_ITEM", STATUS_LOGGEDIN, &WorldSession::HandleAuctionRemoveItem }, - /*0x258*/ { "CMSG_AUCTION_LIST_ITEMS", STATUS_LOGGEDIN, &WorldSession::HandleAuctionListItems }, - /*0x259*/ { "CMSG_AUCTION_LIST_OWNER_ITEMS", STATUS_LOGGEDIN, &WorldSession::HandleAuctionListOwnerItems }, - /*0x25A*/ { "CMSG_AUCTION_PLACE_BID", STATUS_LOGGEDIN, &WorldSession::HandleAuctionPlaceBid }, - /*0x25B*/ { "SMSG_AUCTION_COMMAND_RESULT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x25C*/ { "SMSG_AUCTION_LIST_RESULT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x25D*/ { "SMSG_AUCTION_OWNER_LIST_RESULT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x25E*/ { "SMSG_AUCTION_BIDDER_NOTIFICATION", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x25F*/ { "SMSG_AUCTION_OWNER_NOTIFICATION", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x260*/ { "SMSG_PROCRESIST", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x261*/ { "SMSG_STANDSTATE_CHANGE_FAILURE_OBSOLETE",STATUS_NEVER,&WorldSession::Handle_ServerSide }, - /*0x262*/ { "SMSG_DISPEL_FAILED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x263*/ { "SMSG_SPELLORDAMAGE_IMMUNE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x264*/ { "CMSG_AUCTION_LIST_BIDDER_ITEMS", STATUS_LOGGEDIN, &WorldSession::HandleAuctionListBidderItems }, - /*0x265*/ { "SMSG_AUCTION_BIDDER_LIST_RESULT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x266*/ { "SMSG_SET_FLAT_SPELL_MODIFIER", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x267*/ { "SMSG_SET_PCT_SPELL_MODIFIER", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x268*/ { "CMSG_SET_AMMO", STATUS_LOGGEDIN, &WorldSession::HandleSetAmmoOpcode }, - /*0x269*/ { "SMSG_CORPSE_RECLAIM_DELAY", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x26A*/ { "CMSG_SET_ACTIVE_MOVER", STATUS_LOGGEDIN, &WorldSession::HandleSetActiveMoverOpcode }, - /*0x26B*/ { "CMSG_PET_CANCEL_AURA", STATUS_LOGGEDIN, &WorldSession::HandlePetCancelAuraOpcode }, - /*0x26C*/ { "CMSG_PLAYER_AI_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x26D*/ { "CMSG_CANCEL_AUTO_REPEAT_SPELL", STATUS_LOGGEDIN, &WorldSession::HandleCancelAutoRepeatSpellOpcode}, - /*0x26E*/ { "MSG_GM_ACCOUNT_ONLINE", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x26F*/ { "MSG_LIST_STABLED_PETS", STATUS_LOGGEDIN, &WorldSession::HandleListStabledPetsOpcode }, - /*0x270*/ { "CMSG_STABLE_PET", STATUS_LOGGEDIN, &WorldSession::HandleStablePet }, - /*0x271*/ { "CMSG_UNSTABLE_PET", STATUS_LOGGEDIN, &WorldSession::HandleUnstablePet }, - /*0x272*/ { "CMSG_BUY_STABLE_SLOT", STATUS_LOGGEDIN, &WorldSession::HandleBuyStableSlot }, - /*0x273*/ { "SMSG_STABLE_RESULT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x274*/ { "CMSG_STABLE_REVIVE_PET", STATUS_LOGGEDIN, &WorldSession::HandleStableRevivePet }, - /*0x275*/ { "CMSG_STABLE_SWAP_PET", STATUS_LOGGEDIN, &WorldSession::HandleStableSwapPet }, - /*0x276*/ { "MSG_QUEST_PUSH_RESULT", STATUS_LOGGEDIN, &WorldSession::HandleQuestPushResult }, - /*0x277*/ { "SMSG_PLAY_MUSIC", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x278*/ { "SMSG_PLAY_OBJECT_SOUND", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x279*/ { "CMSG_REQUEST_PET_INFO", STATUS_LOGGEDIN, &WorldSession::HandleRequestPetInfoOpcode }, - /*0x27A*/ { "CMSG_FAR_SIGHT", STATUS_LOGGEDIN, &WorldSession::HandleFarSightOpcode }, - /*0x27B*/ { "SMSG_SPELLDISPELLOG", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x27C*/ { "SMSG_DAMAGE_CALC_LOG", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x27D*/ { "CMSG_ENABLE_DAMAGE_LOG", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x27E*/ { "CMSG_GROUP_CHANGE_SUB_GROUP", STATUS_LOGGEDIN, &WorldSession::HandleGroupChangeSubGroupOpcode }, - /*0x27F*/ { "CMSG_REQUEST_PARTY_MEMBER_STATS", STATUS_LOGGEDIN, &WorldSession::HandleRequestPartyMemberStatsOpcode}, - /*0x280*/ { "CMSG_GROUP_SWAP_SUB_GROUP", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x281*/ { "CMSG_RESET_FACTION_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x282*/ { "CMSG_AUTOSTORE_BANK_ITEM", STATUS_LOGGEDIN, &WorldSession::HandleAutoStoreBankItemOpcode }, - /*0x283*/ { "CMSG_AUTOBANK_ITEM", STATUS_LOGGEDIN, &WorldSession::HandleAutoBankItemOpcode }, - /*0x284*/ { "MSG_QUERY_NEXT_MAIL_TIME", STATUS_LOGGEDIN, &WorldSession::HandleMsgQueryNextMailtime }, - /*0x285*/ { "SMSG_RECEIVED_MAIL", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x286*/ { "SMSG_RAID_GROUP_ONLY", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x287*/ { "CMSG_SET_DURABILITY_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x288*/ { "CMSG_SET_PVP_RANK_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x289*/ { "CMSG_ADD_PVP_MEDAL_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x28A*/ { "CMSG_DEL_PVP_MEDAL_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x28B*/ { "CMSG_SET_PVP_TITLE", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x28C*/ { "SMSG_PVP_CREDIT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x28D*/ { "SMSG_AUCTION_REMOVED_NOTIFICATION",STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x28E*/ { "CMSG_GROUP_RAID_CONVERT", STATUS_LOGGEDIN, &WorldSession::HandleRaidConvertOpcode }, - /*0x28F*/ { "CMSG_GROUP_ASSISTANT_LEADER", STATUS_LOGGEDIN, &WorldSession::HandleGroupAssistantOpcode }, - /*0x290*/ { "CMSG_BUYBACK_ITEM", STATUS_LOGGEDIN, &WorldSession::HandleBuybackItem }, - /*0x291*/ { "SMSG_SERVER_MESSAGE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x292*/ { "CMSG_MEETINGSTONE_JOIN", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x293*/ { "CMSG_MEETINGSTONE_LEAVE", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x294*/ { "CMSG_MEETINGSTONE_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x295*/ { "SMSG_MEETINGSTONE_SETQUEUE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x296*/ { "CMSG_MEETINGSTONE_INFO", STATUS_LOGGEDIN, &WorldSession::HandleMeetingStoneInfo }, - /*0x297*/ { "SMSG_MEETINGSTONE_COMPLETE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x298*/ { "SMSG_MEETINGSTONE_IN_PROGRESS", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x299*/ { "SMSG_MEETINGSTONE_MEMBER_ADDED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x29A*/ { "CMSG_GMTICKETSYSTEM_TOGGLE", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x29B*/ { "CMSG_CANCEL_GROWTH_AURA", STATUS_LOGGEDIN, &WorldSession::HandleCancelGrowthAuraOpcode }, - /*0x29C*/ { "SMSG_CANCEL_AUTO_REPEAT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x29D*/ { "SMSG_STANDSTATE_UPDATE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x29E*/ { "SMSG_LOOT_ALL_PASSED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x29F*/ { "SMSG_LOOT_ROLL_WON", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x2A0*/ { "CMSG_LOOT_ROLL", STATUS_LOGGEDIN, &WorldSession::HandleLootRoll }, - /*0x2A1*/ { "SMSG_LOOT_START_ROLL", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x2A2*/ { "SMSG_LOOT_ROLL", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x2A3*/ { "CMSG_LOOT_MASTER_GIVE", STATUS_LOGGEDIN, &WorldSession::HandleLootMasterGiveOpcode }, - /*0x2A4*/ { "SMSG_LOOT_MASTER_LIST", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x2A5*/ { "SMSG_SET_FORCED_REACTIONS", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x2A6*/ { "SMSG_SPELL_FAILED_OTHER", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x2A7*/ { "SMSG_GAMEOBJECT_RESET_STATE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x2A8*/ { "CMSG_REPAIR_ITEM", STATUS_LOGGEDIN, &WorldSession::HandleRepairItemOpcode }, - /*0x2A9*/ { "SMSG_CHAT_PLAYER_NOT_FOUND", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x2AA*/ { "MSG_TALENT_WIPE_CONFIRM", STATUS_LOGGEDIN, &WorldSession::HandleTalentWipeOpcode }, - /*0x2AB*/ { "SMSG_SUMMON_REQUEST", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x2AC*/ { "CMSG_SUMMON_RESPONSE", STATUS_LOGGEDIN, &WorldSession::HandleSummonResponseOpcode }, - /*0x2AD*/ { "MSG_MOVE_TOGGLE_GRAVITY_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x2AE*/ { "SMSG_MONSTER_MOVE_TRANSPORT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x2AF*/ { "SMSG_PET_BROKEN", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x2B0*/ { "MSG_MOVE_FEATHER_FALL", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x2B1*/ { "MSG_MOVE_WATER_WALK", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x2B2*/ { "CMSG_SERVER_BROADCAST", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x2B3*/ { "CMSG_SELF_RES", STATUS_LOGGEDIN, &WorldSession::HandleSelfResOpcode }, - /*0x2B4*/ { "SMSG_FEIGN_DEATH_RESISTED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x2B5*/ { "CMSG_RUN_SCRIPT", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x2B6*/ { "SMSG_SCRIPT_MESSAGE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x2B7*/ { "SMSG_DUEL_COUNTDOWN", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x2B8*/ { "SMSG_AREA_TRIGGER_MESSAGE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x2B9*/ { "CMSG_TOGGLE_HELM", STATUS_LOGGEDIN, &WorldSession::HandleToggleHelmOpcode }, - /*0x2BA*/ { "CMSG_TOGGLE_CLOAK", STATUS_LOGGEDIN, &WorldSession::HandleToggleCloakOpcode }, - /*0x2BB*/ { "SMSG_MEETINGSTONE_JOINFAILED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x2BC*/ { "SMSG_PLAYER_SKINNED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x2BD*/ { "SMSG_DURABILITY_DAMAGE_DEATH", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x2BE*/ { "CMSG_SET_EXPLORATION", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x2BF*/ { "CMSG_SET_ACTIONBAR_TOGGLES", STATUS_AUTHED, &WorldSession::HandleSetActionBar }, - /*0x2C0*/ { "UMSG_DELETE_GUILD_CHARTER", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x2C1*/ { "MSG_PETITION_RENAME", STATUS_LOGGEDIN, &WorldSession::HandlePetitionRenameOpcode }, - /*0x2C2*/ { "SMSG_INIT_WORLD_STATES", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x2C3*/ { "SMSG_UPDATE_WORLD_STATE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x2C4*/ { "CMSG_ITEM_NAME_QUERY", STATUS_LOGGEDIN, &WorldSession::HandleItemNameQueryOpcode }, - /*0x2C5*/ { "SMSG_ITEM_NAME_QUERY_RESPONSE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x2C6*/ { "SMSG_PET_ACTION_FEEDBACK", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x2C7*/ { "CMSG_CHAR_RENAME", STATUS_AUTHED, &WorldSession::HandleChangePlayerNameOpcode }, - /*0x2C8*/ { "SMSG_CHAR_RENAME", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x2C9*/ { "CMSG_MOVE_SPLINE_DONE", STATUS_LOGGEDIN, &WorldSession::HandleTaxiNextDestinationOpcode }, - /*0x2CA*/ { "CMSG_MOVE_FALL_RESET", STATUS_LOGGEDIN, &WorldSession::HandleMovementOpcodes }, - /*0x2CB*/ { "SMSG_INSTANCE_SAVE_CREATED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x2CC*/ { "SMSG_RAID_INSTANCE_INFO", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x2CD*/ { "CMSG_REQUEST_RAID_INFO", STATUS_LOGGEDIN, &WorldSession::HandleRequestRaidInfoOpcode }, - /*0x2CE*/ { "CMSG_MOVE_TIME_SKIPPED", STATUS_LOGGEDIN, &WorldSession::HandleMoveTimeSkippedOpcode }, - /*0x2CF*/ { "CMSG_MOVE_FEATHER_FALL_ACK", STATUS_LOGGEDIN, &WorldSession::HandleFeatherFallAck }, - /*0x2D0*/ { "CMSG_MOVE_WATER_WALK_ACK", STATUS_LOGGEDIN, &WorldSession::HandleMoveWaterWalkAck }, - /*0x2D1*/ { "CMSG_MOVE_NOT_ACTIVE_MOVER", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x2D2*/ { "SMSG_PLAY_SOUND", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x2D3*/ { "CMSG_BATTLEFIELD_STATUS", STATUS_LOGGEDIN, &WorldSession::HandleBattlefieldStatusOpcode }, - /*0x2D4*/ { "SMSG_BATTLEFIELD_STATUS", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x2D5*/ { "CMSG_BATTLEFIELD_PORT", STATUS_LOGGEDIN, &WorldSession::HandleBattleGroundPlayerPortOpcode}, - /*0x2D6*/ { "MSG_INSPECT_HONOR_STATS", STATUS_LOGGEDIN, &WorldSession::HandleInspectHonorStatsOpcode }, - /*0x2D7*/ { "CMSG_BATTLEMASTER_HELLO", STATUS_LOGGEDIN, &WorldSession::HandleBattleGroundHelloOpcode }, - /*0x2D8*/ { "CMSG_MOVE_START_SWIM_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x2D9*/ { "CMSG_MOVE_STOP_SWIM_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x2DA*/ { "SMSG_FORCE_WALK_SPEED_CHANGE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x2DB*/ { "CMSG_FORCE_WALK_SPEED_CHANGE_ACK", STATUS_LOGGEDIN, &WorldSession::HandleForceSpeedChangeAck }, - /*0x2DC*/ { "SMSG_FORCE_SWIM_BACK_SPEED_CHANGE",STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x2DD*/ { "CMSG_FORCE_SWIM_BACK_SPEED_CHANGE_ACK",STATUS_LOGGEDIN,&WorldSession::HandleForceSpeedChangeAck }, - /*0x2DE*/ { "SMSG_FORCE_TURN_RATE_CHANGE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x2DF*/ { "CMSG_FORCE_TURN_RATE_CHANGE_ACK", STATUS_LOGGEDIN, &WorldSession::HandleForceSpeedChangeAck }, - /*0x2E0*/ { "MSG_PVP_LOG_DATA", STATUS_LOGGEDIN, &WorldSession::HandleBattleGroundPVPlogdataOpcode}, - /*0x2E1*/ { "CMSG_LEAVE_BATTLEFIELD", STATUS_LOGGEDIN, &WorldSession::HandleBattleGroundLeaveOpcode }, - /*0x2E2*/ { "CMSG_AREA_SPIRIT_HEALER_QUERY", STATUS_LOGGEDIN, &WorldSession::HandleAreaSpiritHealerQueryOpcode}, - /*0x2E3*/ { "CMSG_AREA_SPIRIT_HEALER_QUEUE", STATUS_LOGGEDIN, &WorldSession::HandleAreaSpiritHealerQueueOpcode}, - /*0x2E4*/ { "SMSG_AREA_SPIRIT_HEALER_TIME", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x2E5*/ { "CMSG_GM_UNTEACH", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x2E6*/ { "SMSG_WARDEN_DATA", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x2E7*/ { "CMSG_WARDEN_DATA", STATUS_LOGGEDIN, &WorldSession::HandleWardenDataOpcode }, - /*0x2E8*/ { "SMSG_GROUP_JOINED_BATTLEGROUND", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x2E9*/ { "MSG_BATTLEGROUND_PLAYER_POSITIONS",STATUS_LOGGEDIN, &WorldSession::HandleBattleGroundPlayerPositionsOpcode}, - /*0x2EA*/ { "CMSG_PET_STOP_ATTACK", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x2EB*/ { "SMSG_BINDER_CONFIRM", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x2EC*/ { "SMSG_BATTLEGROUND_PLAYER_JOINED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x2ED*/ { "SMSG_BATTLEGROUND_PLAYER_LEFT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x2EE*/ { "CMSG_BATTLEMASTER_JOIN", STATUS_LOGGEDIN, &WorldSession::HandleBattleGroundJoinOpcode }, - /*0x2EF*/ { "SMSG_ADDON_INFO", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x2F0*/ { "CMSG_PET_UNLEARN", STATUS_LOGGEDIN, &WorldSession::HandlePetUnlearnOpcode }, - /*0x2F1*/ { "SMSG_PET_UNLEARN_CONFIRM", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x2F2*/ { "SMSG_PARTY_MEMBER_STATS_FULL", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x2F3*/ { "CMSG_PET_SPELL_AUTOCAST", STATUS_LOGGEDIN, &WorldSession::HandlePetSpellAutocastOpcode }, - /*0x2F4*/ { "SMSG_WEATHER", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x2F5*/ { "SMSG_PLAY_TIME_WARNING", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x2F6*/ { "SMSG_MINIGAME_SETUP", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x2F7*/ { "SMSG_MINIGAME_STATE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x2F8*/ { "CMSG_MINIGAME_MOVE", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x2F9*/ { "SMSG_MINIGAME_MOVE_FAILED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x2FA*/ { "SMSG_RAID_INSTANCE_MESSAGE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x2FB*/ { "SMSG_COMPRESSED_MOVES", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x2FC*/ { "CMSG_GUILD_INFO_TEXT", STATUS_LOGGEDIN, &WorldSession::HandleGuildChangeInfoOpcode }, - /*0x2FD*/ { "SMSG_CHAT_RESTRICTED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x2FE*/ { "SMSG_SPLINE_SET_RUN_SPEED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x2FF*/ { "SMSG_SPLINE_SET_RUN_BACK_SPEED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x300*/ { "SMSG_SPLINE_SET_SWIM_SPEED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x301*/ { "SMSG_SPLINE_SET_WALK_SPEED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x302*/ { "SMSG_SPLINE_SET_SWIM_BACK_SPEED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x303*/ { "SMSG_SPLINE_SET_TURN_RATE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x304*/ { "SMSG_SPLINE_MOVE_UNROOT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x305*/ { "SMSG_SPLINE_MOVE_FEATHER_FALL", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x306*/ { "SMSG_SPLINE_MOVE_NORMAL_FALL", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x307*/ { "SMSG_SPLINE_MOVE_SET_HOVER", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x308*/ { "SMSG_SPLINE_MOVE_UNSET_HOVER", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x309*/ { "SMSG_SPLINE_MOVE_WATER_WALK", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x30A*/ { "SMSG_SPLINE_MOVE_LAND_WALK", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x30B*/ { "SMSG_SPLINE_MOVE_START_SWIM", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x30C*/ { "SMSG_SPLINE_MOVE_STOP_SWIM", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x30D*/ { "SMSG_SPLINE_MOVE_SET_RUN_MODE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x30E*/ { "SMSG_SPLINE_MOVE_SET_WALK_MODE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x30F*/ { "CMSG_GM_NUKE_ACCOUNT", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x310*/ { "MSG_GM_DESTROY_CORPSE", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x311*/ { "CMSG_GM_DESTROY_ONLINE_CORPSE", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x312*/ { "CMSG_ACTIVATETAXIEXPRESS", STATUS_LOGGEDIN, &WorldSession::HandleActivateTaxiFarOpcode }, - /*0x313*/ { "SMSG_SET_FACTION_ATWAR", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x314*/ { "SMSG_GAMETIMEBIAS_SET", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x315*/ { "CMSG_DEBUG_ACTIONS_START", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x316*/ { "CMSG_DEBUG_ACTIONS_STOP", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x317*/ { "CMSG_SET_FACTION_INACTIVE", STATUS_LOGGEDIN, &WorldSession::HandleSetWatchedFactionInactiveOpcode}, - /*0x318*/ { "CMSG_SET_WATCHED_FACTION", STATUS_LOGGEDIN, &WorldSession::HandleSetWatchedFactionIndexOpcode}, - /*0x319*/ { "MSG_MOVE_TIME_SKIPPED", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x31A*/ { "SMSG_SPLINE_MOVE_ROOT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x31B*/ { "CMSG_SET_EXPLORATION_ALL", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x31C*/ { "SMSG_INVALIDATE_PLAYER", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x31D*/ { "CMSG_RESET_INSTANCES", STATUS_LOGGEDIN, &WorldSession::HandleResetInstancesOpcode }, - /*0x31E*/ { "SMSG_INSTANCE_RESET", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x31F*/ { "SMSG_INSTANCE_RESET_FAILED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x320*/ { "SMSG_UPDATE_LAST_INSTANCE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x321*/ { "MSG_RAID_TARGET_UPDATE", STATUS_LOGGEDIN, &WorldSession::HandleRaidIconTargetOpcode }, - /*0x322*/ { "MSG_RAID_READY_CHECK", STATUS_LOGGEDIN, &WorldSession::HandleRaidReadyCheckOpcode }, - /*0x323*/ { "CMSG_LUA_USAGE", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x324*/ { "SMSG_PET_ACTION_SOUND", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x325*/ { "SMSG_PET_DISMISS_SOUND", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x326*/ { "SMSG_GHOSTEE_GONE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x327*/ { "CMSG_GM_UPDATE_TICKET_STATUS", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x328*/ { "SMSG_GM_TICKET_STATUS_UPDATE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x329*/ { "MSG_SET_DUNGEON_DIFFICULTY", STATUS_LOGGEDIN, &WorldSession::HandleDungeonDifficultyOpcode }, - /*0x32A*/ { "CMSG_GMSURVEY_SUBMIT", STATUS_LOGGEDIN, &WorldSession::HandleGMSurveySubmit }, - /*0x32B*/ { "SMSG_UPDATE_INSTANCE_OWNERSHIP", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x32C*/ { "CMSG_IGNORE_KNOCKBACK_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x32D*/ { "SMSG_CHAT_PLAYER_AMBIGUOUS", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x32E*/ { "MSG_DELAY_GHOST_TELEPORT", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x32F*/ { "SMSG_SPELLINSTAKILLLOG", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x330*/ { "SMSG_SPELL_UPDATE_CHAIN_TARGETS", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x331*/ { "CMSG_CHAT_FILTERED", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x332*/ { "SMSG_EXPECTED_SPAM_RECORDS", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x333*/ { "SMSG_SPELLSTEALLOG", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x334*/ { "CMSG_LOTTERY_QUERY_OBSOLETE", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x335*/ { "SMSG_LOTTERY_QUERY_RESULT_OBSOLETE",STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x336*/ { "CMSG_BUY_LOTTERY_TICKET_OBSOLETE", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x337*/ { "SMSG_LOTTERY_RESULT_OBSOLETE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x338*/ { "SMSG_CHARACTER_PROFILE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x339*/ { "SMSG_CHARACTER_PROFILE_REALM_CONNECTED",STATUS_NEVER,&WorldSession::Handle_ServerSide }, - /*0x33A*/ { "SMSG_DEFENSE_MESSAGE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x33B*/ { "SMSG_INSTANCE_DIFFICULTY", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x33C*/ { "MSG_GM_RESETINSTANCELIMIT", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x33D*/ { "SMSG_MOTD", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x33E*/ { "SMSG_MOVE_SET_FLIGHT_OBSOLETE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x33F*/ { "SMSG_MOVE_UNSET_FLIGHT_OBSOLETE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x340*/ { "CMSG_MOVE_FLIGHT_ACK_OBSOLETE", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x341*/ { "MSG_MOVE_START_SWIM_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x342*/ { "MSG_MOVE_STOP_SWIM_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x343*/ { "SMSG_MOVE_SET_CAN_FLY", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x344*/ { "SMSG_MOVE_UNSET_CAN_FLY", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x345*/ { "CMSG_MOVE_SET_CAN_FLY_ACK", STATUS_LOGGEDIN, &WorldSession::HandleMoveFlyModeChangeAckOpcode}, - /*0x346*/ { "CMSG_MOVE_SET_FLY", STATUS_LOGGEDIN, &WorldSession::HandleMovementOpcodes }, - /*0x347*/ { "CMSG_SOCKET_GEMS", STATUS_LOGGEDIN, &WorldSession::HandleSocketOpcode }, - /*0x348*/ { "CMSG_ARENA_TEAM_CREATE", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x349*/ { "SMSG_ARENA_TEAM_COMMAND_RESULT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x34A*/ { "UMSG_UPDATE_ARENA_TEAM_OBSOLETE", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x34B*/ { "CMSG_ARENA_TEAM_QUERY", STATUS_LOGGEDIN, &WorldSession::HandleArenaTeamQueryOpcode }, - /*0x34C*/ { "SMSG_ARENA_TEAM_QUERY_RESPONSE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x34D*/ { "CMSG_ARENA_TEAM_ROSTER", STATUS_LOGGEDIN, &WorldSession::HandleArenaTeamRosterOpcode }, - /*0x34E*/ { "SMSG_ARENA_TEAM_ROSTER", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x34F*/ { "CMSG_ARENA_TEAM_INVITE", STATUS_LOGGEDIN, &WorldSession::HandleArenaTeamAddMemberOpcode }, - /*0x350*/ { "SMSG_ARENA_TEAM_INVITE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x351*/ { "CMSG_ARENA_TEAM_ACCEPT", STATUS_LOGGEDIN, &WorldSession::HandleArenaTeamInviteAcceptOpcode}, - /*0x352*/ { "CMSG_ARENA_TEAM_DECLINE", STATUS_LOGGEDIN, &WorldSession::HandleArenaTeamInviteDeclineOpcode}, - /*0x353*/ { "CMSG_ARENA_TEAM_LEAVE", STATUS_LOGGEDIN, &WorldSession::HandleArenaTeamLeaveOpcode }, - /*0x354*/ { "CMSG_ARENA_TEAM_REMOVE", STATUS_LOGGEDIN, &WorldSession::HandleArenaTeamRemoveFromTeamOpcode}, - /*0x355*/ { "CMSG_ARENA_TEAM_DISBAND", STATUS_LOGGEDIN, &WorldSession::HandleArenaTeamDisbandOpcode }, - /*0x356*/ { "CMSG_ARENA_TEAM_LEADER", STATUS_LOGGEDIN, &WorldSession::HandleArenaTeamPromoteToCaptainOpcode}, - /*0x357*/ { "SMSG_ARENA_TEAM_EVENT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x358*/ { "CMSG_BATTLEMASTER_JOIN_ARENA", STATUS_LOGGEDIN, &WorldSession::HandleBattleGroundArenaJoin }, - /*0x359*/ { "MSG_MOVE_START_ASCEND", STATUS_LOGGEDIN, &WorldSession::HandleMovementOpcodes }, - /*0x35A*/ { "MSG_MOVE_STOP_ASCEND", STATUS_LOGGEDIN, &WorldSession::HandleMovementOpcodes }, - /*0x35B*/ { "SMSG_ARENA_TEAM_STATS", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x35C*/ { "CMSG_LFG_SET_AUTOJOIN", STATUS_AUTHED, &WorldSession::HandleLfgAutoJoinOpcode }, - /*0x35D*/ { "CMSG_LFG_CLEAR_AUTOJOIN", STATUS_LOGGEDIN, &WorldSession::HandleLfgCancelAutoJoinOpcode }, - /*0x35E*/ { "CMSG_LFM_SET_AUTOFILL", STATUS_AUTHED, &WorldSession::HandleLfmAutoAddMembersOpcode }, - /*0x35F*/ { "CMSG_LFM_CLEAR_AUTOFILL", STATUS_LOGGEDIN, &WorldSession::HandleLfmCancelAutoAddmembersOpcode}, - /*0x360*/ { "CMSG_ACCEPT_LFG_MATCH", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x361*/ { "CMSG_DECLINE_LFG_MATCH", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x362*/ { "CMSG_CANCEL_PENDING_LFG", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x363*/ { "CMSG_CLEAR_LOOKING_FOR_GROUP", STATUS_LOGGEDIN, &WorldSession::HandleLfgClearOpcode }, - /*0x364*/ { "CMSG_CLEAR_LOOKING_FOR_MORE", STATUS_LOGGEDIN, &WorldSession::HandleLfmSetNoneOpcode }, - /*0x365*/ { "CMSG_SET_LOOKING_FOR_MORE", STATUS_LOGGEDIN, &WorldSession::HandleLfmSetOpcode }, - /*0x366*/ { "CMSG_SET_LFG_COMMENT", STATUS_LOGGEDIN, &WorldSession::HandleLfgSetCommentOpcode }, - /*0x367*/ { "SMSG_LFG_TIMEDOUT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x368*/ { "SMSG_LFG_OTHER_TIMEDOUT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x369*/ { "SMSG_LFG_AUTOJOIN_FAILED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x36A*/ { "SMSG_LFG_AUTOJOIN_FAILED_NO_PLAYER",STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x36B*/ { "SMSG_LFG_LEADER_IS_LFM", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x36C*/ { "SMSG_LFG_UPDATE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x36D*/ { "SMSG_LFG_UPDATE_LFM", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x36E*/ { "SMSG_LFG_UPDATE_LFG", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x36F*/ { "SMSG_LFG_UPDATE_QUEUED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x370*/ { "SMSG_LFG_PENDING_INVITE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x371*/ { "SMSG_LFG_PENDING_MATCH", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x372*/ { "SMSG_LFG_PENDING_MATCH_DONE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x373*/ { "SMSG_TITLE_EARNED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x374*/ { "CMSG_SET_TITLE", STATUS_LOGGEDIN, &WorldSession::HandleChooseTitleOpcode }, - /*0x375*/ { "CMSG_CANCEL_MOUNT_AURA", STATUS_LOGGEDIN, &WorldSession::HandleDismountOpcode }, - /*0x376*/ { "SMSG_ARENA_ERROR", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x377*/ { "MSG_INSPECT_ARENA_TEAMS", STATUS_LOGGEDIN, &WorldSession::HandleInspectArenaStatsOpcode }, - /*0x378*/ { "SMSG_DEATH_RELEASE_LOC", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x379*/ { "CMSG_CANCEL_TEMP_ENCHANTMENT", STATUS_LOGGEDIN, &WorldSession::HandleCancelTempItemEnchantmentOpcode}, - /*0x37A*/ { "SMSG_FORCED_DEATH_UPDATE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x37B*/ { "CMSG_CHEAT_SET_HONOR_CURRENCY", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x37C*/ { "CMSG_CHEAT_SET_ARENA_CURRENCY", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x37D*/ { "MSG_MOVE_SET_FLIGHT_SPEED_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x37E*/ { "MSG_MOVE_SET_FLIGHT_SPEED", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x37F*/ { "MSG_MOVE_SET_FLIGHT_BACK_SPEED_CHEAT",STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x380*/ { "MSG_MOVE_SET_FLIGHT_BACK_SPEED", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x381*/ { "SMSG_FORCE_FLIGHT_SPEED_CHANGE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x382*/ { "CMSG_FORCE_FLIGHT_SPEED_CHANGE_ACK",STATUS_LOGGEDIN,&WorldSession::HandleForceSpeedChangeAck }, - /*0x383*/ { "SMSG_FORCE_FLIGHT_BACK_SPEED_CHANGE",STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x384*/ { "CMSG_FORCE_FLIGHT_BACK_SPEED_CHANGE_ACK",STATUS_LOGGEDIN,&WorldSession::HandleForceSpeedChangeAck }, - /*0x385*/ { "SMSG_SPLINE_SET_FLIGHT_SPEED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x386*/ { "SMSG_SPLINE_SET_FLIGHT_BACK_SPEED",STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x387*/ { "CMSG_MAELSTROM_INVALIDATE_CACHE", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x388*/ { "SMSG_FLIGHT_SPLINE_SYNC", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x389*/ { "CMSG_SET_TAXI_BENCHMARK_MODE", STATUS_AUTHED, &WorldSession::HandleSetTaxiBenchmarkOpcode }, - /*0x38A*/ { "SMSG_JOINED_BATTLEGROUND_QUEUE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x38B*/ { "SMSG_REALM_SPLIT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x38C*/ { "CMSG_REALM_SPLIT", STATUS_AUTHED, &WorldSession::HandleRealmStateRequestOpcode }, - /*0x38D*/ { "CMSG_MOVE_CHNG_TRANSPORT", STATUS_LOGGEDIN, &WorldSession::HandleMovementOpcodes }, - /*0x38E*/ { "MSG_PARTY_ASSIGNMENT", STATUS_LOGGEDIN, &WorldSession::HandleGroupPromoteOpcode }, - /*0x38F*/ { "SMSG_OFFER_PETITION_ERROR", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x390*/ { "SMSG_TIME_SYNC_REQ", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x391*/ { "CMSG_TIME_SYNC_RESP", STATUS_LOGGEDIN, &WorldSession::HandleAllowMoveAckOpcode }, - /*0x392*/ { "CMSG_SEND_LOCAL_EVENT", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x393*/ { "CMSG_SEND_GENERAL_TRIGGER", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x394*/ { "CMSG_SEND_COMBAT_TRIGGER", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x395*/ { "CMSG_MAELSTROM_GM_SENT_MAIL", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x396*/ { "SMSG_RESET_FAILED_NOTIFY", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x397*/ { "SMSG_REAL_GROUP_UPDATE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x398*/ { "SMSG_LFG_DISABLED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x399*/ { "CMSG_ACTIVE_PVP_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x39A*/ { "CMSG_CHEAT_DUMP_ITEMS_DEBUG_ONLY", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x39B*/ { "SMSG_CHEAT_DUMP_ITEMS_DEBUG_ONLY_RESPONSE",STATUS_NEVER,&WorldSession::Handle_ServerSide }, - /*0x39C*/ { "SMSG_CHEAT_DUMP_ITEMS_DEBUG_ONLY_RESPONSE_WRITE_FILE",STATUS_NEVER,&WorldSession::Handle_ServerSide}, - /*0x39D*/ { "SMSG_UPDATE_COMBO_POINTS", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x39E*/ { "SMSG_VOICE_SESSION_ROSTER_UPDATE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x39F*/ { "SMSG_VOICE_SESSION_LEAVE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x3A0*/ { "SMSG_VOICE_SESSION_ADJUST_PRIORITY",STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x3A1*/ { "CMSG_VOICE_SET_TALKER_MUTED_REQUEST",STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x3A2*/ { "SMSG_VOICE_SET_TALKER_MUTED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x3A3*/ { "SMSG_INIT_EXTRA_AURA_INFO", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x3A4*/ { "SMSG_SET_EXTRA_AURA_INFO", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x3A5*/ { "SMSG_SET_EXTRA_AURA_INFO_NEED_UPDATE",STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x3A6*/ { "SMSG_CLEAR_EXTRA_AURA_INFO", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x3A7*/ { "MSG_MOVE_START_DESCEND", STATUS_LOGGEDIN, &WorldSession::HandleMovementOpcodes }, - /*0x3A8*/ { "CMSG_IGNORE_REQUIREMENTS_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x3A9*/ { "SMSG_IGNORE_REQUIREMENTS_CHEAT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x3AA*/ { "SMSG_SPELL_CHANCE_PROC_LOG", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x3AB*/ { "CMSG_MOVE_SET_RUN_SPEED", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x3AC*/ { "SMSG_DISMOUNT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x3AD*/ { "MSG_MOVE_UPDATE_CAN_FLY", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x3AE*/ { "MSG_RAID_READY_CHECK_CONFIRM", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x3AF*/ { "CMSG_VOICE_SESSION_ENABLE", STATUS_AUTHED, &WorldSession::HandleVoiceSettingsOpcode }, - /*0x3B0*/ { "SMSG_VOICE_PARENTAL_CONTROLS", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x3B1*/ { "CMSG_GM_WHISPER", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x3B2*/ { "SMSG_GM_MESSAGECHAT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x3B3*/ { "MSG_GM_GEARRATING", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x3B4*/ { "CMSG_COMMENTATOR_ENABLE", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x3B5*/ { "SMSG_COMMENTATOR_STATE_CHANGED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x3B6*/ { "CMSG_COMMENTATOR_GET_MAP_INFO", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x3B7*/ { "SMSG_COMMENTATOR_MAP_INFO", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x3B8*/ { "CMSG_COMMENTATOR_GET_PLAYER_INFO", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x3B9*/ { "SMSG_COMMENTATOR_GET_PLAYER_INFO", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x3BA*/ { "SMSG_COMMENTATOR_PLAYER_INFO", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x3BB*/ { "CMSG_COMMENTATOR_ENTER_INSTANCE", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x3BC*/ { "CMSG_COMMENTATOR_EXIT_INSTANCE", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x3BD*/ { "CMSG_COMMENTATOR_INSTANCE_COMMAND",STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x3BE*/ { "SMSG_CLEAR_TARGET", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x3BF*/ { "CMSG_BOT_DETECTED", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x3C0*/ { "SMSG_CROSSED_INEBRIATION_THRESHOLD",STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x3C1*/ { "CMSG_CHEAT_PLAYER_LOGIN", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x3C2*/ { "CMSG_CHEAT_PLAYER_LOOKUP", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x3C3*/ { "SMSG_CHEAT_PLAYER_LOOKUP", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x3C4*/ { "SMSG_KICK_REASON", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x3C5*/ { "MSG_RAID_READY_CHECK_FINISHED", STATUS_LOGGEDIN, &WorldSession::HandleRaidReadyCheckFinishOpcode}, - /*0x3C6*/ { "CMSG_COMPLAIN", STATUS_LOGGEDIN, &WorldSession::HandleReportSpamOpcode }, - /*0x3C7*/ { "SMSG_COMPLAIN_RESULT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x3C8*/ { "SMSG_FEATURE_SYSTEM_STATUS", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x3C9*/ { "CMSG_GM_SHOW_COMPLAINTS", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x3CA*/ { "CMSG_GM_UNSQUELCH", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x3CB*/ { "CMSG_CHANNEL_SILENCE_VOICE", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x3CC*/ { "CMSG_CHANNEL_SILENCE_ALL", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x3CD*/ { "CMSG_CHANNEL_UNSILENCE_VOICE", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x3CE*/ { "CMSG_CHANNEL_UNSILENCE_ALL", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x3CF*/ { "CMSG_TARGET_CAST", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x3D0*/ { "CMSG_TARGET_SCRIPT_CAST", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x3D1*/ { "CMSG_CHANNEL_DISPLAY_LIST", STATUS_LOGGEDIN, &WorldSession::HandleChannelRosterQuery }, - /*0x3D2*/ { "CMSG_SET_ACTIVE_VOICE_CHANNEL", STATUS_AUTHED, &WorldSession::HandleChannelVoiceChatQuery }, - /*0x3D3*/ { "CMSG_GET_CHANNEL_MEMBER_COUNT", STATUS_LOGGEDIN, &WorldSession::HandleChannelInfoQuery }, - /*0x3D4*/ { "SMSG_CHANNEL_MEMBER_COUNT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x3D5*/ { "CMSG_CHANNEL_VOICE_ON", STATUS_LOGGEDIN, &WorldSession::HandleChannelEnableVoiceOpcode }, - /*0x3D6*/ { "CMSG_CHANNEL_VOICE_OFF", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x3D7*/ { "CMSG_DEBUG_LIST_TARGETS", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x3D8*/ { "SMSG_DEBUG_LIST_TARGETS", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x3D9*/ { "SMSG_AVAILABLE_VOICE_CHANNEL", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x3DA*/ { "CMSG_ADD_VOICE_IGNORE", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x3DB*/ { "CMSG_DEL_VOICE_IGNORE", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x3DC*/ { "CMSG_PARTY_SILENCE", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x3DD*/ { "CMSG_PARTY_UNSILENCE", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x3DE*/ { "MSG_NOTIFY_PARTY_SQUELCH", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x3DF*/ { "SMSG_COMSAT_RECONNECT_TRY", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x3E0*/ { "SMSG_COMSAT_DISCONNECT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x3E1*/ { "SMSG_COMSAT_CONNECT_FAIL", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x3E2*/ { "SMSG_VOICE_CHAT_STATUS", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x3E3*/ { "CMSG_REPORT_PVP_AFK", STATUS_LOGGEDIN, &WorldSession::HandleBattleGroundReportAFK }, - /*0x3E4*/ { "CMSG_REPORT_PVP_AFK_RESULT", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x3E5*/ { "CMSG_GUILD_BANKER_ACTIVATE", STATUS_LOGGEDIN, &WorldSession::HandleGuildBankQuery }, - /*0x3E6*/ { "CMSG_GUILD_BANK_QUERY_TAB", STATUS_LOGGEDIN, &WorldSession::HandleGuildBankTabColon }, - /*0x3E7*/ { "SMSG_GUILD_BANK_LIST", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x3E8*/ { "CMSG_GUILD_BANK_SWAP_ITEMS", STATUS_LOGGEDIN, &WorldSession::HandleGuildBankDepositItem }, - /*0x3E9*/ { "CMSG_GUILD_BANK_BUY_TAB", STATUS_LOGGEDIN, &WorldSession::HandleGuildBankBuyTab }, - /*0x3EA*/ { "CMSG_GUILD_BANK_UPDATE_TAB", STATUS_LOGGEDIN, &WorldSession::HandleGuildBankModifyTab }, - /*0x3EB*/ { "CMSG_GUILD_BANK_DEPOSIT_MONEY", STATUS_LOGGEDIN, &WorldSession::HandleGuildBankDeposit }, - /*0x3EC*/ { "CMSG_GUILD_BANK_WITHDRAW_MONEY", STATUS_LOGGEDIN, &WorldSession::HandleGuildBankWithdraw }, - /*0x3ED*/ { "MSG_GUILD_BANK_LOG_QUERY", STATUS_LOGGEDIN, &WorldSession::HandleGuildBankLog }, - /*0x3EE*/ { "CMSG_SET_CHANNEL_WATCH", STATUS_LOGGEDIN, &WorldSession::HandleChannelJoinNotify }, - /*0x3EF*/ { "SMSG_USERLIST_ADD", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x3F0*/ { "SMSG_USERLIST_REMOVE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x3F1*/ { "SMSG_USERLIST_UPDATE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x3F2*/ { "CMSG_CLEAR_CHANNEL_WATCH", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x3F3*/ { "SMSG_INSPECT_TALENT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x3F4*/ { "SMSG_GOGOGO_OBSOLETE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x3F5*/ { "SMSG_ECHO_PARTY_SQUELCH", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x3F6*/ { "CMSG_SET_TITLE_SUFFIX", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x3F7*/ { "CMSG_SPELLCLICK", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x3F8*/ { "SMSG_LOOT_LIST", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x3F9*/ { "CMSG_GM_CHARACTER_RESTORE", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x3FA*/ { "CMSG_GM_CHARACTER_SAVE", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x3FB*/ { "SMSG_VOICESESSION_FULL", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x3FC*/ { "MSG_GUILD_PERMISSIONS", STATUS_LOGGEDIN, &WorldSession::HandleGuildBankGetRights }, - /*0x3FD*/ { "MSG_GUILD_BANK_MONEY_WITHDRAWN", STATUS_LOGGEDIN, &WorldSession::HandleGuildBankGetMoneyAmount }, - /*0x3FE*/ { "MSG_GUILD_EVENT_LOG_QUERY", STATUS_LOGGEDIN, &WorldSession::HandleGuildEventLogOpcode }, - /*0x3FF*/ { "CMSG_MAELSTROM_RENAME_GUILD", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x400*/ { "CMSG_GET_MIRRORIMAGE_DATA", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x401*/ { "SMSG_MIRRORIMAGE_DATA", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x402*/ { "SMSG_FORCE_DISPLAY_UPDATE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x403*/ { "SMSG_SPELL_CHANCE_RESIST_PUSHBACK",STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x404*/ { "CMSG_IGNORE_DIMINISHING_RETURNS_CHEAT",STATUS_NEVER,&WorldSession::Handle_NULL }, - /*0x405*/ { "SMSG_IGNORE_DIMINISHING_RETURNS_CHEAT",STATUS_NEVER,&WorldSession::Handle_ServerSide }, - /*0x406*/ { "CMSG_KEEP_ALIVE", STATUS_NEVER, &WorldSession::Handle_EarlyProccess }, - /*0x407*/ { "SMSG_RAID_READY_CHECK_ERROR", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x408*/ { "CMSG_OPT_OUT_OF_LOOT", STATUS_AUTHED, &WorldSession::HandleGroupPassOnLootOpcode }, - /*0x409*/ { "MSG_QUERY_GUILD_BANK_TEXT", STATUS_LOGGEDIN, &WorldSession::HandleGuildBankTabText }, - /*0x40A*/ { "CMSG_SET_GUILD_BANK_TEXT", STATUS_LOGGEDIN, &WorldSession::HandleGuildBankSetTabText }, - /*0x40B*/ { "CMSG_SET_GRANTABLE_LEVELS", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x40C*/ { "CMSG_GRANT_LEVEL", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x40D*/ { "CMSG_REFER_A_FRIEND", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x40E*/ { "MSG_GM_CHANGE_ARENA_RATING", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x40F*/ { "CMSG_DECLINE_CHANNEL_INVITE", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x410*/ { "CMSG_GROUPACTION_THROTTLED", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x411*/ { "SMSG_OVERRIDE_LIGHT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x412*/ { "SMSG_TOTEM_CREATED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x413*/ { "CMSG_TOTEM_DESTROYED", STATUS_LOGGEDIN, &WorldSession::HandleTotemDestroy }, - /*0x414*/ { "CMSG_EXPIRE_RAID_INSTANCE", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x415*/ { "CMSG_NO_SPELL_VARIANCE", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x416*/ { "CMSG_QUESTGIVER_STATUS_MULTIPLE_QUERY",STATUS_LOGGEDIN,&WorldSession::HandleQuestgiverStatusQueryMultipleOpcode}, - /*0x417*/ { "SMSG_QUESTGIVER_STATUS_MULTIPLE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x418*/ { "CMSG_SET_PLAYER_DECLINED_NAMES", STATUS_AUTHED, &WorldSession::HandleDeclinedPlayerNameOpcode }, - /*0x419*/ { "SMSG_SET_PLAYER_DECLINED_NAMES_RESULT",STATUS_NEVER,&WorldSession::Handle_ServerSide }, - /*0x41A*/ { "CMSG_QUERY_SERVER_BUCK_DATA", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x41B*/ { "CMSG_CLEAR_SERVER_BUCK_DATA", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x41C*/ { "SMSG_SERVER_BUCK_DATA", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x41D*/ { "SMSG_SEND_UNLEARN_SPELLS", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x41E*/ { "SMSG_PROPOSE_LEVEL_GRANT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x41F*/ { "CMSG_ACCEPT_LEVEL_GRANT", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x420*/ { "SMSG_REFER_A_FRIEND_FAILURE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x421*/ { "SMSG_SPLINE_MOVE_SET_FLYING", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x422*/ { "SMSG_SPLINE_MOVE_UNSET_FLYING", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x423*/ { "SMSG_SUMMON_CANCEL", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x000*/ { "MSG_NULL_ACTION", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x001*/ { "CMSG_BOOTME", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x002*/ { "CMSG_DBLOOKUP", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x003*/ { "SMSG_DBLOOKUP", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x004*/ { "CMSG_QUERY_OBJECT_POSITION", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x005*/ { "SMSG_QUERY_OBJECT_POSITION", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x006*/ { "CMSG_QUERY_OBJECT_ROTATION", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x007*/ { "SMSG_QUERY_OBJECT_ROTATION", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x008*/ { "CMSG_WORLD_TELEPORT", STATUS_LOGGEDIN, &WorldSession::HandleWorldTeleportOpcode }, + /*0x009*/ { "CMSG_TELEPORT_TO_UNIT", STATUS_LOGGEDIN, &WorldSession::Handle_NULL }, + /*0x00A*/ { "CMSG_ZONE_MAP", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x00B*/ { "SMSG_ZONE_MAP", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x00C*/ { "CMSG_DEBUG_CHANGECELLZONE", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x00D*/ { "CMSG_MOVE_CHARACTER_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x00E*/ { "SMSG_MOVE_CHARACTER_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x00F*/ { "CMSG_RECHARGE", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x010*/ { "CMSG_LEARN_SPELL", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x011*/ { "CMSG_CREATEMONSTER", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x012*/ { "CMSG_DESTROYMONSTER", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x013*/ { "CMSG_CREATEITEM", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x014*/ { "CMSG_CREATEGAMEOBJECT", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x015*/ { "SMSG_CHECK_FOR_BOTS", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x016*/ { "CMSG_MAKEMONSTERATTACKGUID", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x017*/ { "CMSG_BOT_DETECTED2", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x018*/ { "CMSG_FORCEACTION", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x019*/ { "CMSG_FORCEACTIONONOTHER", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x01A*/ { "CMSG_FORCEACTIONSHOW", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x01B*/ { "SMSG_FORCEACTIONSHOW", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x01C*/ { "CMSG_PETGODMODE", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x01D*/ { "SMSG_PETGODMODE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x01E*/ { "SMSG_REFER_A_FRIEND_EXPIRED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x01F*/ { "CMSG_WEATHER_SPEED_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x020*/ { "CMSG_UNDRESSPLAYER", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x021*/ { "CMSG_BEASTMASTER", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x022*/ { "CMSG_GODMODE", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x023*/ { "SMSG_GODMODE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x024*/ { "CMSG_CHEAT_SETMONEY", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x025*/ { "CMSG_LEVEL_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x026*/ { "CMSG_PET_LEVEL_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x027*/ { "CMSG_SET_WORLDSTATE", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x028*/ { "CMSG_COOLDOWN_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x029*/ { "CMSG_USE_SKILL_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x02A*/ { "CMSG_FLAG_QUEST", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x02B*/ { "CMSG_FLAG_QUEST_FINISH", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x02C*/ { "CMSG_CLEAR_QUEST", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x02D*/ { "CMSG_SEND_EVENT", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x02E*/ { "CMSG_DEBUG_AISTATE", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x02F*/ { "SMSG_DEBUG_AISTATE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x030*/ { "CMSG_DISABLE_PVP_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x031*/ { "CMSG_ADVANCE_SPAWN_TIME", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x032*/ { "SMSG_DESTRUCTIBLE_BUILDING_DAMAGE", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x033*/ { "CMSG_AUTH_SRP6_BEGIN", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x034*/ { "CMSG_AUTH_SRP6_PROOF", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x035*/ { "CMSG_AUTH_SRP6_RECODE", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x036*/ { "CMSG_CHAR_CREATE", STATUS_AUTHED, &WorldSession::HandleCharCreateOpcode }, + /*0x037*/ { "CMSG_CHAR_ENUM", STATUS_AUTHED, &WorldSession::HandleCharEnumOpcode }, + /*0x038*/ { "CMSG_CHAR_DELETE", STATUS_AUTHED, &WorldSession::HandleCharDeleteOpcode }, + /*0x039*/ { "SMSG_AUTH_SRP6_RESPONSE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x03A*/ { "SMSG_CHAR_CREATE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x03B*/ { "SMSG_CHAR_ENUM", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x03C*/ { "SMSG_CHAR_DELETE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x03D*/ { "CMSG_PLAYER_LOGIN", STATUS_AUTHED, &WorldSession::HandlePlayerLoginOpcode }, + /*0x03E*/ { "SMSG_NEW_WORLD", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x03F*/ { "SMSG_TRANSFER_PENDING", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x040*/ { "SMSG_TRANSFER_ABORTED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x041*/ { "SMSG_CHARACTER_LOGIN_FAILED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x042*/ { "SMSG_LOGIN_SETTIMESPEED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x043*/ { "SMSG_GAMETIME_UPDATE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x044*/ { "CMSG_GAMETIME_SET", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x045*/ { "SMSG_GAMETIME_SET", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x046*/ { "CMSG_GAMESPEED_SET", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x047*/ { "SMSG_GAMESPEED_SET", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x048*/ { "CMSG_SERVERTIME", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x049*/ { "SMSG_SERVERTIME", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x04A*/ { "CMSG_PLAYER_LOGOUT", STATUS_LOGGEDIN, &WorldSession::HandlePlayerLogoutOpcode }, + /*0x04B*/ { "CMSG_LOGOUT_REQUEST", STATUS_LOGGEDIN, &WorldSession::HandleLogoutRequestOpcode }, + /*0x04C*/ { "SMSG_LOGOUT_RESPONSE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x04D*/ { "SMSG_LOGOUT_COMPLETE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x04E*/ { "CMSG_LOGOUT_CANCEL", STATUS_LOGGEDIN, &WorldSession::HandleLogoutCancelOpcode }, + /*0x04F*/ { "SMSG_LOGOUT_CANCEL_ACK", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x050*/ { "CMSG_NAME_QUERY", STATUS_LOGGEDIN, &WorldSession::HandleNameQueryOpcode }, + /*0x051*/ { "SMSG_NAME_QUERY_RESPONSE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x052*/ { "CMSG_PET_NAME_QUERY", STATUS_LOGGEDIN, &WorldSession::HandlePetNameQuery }, + /*0x053*/ { "SMSG_PET_NAME_QUERY_RESPONSE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x054*/ { "CMSG_GUILD_QUERY", STATUS_AUTHED, &WorldSession::HandleGuildQueryOpcode }, + /*0x055*/ { "SMSG_GUILD_QUERY_RESPONSE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x056*/ { "CMSG_ITEM_QUERY_SINGLE", STATUS_LOGGEDIN, &WorldSession::HandleItemQuerySingleOpcode }, + /*0x057*/ { "CMSG_ITEM_QUERY_MULTIPLE", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x058*/ { "SMSG_ITEM_QUERY_SINGLE_RESPONSE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x059*/ { "SMSG_ITEM_QUERY_MULTIPLE_RESPONSE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x05A*/ { "CMSG_PAGE_TEXT_QUERY", STATUS_LOGGEDIN, &WorldSession::HandlePageQueryOpcode }, + /*0x05B*/ { "SMSG_PAGE_TEXT_QUERY_RESPONSE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x05C*/ { "CMSG_QUEST_QUERY", STATUS_LOGGEDIN, &WorldSession::HandleQuestQueryOpcode }, + /*0x05D*/ { "SMSG_QUEST_QUERY_RESPONSE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x05E*/ { "CMSG_GAMEOBJECT_QUERY", STATUS_LOGGEDIN, &WorldSession::HandleGameObjectQueryOpcode }, + /*0x05F*/ { "SMSG_GAMEOBJECT_QUERY_RESPONSE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x060*/ { "CMSG_CREATURE_QUERY", STATUS_LOGGEDIN, &WorldSession::HandleCreatureQueryOpcode }, + /*0x061*/ { "SMSG_CREATURE_QUERY_RESPONSE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x062*/ { "CMSG_WHO", STATUS_LOGGEDIN, &WorldSession::HandleWhoOpcode }, + /*0x063*/ { "SMSG_WHO", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x064*/ { "CMSG_WHOIS", STATUS_LOGGEDIN, &WorldSession::HandleWhoisOpcode }, + /*0x065*/ { "SMSG_WHOIS", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x066*/ { "CMSG_CONTACT_LIST", STATUS_LOGGEDIN, &WorldSession::HandleFriendListOpcode }, + /*0x067*/ { "SMSG_CONTACT_LIST", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x068*/ { "SMSG_FRIEND_STATUS", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x069*/ { "CMSG_ADD_FRIEND", STATUS_LOGGEDIN, &WorldSession::HandleAddFriendOpcode }, + /*0x06A*/ { "CMSG_DEL_FRIEND", STATUS_LOGGEDIN, &WorldSession::HandleDelFriendOpcode }, + /*0x06B*/ { "CMSG_SET_CONTACT_NOTES", STATUS_LOGGEDIN, &WorldSession::HandleSetFriendNoteOpcode }, + /*0x06C*/ { "CMSG_ADD_IGNORE", STATUS_LOGGEDIN, &WorldSession::HandleAddIgnoreOpcode }, + /*0x06D*/ { "CMSG_DEL_IGNORE", STATUS_LOGGEDIN, &WorldSession::HandleDelIgnoreOpcode }, + /*0x06E*/ { "CMSG_GROUP_INVITE", STATUS_LOGGEDIN, &WorldSession::HandleGroupInviteOpcode }, + /*0x06F*/ { "SMSG_GROUP_INVITE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x070*/ { "CMSG_GROUP_CANCEL", STATUS_LOGGEDIN, &WorldSession::Handle_Deprecated }, + /*0x071*/ { "SMSG_GROUP_CANCEL", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x072*/ { "CMSG_GROUP_ACCEPT", STATUS_LOGGEDIN, &WorldSession::HandleGroupAcceptOpcode }, + /*0x073*/ { "CMSG_GROUP_DECLINE", STATUS_LOGGEDIN, &WorldSession::HandleGroupDeclineOpcode }, + /*0x074*/ { "SMSG_GROUP_DECLINE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x075*/ { "CMSG_GROUP_UNINVITE", STATUS_LOGGEDIN, &WorldSession::HandleGroupUninviteNameOpcode }, + /*0x076*/ { "CMSG_GROUP_UNINVITE_GUID", STATUS_LOGGEDIN, &WorldSession::HandleGroupUninviteGuidOpcode }, + /*0x077*/ { "SMSG_GROUP_UNINVITE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x078*/ { "CMSG_GROUP_SET_LEADER", STATUS_LOGGEDIN, &WorldSession::HandleGroupSetLeaderOpcode }, + /*0x079*/ { "SMSG_GROUP_SET_LEADER", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x07A*/ { "CMSG_LOOT_METHOD", STATUS_LOGGEDIN, &WorldSession::HandleLootMethodOpcode }, + /*0x07B*/ { "CMSG_GROUP_DISBAND", STATUS_LOGGEDIN, &WorldSession::HandleGroupLeaveOpcode }, + /*0x07C*/ { "SMSG_GROUP_DESTROYED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x07D*/ { "SMSG_GROUP_LIST", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x07E*/ { "SMSG_PARTY_MEMBER_STATS", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x07F*/ { "SMSG_PARTY_COMMAND_RESULT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x080*/ { "UMSG_UPDATE_GROUP_MEMBERS", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x081*/ { "CMSG_GUILD_CREATE", STATUS_LOGGEDIN, &WorldSession::HandleGuildCreateOpcode }, + /*0x082*/ { "CMSG_GUILD_INVITE", STATUS_LOGGEDIN, &WorldSession::HandleGuildInviteOpcode }, + /*0x083*/ { "SMSG_GUILD_INVITE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x084*/ { "CMSG_GUILD_ACCEPT", STATUS_LOGGEDIN, &WorldSession::HandleGuildAcceptOpcode }, + /*0x085*/ { "CMSG_GUILD_DECLINE", STATUS_LOGGEDIN, &WorldSession::HandleGuildDeclineOpcode }, + /*0x086*/ { "SMSG_GUILD_DECLINE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x087*/ { "CMSG_GUILD_INFO", STATUS_LOGGEDIN, &WorldSession::HandleGuildInfoOpcode }, + /*0x088*/ { "SMSG_GUILD_INFO", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x089*/ { "CMSG_GUILD_ROSTER", STATUS_LOGGEDIN, &WorldSession::HandleGuildRosterOpcode }, + /*0x08A*/ { "SMSG_GUILD_ROSTER", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x08B*/ { "CMSG_GUILD_PROMOTE", STATUS_LOGGEDIN, &WorldSession::HandleGuildPromoteOpcode }, + /*0x08C*/ { "CMSG_GUILD_DEMOTE", STATUS_LOGGEDIN, &WorldSession::HandleGuildDemoteOpcode }, + /*0x08D*/ { "CMSG_GUILD_LEAVE", STATUS_LOGGEDIN, &WorldSession::HandleGuildLeaveOpcode }, + /*0x08E*/ { "CMSG_GUILD_REMOVE", STATUS_LOGGEDIN, &WorldSession::HandleGuildRemoveOpcode }, + /*0x08F*/ { "CMSG_GUILD_DISBAND", STATUS_LOGGEDIN, &WorldSession::HandleGuildDisbandOpcode }, + /*0x090*/ { "CMSG_GUILD_LEADER", STATUS_LOGGEDIN, &WorldSession::HandleGuildLeaderOpcode }, + /*0x091*/ { "CMSG_GUILD_MOTD", STATUS_LOGGEDIN, &WorldSession::HandleGuildMOTDOpcode }, + /*0x092*/ { "SMSG_GUILD_EVENT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x093*/ { "SMSG_GUILD_COMMAND_RESULT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x094*/ { "UMSG_UPDATE_GUILD", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x095*/ { "CMSG_MESSAGECHAT", STATUS_LOGGEDIN, &WorldSession::HandleMessagechatOpcode }, + /*0x096*/ { "SMSG_MESSAGECHAT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x097*/ { "CMSG_JOIN_CHANNEL", STATUS_LOGGEDIN, &WorldSession::HandleChannelJoin }, + /*0x098*/ { "CMSG_LEAVE_CHANNEL", STATUS_LOGGEDIN, &WorldSession::HandleChannelLeave }, + /*0x099*/ { "SMSG_CHANNEL_NOTIFY", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x09A*/ { "CMSG_CHANNEL_LIST", STATUS_LOGGEDIN, &WorldSession::HandleChannelList }, + /*0x09B*/ { "SMSG_CHANNEL_LIST", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x09C*/ { "CMSG_CHANNEL_PASSWORD", STATUS_LOGGEDIN, &WorldSession::HandleChannelPassword }, + /*0x09D*/ { "CMSG_CHANNEL_SET_OWNER", STATUS_LOGGEDIN, &WorldSession::HandleChannelSetOwner }, + /*0x09E*/ { "CMSG_CHANNEL_OWNER", STATUS_LOGGEDIN, &WorldSession::HandleChannelOwner }, + /*0x09F*/ { "CMSG_CHANNEL_MODERATOR", STATUS_LOGGEDIN, &WorldSession::HandleChannelModerator }, + /*0x0A0*/ { "CMSG_CHANNEL_UNMODERATOR", STATUS_LOGGEDIN, &WorldSession::HandleChannelUnmoderator }, + /*0x0A1*/ { "CMSG_CHANNEL_MUTE", STATUS_LOGGEDIN, &WorldSession::HandleChannelMute }, + /*0x0A2*/ { "CMSG_CHANNEL_UNMUTE", STATUS_LOGGEDIN, &WorldSession::HandleChannelUnmute }, + /*0x0A3*/ { "CMSG_CHANNEL_INVITE", STATUS_LOGGEDIN, &WorldSession::HandleChannelInvite }, + /*0x0A4*/ { "CMSG_CHANNEL_KICK", STATUS_LOGGEDIN, &WorldSession::HandleChannelKick }, + /*0x0A5*/ { "CMSG_CHANNEL_BAN", STATUS_LOGGEDIN, &WorldSession::HandleChannelBan }, + /*0x0A6*/ { "CMSG_CHANNEL_UNBAN", STATUS_LOGGEDIN, &WorldSession::HandleChannelUnban }, + /*0x0A7*/ { "CMSG_CHANNEL_ANNOUNCEMENTS", STATUS_LOGGEDIN, &WorldSession::HandleChannelAnnounce }, + /*0x0A8*/ { "CMSG_CHANNEL_MODERATE", STATUS_LOGGEDIN, &WorldSession::HandleChannelModerate }, + /*0x0A9*/ { "SMSG_UPDATE_OBJECT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x0AA*/ { "SMSG_DESTROY_OBJECT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x0AB*/ { "CMSG_USE_ITEM", STATUS_LOGGEDIN, &WorldSession::HandleUseItemOpcode }, + /*0x0AC*/ { "CMSG_OPEN_ITEM", STATUS_LOGGEDIN, &WorldSession::HandleOpenItemOpcode }, + /*0x0AD*/ { "CMSG_READ_ITEM", STATUS_LOGGEDIN, &WorldSession::HandleReadItem }, + /*0x0AE*/ { "SMSG_READ_ITEM_OK", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x0AF*/ { "SMSG_READ_ITEM_FAILED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x0B0*/ { "SMSG_ITEM_COOLDOWN", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x0B1*/ { "CMSG_GAMEOBJ_USE", STATUS_LOGGEDIN, &WorldSession::HandleGameObjectUseOpcode }, + /*0x0B2*/ { "CMSG_DESTROY_ITEMS", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x0B3*/ { "SMSG_GAMEOBJECT_CUSTOM_ANIM", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x0B4*/ { "CMSG_AREATRIGGER", STATUS_LOGGEDIN, &WorldSession::HandleAreaTriggerOpcode }, + /*0x0B5*/ { "MSG_MOVE_START_FORWARD", STATUS_LOGGEDIN, &WorldSession::HandleMovementOpcodes }, + /*0x0B6*/ { "MSG_MOVE_START_BACKWARD", STATUS_LOGGEDIN, &WorldSession::HandleMovementOpcodes }, + /*0x0B7*/ { "MSG_MOVE_STOP", STATUS_LOGGEDIN, &WorldSession::HandleMovementOpcodes }, + /*0x0B8*/ { "MSG_MOVE_START_STRAFE_LEFT", STATUS_LOGGEDIN, &WorldSession::HandleMovementOpcodes }, + /*0x0B9*/ { "MSG_MOVE_START_STRAFE_RIGHT", STATUS_LOGGEDIN, &WorldSession::HandleMovementOpcodes }, + /*0x0BA*/ { "MSG_MOVE_STOP_STRAFE", STATUS_LOGGEDIN, &WorldSession::HandleMovementOpcodes }, + /*0x0BB*/ { "MSG_MOVE_JUMP", STATUS_LOGGEDIN, &WorldSession::HandleMovementOpcodes }, + /*0x0BC*/ { "MSG_MOVE_START_TURN_LEFT", STATUS_LOGGEDIN, &WorldSession::HandleMovementOpcodes }, + /*0x0BD*/ { "MSG_MOVE_START_TURN_RIGHT", STATUS_LOGGEDIN, &WorldSession::HandleMovementOpcodes }, + /*0x0BE*/ { "MSG_MOVE_STOP_TURN", STATUS_LOGGEDIN, &WorldSession::HandleMovementOpcodes }, + /*0x0BF*/ { "MSG_MOVE_START_PITCH_UP", STATUS_LOGGEDIN, &WorldSession::HandleMovementOpcodes }, + /*0x0C0*/ { "MSG_MOVE_START_PITCH_DOWN", STATUS_LOGGEDIN, &WorldSession::HandleMovementOpcodes }, + /*0x0C1*/ { "MSG_MOVE_STOP_PITCH", STATUS_LOGGEDIN, &WorldSession::HandleMovementOpcodes }, + /*0x0C2*/ { "MSG_MOVE_SET_RUN_MODE", STATUS_LOGGEDIN, &WorldSession::HandleMovementOpcodes }, + /*0x0C3*/ { "MSG_MOVE_SET_WALK_MODE", STATUS_LOGGEDIN, &WorldSession::HandleMovementOpcodes }, + /*0x0C4*/ { "MSG_MOVE_TOGGLE_LOGGING", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x0C5*/ { "MSG_MOVE_TELEPORT", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x0C6*/ { "MSG_MOVE_TELEPORT_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x0C7*/ { "MSG_MOVE_TELEPORT_ACK", STATUS_LOGGEDIN, &WorldSession::HandleMoveTeleportAck }, + /*0x0C8*/ { "MSG_MOVE_TOGGLE_FALL_LOGGING", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x0C9*/ { "MSG_MOVE_FALL_LAND", STATUS_LOGGEDIN, &WorldSession::HandleMovementOpcodes }, + /*0x0CA*/ { "MSG_MOVE_START_SWIM", STATUS_LOGGEDIN, &WorldSession::HandleMovementOpcodes }, + /*0x0CB*/ { "MSG_MOVE_STOP_SWIM", STATUS_LOGGEDIN, &WorldSession::HandleMovementOpcodes }, + /*0x0CC*/ { "MSG_MOVE_SET_RUN_SPEED_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x0CD*/ { "MSG_MOVE_SET_RUN_SPEED", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x0CE*/ { "MSG_MOVE_SET_RUN_BACK_SPEED_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x0CF*/ { "MSG_MOVE_SET_RUN_BACK_SPEED", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x0D0*/ { "MSG_MOVE_SET_WALK_SPEED_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x0D1*/ { "MSG_MOVE_SET_WALK_SPEED", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x0D2*/ { "MSG_MOVE_SET_SWIM_SPEED_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x0D3*/ { "MSG_MOVE_SET_SWIM_SPEED", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x0D4*/ { "MSG_MOVE_SET_SWIM_BACK_SPEED_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x0D5*/ { "MSG_MOVE_SET_SWIM_BACK_SPEED", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x0D6*/ { "MSG_MOVE_SET_ALL_SPEED_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x0D7*/ { "MSG_MOVE_SET_TURN_RATE_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x0D8*/ { "MSG_MOVE_SET_TURN_RATE", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x0D9*/ { "MSG_MOVE_TOGGLE_COLLISION_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x0DA*/ { "MSG_MOVE_SET_FACING", STATUS_LOGGEDIN, &WorldSession::HandleMovementOpcodes }, + /*0x0DB*/ { "MSG_MOVE_SET_PITCH", STATUS_LOGGEDIN, &WorldSession::HandleMovementOpcodes }, + /*0x0DC*/ { "MSG_MOVE_WORLDPORT_ACK", STATUS_TRANSFER_PENDING,&WorldSession::HandleMoveWorldportAckOpcode}, + /*0x0DD*/ { "SMSG_MONSTER_MOVE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x0DE*/ { "SMSG_MOVE_WATER_WALK", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x0DF*/ { "SMSG_MOVE_LAND_WALK", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x0E0*/ { "MSG_MOVE_SET_RAW_POSITION_ACK", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x0E1*/ { "CMSG_MOVE_SET_RAW_POSITION", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x0E2*/ { "SMSG_FORCE_RUN_SPEED_CHANGE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x0E3*/ { "CMSG_FORCE_RUN_SPEED_CHANGE_ACK", STATUS_LOGGEDIN, &WorldSession::HandleForceSpeedChangeAck }, + /*0x0E4*/ { "SMSG_FORCE_RUN_BACK_SPEED_CHANGE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x0E5*/ { "CMSG_FORCE_RUN_BACK_SPEED_CHANGE_ACK", STATUS_LOGGEDIN, &WorldSession::HandleForceSpeedChangeAck }, + /*0x0E6*/ { "SMSG_FORCE_SWIM_SPEED_CHANGE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x0E7*/ { "CMSG_FORCE_SWIM_SPEED_CHANGE_ACK", STATUS_LOGGEDIN, &WorldSession::HandleForceSpeedChangeAck }, + /*0x0E8*/ { "SMSG_FORCE_MOVE_ROOT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x0E9*/ { "CMSG_FORCE_MOVE_ROOT_ACK", STATUS_LOGGEDIN, &WorldSession::HandleMoveRootAck }, + /*0x0EA*/ { "SMSG_FORCE_MOVE_UNROOT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x0EB*/ { "CMSG_FORCE_MOVE_UNROOT_ACK", STATUS_LOGGEDIN, &WorldSession::HandleMoveUnRootAck }, + /*0x0EC*/ { "MSG_MOVE_ROOT", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x0ED*/ { "MSG_MOVE_UNROOT", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x0EE*/ { "MSG_MOVE_HEARTBEAT", STATUS_LOGGEDIN, &WorldSession::HandleMovementOpcodes }, + /*0x0EF*/ { "SMSG_MOVE_KNOCK_BACK", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x0F0*/ { "CMSG_MOVE_KNOCK_BACK_ACK", STATUS_LOGGEDIN, &WorldSession::HandleMoveKnockBackAck }, + /*0x0F1*/ { "MSG_MOVE_KNOCK_BACK", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x0F2*/ { "SMSG_MOVE_FEATHER_FALL", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x0F3*/ { "SMSG_MOVE_NORMAL_FALL", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x0F4*/ { "SMSG_MOVE_SET_HOVER", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x0F5*/ { "SMSG_MOVE_UNSET_HOVER", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x0F6*/ { "CMSG_MOVE_HOVER_ACK", STATUS_LOGGEDIN, &WorldSession::HandleMoveHoverAck }, + /*0x0F7*/ { "MSG_MOVE_HOVER", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x0F8*/ { "CMSG_TRIGGER_CINEMATIC_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x0F9*/ { "CMSG_OPENING_CINEMATIC", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x0FA*/ { "SMSG_TRIGGER_CINEMATIC", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x0FB*/ { "CMSG_NEXT_CINEMATIC_CAMERA", STATUS_LOGGEDIN, &WorldSession::HandleNextCinematicCamera }, + /*0x0FC*/ { "CMSG_COMPLETE_CINEMATIC", STATUS_LOGGEDIN, &WorldSession::HandleCompleteCinema }, + /*0x0FD*/ { "SMSG_TUTORIAL_FLAGS", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x0FE*/ { "CMSG_TUTORIAL_FLAG", STATUS_LOGGEDIN, &WorldSession::HandleTutorialFlag }, + /*0x0FF*/ { "CMSG_TUTORIAL_CLEAR", STATUS_LOGGEDIN, &WorldSession::HandleTutorialClear }, + /*0x100*/ { "CMSG_TUTORIAL_RESET", STATUS_LOGGEDIN, &WorldSession::HandleTutorialReset }, + /*0x101*/ { "CMSG_STANDSTATECHANGE", STATUS_LOGGEDIN, &WorldSession::HandleStandStateChangeOpcode }, + /*0x102*/ { "CMSG_EMOTE", STATUS_LOGGEDIN, &WorldSession::HandleEmoteOpcode }, + /*0x103*/ { "SMSG_EMOTE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x104*/ { "CMSG_TEXT_EMOTE", STATUS_LOGGEDIN, &WorldSession::HandleTextEmoteOpcode }, + /*0x105*/ { "SMSG_TEXT_EMOTE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x106*/ { "CMSG_AUTOEQUIP_GROUND_ITEM", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x107*/ { "CMSG_AUTOSTORE_GROUND_ITEM", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x108*/ { "CMSG_AUTOSTORE_LOOT_ITEM", STATUS_LOGGEDIN, &WorldSession::HandleAutostoreLootItemOpcode }, + /*0x109*/ { "CMSG_STORE_LOOT_IN_SLOT", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x10A*/ { "CMSG_AUTOEQUIP_ITEM", STATUS_LOGGEDIN, &WorldSession::HandleAutoEquipItemOpcode }, + /*0x10B*/ { "CMSG_AUTOSTORE_BAG_ITEM", STATUS_LOGGEDIN, &WorldSession::HandleAutoStoreBagItemOpcode }, + /*0x10C*/ { "CMSG_SWAP_ITEM", STATUS_LOGGEDIN, &WorldSession::HandleSwapItem }, + /*0x10D*/ { "CMSG_SWAP_INV_ITEM", STATUS_LOGGEDIN, &WorldSession::HandleSwapInvItemOpcode }, + /*0x10E*/ { "CMSG_SPLIT_ITEM", STATUS_LOGGEDIN, &WorldSession::HandleSplitItemOpcode }, + /*0x10F*/ { "CMSG_AUTOEQUIP_ITEM_SLOT", STATUS_LOGGEDIN, &WorldSession::HandleAutoEquipItemSlotOpcode }, + /*0x110*/ { "OBSOLETE_DROP_ITEM", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x111*/ { "CMSG_DESTROYITEM", STATUS_LOGGEDIN, &WorldSession::HandleDestroyItemOpcode }, + /*0x112*/ { "SMSG_INVENTORY_CHANGE_FAILURE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x113*/ { "SMSG_OPEN_CONTAINER", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x114*/ { "CMSG_INSPECT", STATUS_LOGGEDIN, &WorldSession::HandleInspectOpcode }, + /*0x115*/ { "SMSG_INSPECT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x116*/ { "CMSG_INITIATE_TRADE", STATUS_LOGGEDIN, &WorldSession::HandleInitiateTradeOpcode }, + /*0x117*/ { "CMSG_BEGIN_TRADE", STATUS_LOGGEDIN, &WorldSession::HandleBeginTradeOpcode }, + /*0x118*/ { "CMSG_BUSY_TRADE", STATUS_LOGGEDIN, &WorldSession::HandleBusyTradeOpcode }, + /*0x119*/ { "CMSG_IGNORE_TRADE", STATUS_LOGGEDIN, &WorldSession::HandleIgnoreTradeOpcode }, + /*0x11A*/ { "CMSG_ACCEPT_TRADE", STATUS_LOGGEDIN, &WorldSession::HandleAcceptTradeOpcode }, + /*0x11B*/ { "CMSG_UNACCEPT_TRADE", STATUS_LOGGEDIN, &WorldSession::HandleUnacceptTradeOpcode }, + /*0x11C*/ { "CMSG_CANCEL_TRADE", STATUS_AUTHED, &WorldSession::HandleCancelTradeOpcode }, + /*0x11D*/ { "CMSG_SET_TRADE_ITEM", STATUS_LOGGEDIN, &WorldSession::HandleSetTradeItemOpcode }, + /*0x11E*/ { "CMSG_CLEAR_TRADE_ITEM", STATUS_LOGGEDIN, &WorldSession::HandleClearTradeItemOpcode }, + /*0x11F*/ { "CMSG_SET_TRADE_GOLD", STATUS_LOGGEDIN, &WorldSession::HandleSetTradeGoldOpcode }, + /*0x120*/ { "SMSG_TRADE_STATUS", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x121*/ { "SMSG_TRADE_STATUS_EXTENDED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x122*/ { "SMSG_INITIALIZE_FACTIONS", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x123*/ { "SMSG_SET_FACTION_VISIBLE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x124*/ { "SMSG_SET_FACTION_STANDING", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x125*/ { "CMSG_SET_FACTION_ATWAR", STATUS_LOGGEDIN, &WorldSession::HandleSetFactionAtWar }, + /*0x126*/ { "CMSG_SET_FACTION_CHEAT", STATUS_LOGGEDIN, &WorldSession::HandleSetFactionCheat }, + /*0x127*/ { "SMSG_SET_PROFICIENCY", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x128*/ { "CMSG_SET_ACTION_BUTTON", STATUS_LOGGEDIN, &WorldSession::HandleSetActionButtonOpcode }, + /*0x129*/ { "SMSG_ACTION_BUTTONS", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x12A*/ { "SMSG_INITIAL_SPELLS", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x12B*/ { "SMSG_LEARNED_SPELL", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x12C*/ { "SMSG_SUPERCEDED_SPELL", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x12D*/ { "CMSG_NEW_SPELL_SLOT", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x12E*/ { "CMSG_CAST_SPELL", STATUS_LOGGEDIN, &WorldSession::HandleCastSpellOpcode }, + /*0x12F*/ { "CMSG_CANCEL_CAST", STATUS_LOGGEDIN, &WorldSession::HandleCancelCastOpcode }, + /*0x130*/ { "SMSG_CAST_FAILED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x131*/ { "SMSG_SPELL_START", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x132*/ { "SMSG_SPELL_GO", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x133*/ { "SMSG_SPELL_FAILURE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x134*/ { "SMSG_SPELL_COOLDOWN", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x135*/ { "SMSG_COOLDOWN_EVENT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x136*/ { "CMSG_CANCEL_AURA", STATUS_LOGGEDIN, &WorldSession::HandleCancelAuraOpcode }, + /*0x137*/ { "SMSG_UPDATE_AURA_DURATION_OBSOLETE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x138*/ { "SMSG_PET_CAST_FAILED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x139*/ { "MSG_CHANNEL_START", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x13A*/ { "MSG_CHANNEL_UPDATE", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x13B*/ { "CMSG_CANCEL_CHANNELLING", STATUS_LOGGEDIN, &WorldSession::HandleCancelChanneling }, + /*0x13C*/ { "SMSG_AI_REACTION", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x13D*/ { "CMSG_SET_SELECTION", STATUS_LOGGEDIN, &WorldSession::HandleSetSelectionOpcode }, + /*0x13E*/ { "CMSG_SET_TARGET_OBSOLETE", STATUS_LOGGEDIN, &WorldSession::HandleSetTargetOpcode }, + /*0x13F*/ { "CMSG_UNUSED", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x140*/ { "CMSG_UNUSED2", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x141*/ { "CMSG_ATTACKSWING", STATUS_LOGGEDIN, &WorldSession::HandleAttackSwingOpcode }, + /*0x142*/ { "CMSG_ATTACKSTOP", STATUS_LOGGEDIN, &WorldSession::HandleAttackStopOpcode }, + /*0x143*/ { "SMSG_ATTACKSTART", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x144*/ { "SMSG_ATTACKSTOP", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x145*/ { "SMSG_ATTACKSWING_NOTINRANGE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x146*/ { "SMSG_ATTACKSWING_BADFACING", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x147*/ { "SMSG_ATTACKSWING_NOTSTANDING", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x148*/ { "SMSG_ATTACKSWING_DEADTARGET", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x149*/ { "SMSG_ATTACKSWING_CANT_ATTACK", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x14A*/ { "SMSG_ATTACKERSTATEUPDATE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x14B*/ { "SMSG_VICTIMSTATEUPDATE_OBSOLETE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x14C*/ { "SMSG_DAMAGE_DONE_OBSOLETE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x14D*/ { "SMSG_DAMAGE_TAKEN_OBSOLETE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x14E*/ { "SMSG_CANCEL_COMBAT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x14F*/ { "SMSG_SPELLBREAKLOG", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x150*/ { "SMSG_SPELLHEALLOG", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x151*/ { "SMSG_SPELLENERGIZELOG", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x152*/ { "SMSG_BREAK_TARGET", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x153*/ { "CMSG_SAVE_PLAYER", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x154*/ { "CMSG_SETDEATHBINDPOINT", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x155*/ { "SMSG_BINDPOINTUPDATE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x156*/ { "CMSG_GETDEATHBINDZONE", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x157*/ { "SMSG_BINDZONEREPLY", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x158*/ { "SMSG_PLAYERBOUND", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x159*/ { "SMSG_CLIENT_CONTROL_UPDATE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x15A*/ { "CMSG_REPOP_REQUEST", STATUS_LOGGEDIN, &WorldSession::HandleRepopRequestOpcode }, + /*0x15B*/ { "SMSG_RESURRECT_REQUEST", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x15C*/ { "CMSG_RESURRECT_RESPONSE", STATUS_LOGGEDIN, &WorldSession::HandleResurrectResponseOpcode }, + /*0x15D*/ { "CMSG_LOOT", STATUS_LOGGEDIN, &WorldSession::HandleLootOpcode }, + /*0x15E*/ { "CMSG_LOOT_MONEY", STATUS_LOGGEDIN, &WorldSession::HandleLootMoneyOpcode }, + /*0x15F*/ { "CMSG_LOOT_RELEASE", STATUS_LOGGEDIN, &WorldSession::HandleLootReleaseOpcode }, + /*0x160*/ { "SMSG_LOOT_RESPONSE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x161*/ { "SMSG_LOOT_RELEASE_RESPONSE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x162*/ { "SMSG_LOOT_REMOVED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x163*/ { "SMSG_LOOT_MONEY_NOTIFY", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x164*/ { "SMSG_LOOT_ITEM_NOTIFY", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x165*/ { "SMSG_LOOT_CLEAR_MONEY", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x166*/ { "SMSG_ITEM_PUSH_RESULT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x167*/ { "SMSG_DUEL_REQUESTED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x168*/ { "SMSG_DUEL_OUTOFBOUNDS", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x169*/ { "SMSG_DUEL_INBOUNDS", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x16A*/ { "SMSG_DUEL_COMPLETE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x16B*/ { "SMSG_DUEL_WINNER", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x16C*/ { "CMSG_DUEL_ACCEPTED", STATUS_LOGGEDIN, &WorldSession::HandleDuelAcceptedOpcode }, + /*0x16D*/ { "CMSG_DUEL_CANCELLED", STATUS_LOGGEDIN, &WorldSession::HandleDuelCancelledOpcode }, + /*0x16E*/ { "SMSG_MOUNTRESULT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x16F*/ { "SMSG_DISMOUNTRESULT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x170*/ { "SMSG_PUREMOUNT_CANCELLED_OBSOLETE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x171*/ { "CMSG_MOUNTSPECIAL_ANIM", STATUS_LOGGEDIN, &WorldSession::HandleMountSpecialAnimOpcode }, + /*0x172*/ { "SMSG_MOUNTSPECIAL_ANIM", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x173*/ { "SMSG_PET_TAME_FAILURE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x174*/ { "CMSG_PET_SET_ACTION", STATUS_LOGGEDIN, &WorldSession::HandlePetSetAction }, + /*0x175*/ { "CMSG_PET_ACTION", STATUS_LOGGEDIN, &WorldSession::HandlePetAction }, + /*0x176*/ { "CMSG_PET_ABANDON", STATUS_LOGGEDIN, &WorldSession::HandlePetAbandon }, + /*0x177*/ { "CMSG_PET_RENAME", STATUS_LOGGEDIN, &WorldSession::HandlePetRename }, + /*0x178*/ { "SMSG_PET_NAME_INVALID", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x179*/ { "SMSG_PET_SPELLS", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x17A*/ { "SMSG_PET_MODE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x17B*/ { "CMSG_GOSSIP_HELLO", STATUS_LOGGEDIN, &WorldSession::HandleGossipHelloOpcode }, + /*0x17C*/ { "CMSG_GOSSIP_SELECT_OPTION", STATUS_LOGGEDIN, &WorldSession::HandleGossipSelectOptionOpcode }, + /*0x17D*/ { "SMSG_GOSSIP_MESSAGE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x17E*/ { "SMSG_GOSSIP_COMPLETE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x17F*/ { "CMSG_NPC_TEXT_QUERY", STATUS_LOGGEDIN, &WorldSession::HandleNpcTextQueryOpcode }, + /*0x180*/ { "SMSG_NPC_TEXT_UPDATE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x181*/ { "SMSG_NPC_WONT_TALK", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x182*/ { "CMSG_QUESTGIVER_STATUS_QUERY", STATUS_LOGGEDIN, &WorldSession::HandleQuestgiverStatusQueryOpcode}, + /*0x183*/ { "SMSG_QUESTGIVER_STATUS", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x184*/ { "CMSG_QUESTGIVER_HELLO", STATUS_LOGGEDIN, &WorldSession::HandleQuestgiverHelloOpcode }, + /*0x185*/ { "SMSG_QUESTGIVER_QUEST_LIST", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x186*/ { "CMSG_QUESTGIVER_QUERY_QUEST", STATUS_LOGGEDIN, &WorldSession::HandleQuestgiverQuestQueryOpcode}, + /*0x187*/ { "CMSG_QUESTGIVER_QUEST_AUTOLAUNCH", STATUS_LOGGEDIN, &WorldSession::HandleQuestAutoLaunch }, + /*0x188*/ { "SMSG_QUESTGIVER_QUEST_DETAILS", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x189*/ { "CMSG_QUESTGIVER_ACCEPT_QUEST", STATUS_LOGGEDIN, &WorldSession::HandleQuestgiverAcceptQuestOpcode}, + /*0x18A*/ { "CMSG_QUESTGIVER_COMPLETE_QUEST", STATUS_LOGGEDIN, &WorldSession::HandleQuestComplete }, + /*0x18B*/ { "SMSG_QUESTGIVER_REQUEST_ITEMS", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x18C*/ { "CMSG_QUESTGIVER_REQUEST_REWARD", STATUS_LOGGEDIN, &WorldSession::HandleQuestgiverRequestRewardOpcode}, + /*0x18D*/ { "SMSG_QUESTGIVER_OFFER_REWARD", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x18E*/ { "CMSG_QUESTGIVER_CHOOSE_REWARD", STATUS_LOGGEDIN, &WorldSession::HandleQuestgiverChooseRewardOpcode}, + /*0x18F*/ { "SMSG_QUESTGIVER_QUEST_INVALID", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x190*/ { "CMSG_QUESTGIVER_CANCEL", STATUS_LOGGEDIN, &WorldSession::HandleQuestgiverCancel }, + /*0x191*/ { "SMSG_QUESTGIVER_QUEST_COMPLETE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x192*/ { "SMSG_QUESTGIVER_QUEST_FAILED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x193*/ { "CMSG_QUESTLOG_SWAP_QUEST", STATUS_LOGGEDIN, &WorldSession::HandleQuestLogSwapQuest }, + /*0x194*/ { "CMSG_QUESTLOG_REMOVE_QUEST", STATUS_LOGGEDIN, &WorldSession::HandleQuestLogRemoveQuest }, + /*0x195*/ { "SMSG_QUESTLOG_FULL", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x196*/ { "SMSG_QUESTUPDATE_FAILED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x197*/ { "SMSG_QUESTUPDATE_FAILEDTIMER", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x198*/ { "SMSG_QUESTUPDATE_COMPLETE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x199*/ { "SMSG_QUESTUPDATE_ADD_KILL", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x19A*/ { "SMSG_QUESTUPDATE_ADD_ITEM", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x19B*/ { "CMSG_QUEST_CONFIRM_ACCEPT", STATUS_LOGGEDIN, &WorldSession::HandleQuestConfirmAccept }, + /*0x19C*/ { "SMSG_QUEST_CONFIRM_ACCEPT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x19D*/ { "CMSG_PUSHQUESTTOPARTY", STATUS_LOGGEDIN, &WorldSession::HandleQuestPushToParty }, + /*0x19E*/ { "CMSG_LIST_INVENTORY", STATUS_LOGGEDIN, &WorldSession::HandleListInventoryOpcode }, + /*0x19F*/ { "SMSG_LIST_INVENTORY", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x1A0*/ { "CMSG_SELL_ITEM", STATUS_LOGGEDIN, &WorldSession::HandleSellItemOpcode }, + /*0x1A1*/ { "SMSG_SELL_ITEM", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x1A2*/ { "CMSG_BUY_ITEM", STATUS_LOGGEDIN, &WorldSession::HandleBuyItemOpcode }, + /*0x1A3*/ { "CMSG_BUY_ITEM_IN_SLOT", STATUS_LOGGEDIN, &WorldSession::HandleBuyItemInSlotOpcode }, + /*0x1A4*/ { "SMSG_BUY_ITEM", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x1A5*/ { "SMSG_BUY_FAILED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x1A6*/ { "CMSG_TAXICLEARALLNODES", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x1A7*/ { "CMSG_TAXIENABLEALLNODES", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x1A8*/ { "CMSG_TAXISHOWNODES", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x1A9*/ { "SMSG_SHOWTAXINODES", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x1AA*/ { "CMSG_TAXINODE_STATUS_QUERY", STATUS_LOGGEDIN, &WorldSession::HandleTaxiNodeStatusQueryOpcode }, + /*0x1AB*/ { "SMSG_TAXINODE_STATUS", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x1AC*/ { "CMSG_TAXIQUERYAVAILABLENODES", STATUS_LOGGEDIN, &WorldSession::HandleTaxiQueryAvailableNodes }, + /*0x1AD*/ { "CMSG_ACTIVATETAXI", STATUS_LOGGEDIN, &WorldSession::HandleActivateTaxiOpcode }, + /*0x1AE*/ { "SMSG_ACTIVATETAXIREPLY", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x1AF*/ { "SMSG_NEW_TAXI_PATH", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x1B0*/ { "CMSG_TRAINER_LIST", STATUS_LOGGEDIN, &WorldSession::HandleTrainerListOpcode }, + /*0x1B1*/ { "SMSG_TRAINER_LIST", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x1B2*/ { "CMSG_TRAINER_BUY_SPELL", STATUS_LOGGEDIN, &WorldSession::HandleTrainerBuySpellOpcode }, + /*0x1B3*/ { "SMSG_TRAINER_BUY_SUCCEEDED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x1B4*/ { "SMSG_TRAINER_BUY_FAILED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x1B5*/ { "CMSG_BINDER_ACTIVATE", STATUS_LOGGEDIN, &WorldSession::HandleBinderActivateOpcode }, + /*0x1B6*/ { "SMSG_PLAYERBINDERROR", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x1B7*/ { "CMSG_BANKER_ACTIVATE", STATUS_LOGGEDIN, &WorldSession::HandleBankerActivateOpcode }, + /*0x1B8*/ { "SMSG_SHOW_BANK", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x1B9*/ { "CMSG_BUY_BANK_SLOT", STATUS_LOGGEDIN, &WorldSession::HandleBuyBankSlotOpcode }, + /*0x1BA*/ { "SMSG_BUY_BANK_SLOT_RESULT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x1BB*/ { "CMSG_PETITION_SHOWLIST", STATUS_LOGGEDIN, &WorldSession::HandlePetitionShowListOpcode }, + /*0x1BC*/ { "SMSG_PETITION_SHOWLIST", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x1BD*/ { "CMSG_PETITION_BUY", STATUS_LOGGEDIN, &WorldSession::HandlePetitionBuyOpcode }, + /*0x1BE*/ { "CMSG_PETITION_SHOW_SIGNATURES", STATUS_LOGGEDIN, &WorldSession::HandlePetitionShowSignOpcode }, + /*0x1BF*/ { "SMSG_PETITION_SHOW_SIGNATURES", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x1C0*/ { "CMSG_PETITION_SIGN", STATUS_LOGGEDIN, &WorldSession::HandlePetitionSignOpcode }, + /*0x1C1*/ { "SMSG_PETITION_SIGN_RESULTS", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x1C2*/ { "MSG_PETITION_DECLINE", STATUS_LOGGEDIN, &WorldSession::HandlePetitionDeclineOpcode }, + /*0x1C3*/ { "CMSG_OFFER_PETITION", STATUS_LOGGEDIN, &WorldSession::HandleOfferPetitionOpcode }, + /*0x1C4*/ { "CMSG_TURN_IN_PETITION", STATUS_LOGGEDIN, &WorldSession::HandleTurnInPetitionOpcode }, + /*0x1C5*/ { "SMSG_TURN_IN_PETITION_RESULTS", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x1C6*/ { "CMSG_PETITION_QUERY", STATUS_LOGGEDIN, &WorldSession::HandlePetitionQueryOpcode }, + /*0x1C7*/ { "SMSG_PETITION_QUERY_RESPONSE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x1C8*/ { "SMSG_FISH_NOT_HOOKED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x1C9*/ { "SMSG_FISH_ESCAPED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x1CA*/ { "CMSG_BUG", STATUS_LOGGEDIN, &WorldSession::HandleBugOpcode }, + /*0x1CB*/ { "SMSG_NOTIFICATION", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x1CC*/ { "CMSG_PLAYED_TIME", STATUS_LOGGEDIN, &WorldSession::HandlePlayedTime }, + /*0x1CD*/ { "SMSG_PLAYED_TIME", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x1CE*/ { "CMSG_QUERY_TIME", STATUS_LOGGEDIN, &WorldSession::HandleQueryTimeOpcode }, + /*0x1CF*/ { "SMSG_QUERY_TIME_RESPONSE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x1D0*/ { "SMSG_LOG_XPGAIN", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x1D1*/ { "SMSG_AURACASTLOG", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x1D2*/ { "CMSG_RECLAIM_CORPSE", STATUS_LOGGEDIN, &WorldSession::HandleCorpseReclaimOpcode }, + /*0x1D3*/ { "CMSG_WRAP_ITEM", STATUS_LOGGEDIN, &WorldSession::HandleWrapItemOpcode }, + /*0x1D4*/ { "SMSG_LEVELUP_INFO", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x1D5*/ { "MSG_MINIMAP_PING", STATUS_LOGGEDIN, &WorldSession::HandleMinimapPingOpcode }, + /*0x1D6*/ { "SMSG_RESISTLOG", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x1D7*/ { "SMSG_ENCHANTMENTLOG", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x1D8*/ { "CMSG_SET_SKILL_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x1D9*/ { "SMSG_START_MIRROR_TIMER", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x1DA*/ { "SMSG_PAUSE_MIRROR_TIMER", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x1DB*/ { "SMSG_STOP_MIRROR_TIMER", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x1DC*/ { "CMSG_PING", STATUS_NEVER, &WorldSession::Handle_EarlyProccess }, + /*0x1DD*/ { "SMSG_PONG", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x1DE*/ { "SMSG_CLEAR_COOLDOWN", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x1DF*/ { "SMSG_GAMEOBJECT_PAGETEXT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x1E0*/ { "CMSG_SETSHEATHED", STATUS_LOGGEDIN, &WorldSession::HandleSetSheathedOpcode }, + /*0x1E1*/ { "SMSG_COOLDOWN_CHEAT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x1E2*/ { "SMSG_SPELL_DELAYED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x1E3*/ { "CMSG_PLAYER_MACRO_OBSOLETE", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x1E4*/ { "SMSG_PLAYER_MACRO_OBSOLETE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x1E5*/ { "CMSG_GHOST", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x1E6*/ { "CMSG_GM_INVIS", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x1E7*/ { "SMSG_INVALID_PROMOTION_CODE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x1E8*/ { "MSG_GM_BIND_OTHER", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x1E9*/ { "MSG_GM_SUMMON", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x1EA*/ { "SMSG_ITEM_TIME_UPDATE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x1EB*/ { "SMSG_ITEM_ENCHANT_TIME_UPDATE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x1EC*/ { "SMSG_AUTH_CHALLENGE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x1ED*/ { "CMSG_AUTH_SESSION", STATUS_NEVER, &WorldSession::Handle_EarlyProccess }, + /*0x1EE*/ { "SMSG_AUTH_RESPONSE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x1EF*/ { "MSG_GM_SHOWLABEL", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x1F0*/ { "CMSG_PET_CAST_SPELL", STATUS_LOGGEDIN, &WorldSession::HandlePetCastSpellOpcode }, + /*0x1F1*/ { "MSG_SAVE_GUILD_EMBLEM", STATUS_LOGGEDIN, &WorldSession::HandleGuildSaveEmblemOpcode }, + /*0x1F2*/ { "MSG_TABARDVENDOR_ACTIVATE", STATUS_LOGGEDIN, &WorldSession::HandleTabardVendorActivateOpcode}, + /*0x1F3*/ { "SMSG_PLAY_SPELL_VISUAL", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x1F4*/ { "CMSG_ZONEUPDATE", STATUS_LOGGEDIN, &WorldSession::HandleZoneUpdateOpcode }, + /*0x1F5*/ { "SMSG_PARTYKILLLOG", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x1F6*/ { "SMSG_COMPRESSED_UPDATE_OBJECT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x1F7*/ { "SMSG_PLAY_SPELL_IMPACT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x1F8*/ { "SMSG_EXPLORATION_EXPERIENCE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x1F9*/ { "CMSG_GM_SET_SECURITY_GROUP", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x1FA*/ { "CMSG_GM_NUKE", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x1FB*/ { "MSG_RANDOM_ROLL", STATUS_LOGGEDIN, &WorldSession::HandleRandomRollOpcode }, + /*0x1FC*/ { "SMSG_ENVIRONMENTALDAMAGELOG", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x1FD*/ { "CMSG_RWHOIS_OBSOLETE", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x1FE*/ { "SMSG_RWHOIS", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x1FF*/ { "MSG_LOOKING_FOR_GROUP", STATUS_LOGGEDIN, &WorldSession::HandleLookingForGroup }, + /*0x200*/ { "CMSG_SET_LOOKING_FOR_GROUP", STATUS_LOGGEDIN, &WorldSession::HandleSetLfgOpcode }, + /*0x201*/ { "CMSG_UNLEARN_SPELL", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x202*/ { "CMSG_UNLEARN_SKILL", STATUS_LOGGEDIN, &WorldSession::HandleUnlearnSkillOpcode }, + /*0x203*/ { "SMSG_REMOVED_SPELL", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x204*/ { "CMSG_DECHARGE", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x205*/ { "CMSG_GMTICKET_CREATE", STATUS_LOGGEDIN, &WorldSession::HandleGMTicketCreateOpcode }, + /*0x206*/ { "SMSG_GMTICKET_CREATE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x207*/ { "CMSG_GMTICKET_UPDATETEXT", STATUS_LOGGEDIN, &WorldSession::HandleGMTicketUpdateTextOpcode }, + /*0x208*/ { "SMSG_GMTICKET_UPDATETEXT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x209*/ { "SMSG_ACCOUNT_DATA_TIMES", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x20A*/ { "CMSG_REQUEST_ACCOUNT_DATA", STATUS_LOGGEDIN, &WorldSession::HandleRequestAccountData }, + /*0x20B*/ { "CMSG_UPDATE_ACCOUNT_DATA", STATUS_AUTHED, &WorldSession::HandleUpdateAccountData }, + /*0x20C*/ { "SMSG_UPDATE_ACCOUNT_DATA", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x20D*/ { "SMSG_CLEAR_FAR_SIGHT_IMMEDIATE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x20E*/ { "SMSG_POWERGAINLOG_OBSOLETE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x20F*/ { "CMSG_GM_TEACH", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x210*/ { "CMSG_GM_CREATE_ITEM_TARGET", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x211*/ { "CMSG_GMTICKET_GETTICKET", STATUS_LOGGEDIN, &WorldSession::HandleGMTicketGetTicketOpcode }, + /*0x212*/ { "SMSG_GMTICKET_GETTICKET", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x213*/ { "CMSG_UNLEARN_TALENTS", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x214*/ { "SMSG_GAMEOBJECT_SPAWN_ANIM_OBSOLETE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x215*/ { "SMSG_GAMEOBJECT_DESPAWN_ANIM", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x216*/ { "MSG_CORPSE_QUERY", STATUS_LOGGEDIN, &WorldSession::HandleCorpseQueryOpcode }, + /*0x217*/ { "CMSG_GMTICKET_DELETETICKET", STATUS_LOGGEDIN, &WorldSession::HandleGMTicketDeleteOpcode }, + /*0x218*/ { "SMSG_GMTICKET_DELETETICKET", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x219*/ { "SMSG_CHAT_WRONG_FACTION", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x21A*/ { "CMSG_GMTICKET_SYSTEMSTATUS", STATUS_LOGGEDIN, &WorldSession::HandleGMTicketSystemStatusOpcode}, + /*0x21B*/ { "SMSG_GMTICKET_SYSTEMSTATUS", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x21C*/ { "CMSG_SPIRIT_HEALER_ACTIVATE", STATUS_LOGGEDIN, &WorldSession::HandleSpiritHealerActivateOpcode}, + /*0x21D*/ { "CMSG_SET_STAT_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x21E*/ { "SMSG_SET_REST_START_OBSOLETE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x21F*/ { "CMSG_SKILL_BUY_STEP", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x220*/ { "CMSG_SKILL_BUY_RANK", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x221*/ { "CMSG_XP_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x222*/ { "SMSG_SPIRIT_HEALER_CONFIRM", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x223*/ { "CMSG_CHARACTER_POINT_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x224*/ { "SMSG_GOSSIP_POI", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x225*/ { "CMSG_CHAT_IGNORED", STATUS_LOGGEDIN, &WorldSession::HandleChatIgnoredOpcode }, + /*0x226*/ { "CMSG_GM_VISION", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x227*/ { "CMSG_SERVER_COMMAND", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x228*/ { "CMSG_GM_SILENCE", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x229*/ { "CMSG_GM_REVEALTO", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x22A*/ { "CMSG_GM_RESURRECT", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x22B*/ { "CMSG_GM_SUMMONMOB", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x22C*/ { "CMSG_GM_MOVECORPSE", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x22D*/ { "CMSG_GM_FREEZE", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x22E*/ { "CMSG_GM_UBERINVIS", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x22F*/ { "CMSG_GM_REQUEST_PLAYER_INFO", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x230*/ { "SMSG_GM_PLAYER_INFO", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x231*/ { "CMSG_GUILD_RANK", STATUS_LOGGEDIN, &WorldSession::HandleGuildRankOpcode }, + /*0x232*/ { "CMSG_GUILD_ADD_RANK", STATUS_LOGGEDIN, &WorldSession::HandleGuildAddRankOpcode }, + /*0x233*/ { "CMSG_GUILD_DEL_RANK", STATUS_LOGGEDIN, &WorldSession::HandleGuildDelRankOpcode }, + /*0x234*/ { "CMSG_GUILD_SET_PUBLIC_NOTE", STATUS_LOGGEDIN, &WorldSession::HandleGuildSetPublicNoteOpcode }, + /*0x235*/ { "CMSG_GUILD_SET_OFFICER_NOTE", STATUS_LOGGEDIN, &WorldSession::HandleGuildSetOfficerNoteOpcode }, + /*0x236*/ { "SMSG_LOGIN_VERIFY_WORLD", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x237*/ { "CMSG_CLEAR_EXPLORATION", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x238*/ { "CMSG_SEND_MAIL", STATUS_LOGGEDIN, &WorldSession::HandleSendMail }, + /*0x239*/ { "SMSG_SEND_MAIL_RESULT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x23A*/ { "CMSG_GET_MAIL_LIST", STATUS_LOGGEDIN, &WorldSession::HandleGetMail }, + /*0x23B*/ { "SMSG_MAIL_LIST_RESULT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x23C*/ { "CMSG_BATTLEFIELD_LIST", STATUS_LOGGEDIN, &WorldSession::HandleBattleGroundListOpcode }, + /*0x23D*/ { "SMSG_BATTLEFIELD_LIST", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x23E*/ { "CMSG_BATTLEFIELD_JOIN", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x23F*/ { "SMSG_BATTLEFIELD_WIN_OBSOLETE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x240*/ { "SMSG_BATTLEFIELD_LOSE_OBSOLETE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x241*/ { "CMSG_TAXICLEARNODE", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x242*/ { "CMSG_TAXIENABLENODE", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x243*/ { "CMSG_ITEM_TEXT_QUERY", STATUS_LOGGEDIN, &WorldSession::HandleItemTextQuery }, + /*0x244*/ { "SMSG_ITEM_TEXT_QUERY_RESPONSE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x245*/ { "CMSG_MAIL_TAKE_MONEY", STATUS_LOGGEDIN, &WorldSession::HandleTakeMoney }, + /*0x246*/ { "CMSG_MAIL_TAKE_ITEM", STATUS_LOGGEDIN, &WorldSession::HandleTakeItem }, + /*0x247*/ { "CMSG_MAIL_MARK_AS_READ", STATUS_LOGGEDIN, &WorldSession::HandleMarkAsRead }, + /*0x248*/ { "CMSG_MAIL_RETURN_TO_SENDER", STATUS_LOGGEDIN, &WorldSession::HandleReturnToSender }, + /*0x249*/ { "CMSG_MAIL_DELETE", STATUS_LOGGEDIN, &WorldSession::HandleMailDelete }, + /*0x24A*/ { "CMSG_MAIL_CREATE_TEXT_ITEM", STATUS_LOGGEDIN, &WorldSession::HandleMailCreateTextItem }, + /*0x24B*/ { "SMSG_SPELLLOGMISS", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x24C*/ { "SMSG_SPELLLOGEXECUTE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x24D*/ { "SMSG_DEBUGAURAPROC", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x24E*/ { "SMSG_PERIODICAURALOG", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x24F*/ { "SMSG_SPELLDAMAGESHIELD", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x250*/ { "SMSG_SPELLNONMELEEDAMAGELOG", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x251*/ { "CMSG_LEARN_TALENT", STATUS_LOGGEDIN, &WorldSession::HandleLearnTalentOpcode }, + /*0x252*/ { "SMSG_RESURRECT_FAILED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x253*/ { "CMSG_TOGGLE_PVP", STATUS_LOGGEDIN, &WorldSession::HandleTogglePvP }, + /*0x254*/ { "SMSG_ZONE_UNDER_ATTACK", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x255*/ { "MSG_AUCTION_HELLO", STATUS_LOGGEDIN, &WorldSession::HandleAuctionHelloOpcode }, + /*0x256*/ { "CMSG_AUCTION_SELL_ITEM", STATUS_LOGGEDIN, &WorldSession::HandleAuctionSellItem }, + /*0x257*/ { "CMSG_AUCTION_REMOVE_ITEM", STATUS_LOGGEDIN, &WorldSession::HandleAuctionRemoveItem }, + /*0x258*/ { "CMSG_AUCTION_LIST_ITEMS", STATUS_LOGGEDIN, &WorldSession::HandleAuctionListItems }, + /*0x259*/ { "CMSG_AUCTION_LIST_OWNER_ITEMS", STATUS_LOGGEDIN, &WorldSession::HandleAuctionListOwnerItems }, + /*0x25A*/ { "CMSG_AUCTION_PLACE_BID", STATUS_LOGGEDIN, &WorldSession::HandleAuctionPlaceBid }, + /*0x25B*/ { "SMSG_AUCTION_COMMAND_RESULT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x25C*/ { "SMSG_AUCTION_LIST_RESULT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x25D*/ { "SMSG_AUCTION_OWNER_LIST_RESULT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x25E*/ { "SMSG_AUCTION_BIDDER_NOTIFICATION", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x25F*/ { "SMSG_AUCTION_OWNER_NOTIFICATION", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x260*/ { "SMSG_PROCRESIST", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x261*/ { "SMSG_STANDSTATE_CHANGE_FAILURE_OBSOLETE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x262*/ { "SMSG_DISPEL_FAILED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x263*/ { "SMSG_SPELLORDAMAGE_IMMUNE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x264*/ { "CMSG_AUCTION_LIST_BIDDER_ITEMS", STATUS_LOGGEDIN, &WorldSession::HandleAuctionListBidderItems }, + /*0x265*/ { "SMSG_AUCTION_BIDDER_LIST_RESULT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x266*/ { "SMSG_SET_FLAT_SPELL_MODIFIER", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x267*/ { "SMSG_SET_PCT_SPELL_MODIFIER", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x268*/ { "CMSG_SET_AMMO", STATUS_LOGGEDIN, &WorldSession::HandleSetAmmoOpcode }, + /*0x269*/ { "SMSG_CORPSE_RECLAIM_DELAY", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x26A*/ { "CMSG_SET_ACTIVE_MOVER", STATUS_LOGGEDIN, &WorldSession::HandleSetActiveMoverOpcode }, + /*0x26B*/ { "CMSG_PET_CANCEL_AURA", STATUS_LOGGEDIN, &WorldSession::HandlePetCancelAuraOpcode }, + /*0x26C*/ { "CMSG_PLAYER_AI_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x26D*/ { "CMSG_CANCEL_AUTO_REPEAT_SPELL", STATUS_LOGGEDIN, &WorldSession::HandleCancelAutoRepeatSpellOpcode}, + /*0x26E*/ { "MSG_GM_ACCOUNT_ONLINE", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x26F*/ { "MSG_LIST_STABLED_PETS", STATUS_LOGGEDIN, &WorldSession::HandleListStabledPetsOpcode }, + /*0x270*/ { "CMSG_STABLE_PET", STATUS_LOGGEDIN, &WorldSession::HandleStablePet }, + /*0x271*/ { "CMSG_UNSTABLE_PET", STATUS_LOGGEDIN, &WorldSession::HandleUnstablePet }, + /*0x272*/ { "CMSG_BUY_STABLE_SLOT", STATUS_LOGGEDIN, &WorldSession::HandleBuyStableSlot }, + /*0x273*/ { "SMSG_STABLE_RESULT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x274*/ { "CMSG_STABLE_REVIVE_PET", STATUS_LOGGEDIN, &WorldSession::HandleStableRevivePet }, + /*0x275*/ { "CMSG_STABLE_SWAP_PET", STATUS_LOGGEDIN, &WorldSession::HandleStableSwapPet }, + /*0x276*/ { "MSG_QUEST_PUSH_RESULT", STATUS_LOGGEDIN, &WorldSession::HandleQuestPushResult }, + /*0x277*/ { "SMSG_PLAY_MUSIC", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x278*/ { "SMSG_PLAY_OBJECT_SOUND", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x279*/ { "CMSG_REQUEST_PET_INFO", STATUS_LOGGEDIN, &WorldSession::HandleRequestPetInfoOpcode }, + /*0x27A*/ { "CMSG_FAR_SIGHT", STATUS_LOGGEDIN, &WorldSession::HandleFarSightOpcode }, + /*0x27B*/ { "SMSG_SPELLDISPELLOG", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x27C*/ { "SMSG_DAMAGE_CALC_LOG", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x27D*/ { "CMSG_ENABLE_DAMAGE_LOG", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x27E*/ { "CMSG_GROUP_CHANGE_SUB_GROUP", STATUS_LOGGEDIN, &WorldSession::HandleGroupChangeSubGroupOpcode }, + /*0x27F*/ { "CMSG_REQUEST_PARTY_MEMBER_STATS", STATUS_LOGGEDIN, &WorldSession::HandleRequestPartyMemberStatsOpcode}, + /*0x280*/ { "CMSG_GROUP_SWAP_SUB_GROUP", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x281*/ { "CMSG_RESET_FACTION_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x282*/ { "CMSG_AUTOSTORE_BANK_ITEM", STATUS_LOGGEDIN, &WorldSession::HandleAutoStoreBankItemOpcode }, + /*0x283*/ { "CMSG_AUTOBANK_ITEM", STATUS_LOGGEDIN, &WorldSession::HandleAutoBankItemOpcode }, + /*0x284*/ { "MSG_QUERY_NEXT_MAIL_TIME", STATUS_LOGGEDIN, &WorldSession::HandleMsgQueryNextMailtime }, + /*0x285*/ { "SMSG_RECEIVED_MAIL", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x286*/ { "SMSG_RAID_GROUP_ONLY", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x287*/ { "CMSG_SET_DURABILITY_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x288*/ { "CMSG_SET_PVP_RANK_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x289*/ { "CMSG_ADD_PVP_MEDAL_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x28A*/ { "CMSG_DEL_PVP_MEDAL_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x28B*/ { "CMSG_SET_PVP_TITLE", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x28C*/ { "SMSG_PVP_CREDIT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x28D*/ { "SMSG_AUCTION_REMOVED_NOTIFICATION", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x28E*/ { "CMSG_GROUP_RAID_CONVERT", STATUS_LOGGEDIN, &WorldSession::HandleRaidConvertOpcode }, + /*0x28F*/ { "CMSG_GROUP_ASSISTANT_LEADER", STATUS_LOGGEDIN, &WorldSession::HandleGroupAssistantOpcode }, + /*0x290*/ { "CMSG_BUYBACK_ITEM", STATUS_LOGGEDIN, &WorldSession::HandleBuybackItem }, + /*0x291*/ { "SMSG_SERVER_MESSAGE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x292*/ { "CMSG_MEETINGSTONE_JOIN", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x293*/ { "CMSG_MEETINGSTONE_LEAVE", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x294*/ { "CMSG_MEETINGSTONE_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x295*/ { "SMSG_MEETINGSTONE_SETQUEUE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x296*/ { "CMSG_MEETINGSTONE_INFO", STATUS_LOGGEDIN, &WorldSession::HandleMeetingStoneInfo }, + /*0x297*/ { "SMSG_MEETINGSTONE_COMPLETE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x298*/ { "SMSG_MEETINGSTONE_IN_PROGRESS", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x299*/ { "SMSG_MEETINGSTONE_MEMBER_ADDED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x29A*/ { "CMSG_GMTICKETSYSTEM_TOGGLE", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x29B*/ { "CMSG_CANCEL_GROWTH_AURA", STATUS_LOGGEDIN, &WorldSession::HandleCancelGrowthAuraOpcode }, + /*0x29C*/ { "SMSG_CANCEL_AUTO_REPEAT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x29D*/ { "SMSG_STANDSTATE_UPDATE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x29E*/ { "SMSG_LOOT_ALL_PASSED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x29F*/ { "SMSG_LOOT_ROLL_WON", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x2A0*/ { "CMSG_LOOT_ROLL", STATUS_LOGGEDIN, &WorldSession::HandleLootRoll }, + /*0x2A1*/ { "SMSG_LOOT_START_ROLL", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x2A2*/ { "SMSG_LOOT_ROLL", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x2A3*/ { "CMSG_LOOT_MASTER_GIVE", STATUS_LOGGEDIN, &WorldSession::HandleLootMasterGiveOpcode }, + /*0x2A4*/ { "SMSG_LOOT_MASTER_LIST", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x2A5*/ { "SMSG_SET_FORCED_REACTIONS", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x2A6*/ { "SMSG_SPELL_FAILED_OTHER", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x2A7*/ { "SMSG_GAMEOBJECT_RESET_STATE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x2A8*/ { "CMSG_REPAIR_ITEM", STATUS_LOGGEDIN, &WorldSession::HandleRepairItemOpcode }, + /*0x2A9*/ { "SMSG_CHAT_PLAYER_NOT_FOUND", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x2AA*/ { "MSG_TALENT_WIPE_CONFIRM", STATUS_LOGGEDIN, &WorldSession::HandleTalentWipeOpcode }, + /*0x2AB*/ { "SMSG_SUMMON_REQUEST", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x2AC*/ { "CMSG_SUMMON_RESPONSE", STATUS_LOGGEDIN, &WorldSession::HandleSummonResponseOpcode }, + /*0x2AD*/ { "MSG_MOVE_TOGGLE_GRAVITY_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x2AE*/ { "SMSG_MONSTER_MOVE_TRANSPORT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x2AF*/ { "SMSG_PET_BROKEN", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x2B0*/ { "MSG_MOVE_FEATHER_FALL", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x2B1*/ { "MSG_MOVE_WATER_WALK", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x2B2*/ { "CMSG_SERVER_BROADCAST", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x2B3*/ { "CMSG_SELF_RES", STATUS_LOGGEDIN, &WorldSession::HandleSelfResOpcode }, + /*0x2B4*/ { "SMSG_FEIGN_DEATH_RESISTED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x2B5*/ { "CMSG_RUN_SCRIPT", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x2B6*/ { "SMSG_SCRIPT_MESSAGE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x2B7*/ { "SMSG_DUEL_COUNTDOWN", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x2B8*/ { "SMSG_AREA_TRIGGER_MESSAGE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x2B9*/ { "CMSG_SHOWING_HELM", STATUS_LOGGEDIN, &WorldSession::HandleToggleHelmOpcode }, + /*0x2BA*/ { "CMSG_SHOWING_CLOAK", STATUS_LOGGEDIN, &WorldSession::HandleToggleCloakOpcode }, + /*0x2BB*/ { "SMSG_MEETINGSTONE_JOINFAILED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x2BC*/ { "SMSG_PLAYER_SKINNED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x2BD*/ { "SMSG_DURABILITY_DAMAGE_DEATH", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x2BE*/ { "CMSG_SET_EXPLORATION", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x2BF*/ { "CMSG_SET_ACTIONBAR_TOGGLES", STATUS_AUTHED, &WorldSession::HandleSetActionBar }, + /*0x2C0*/ { "UMSG_DELETE_GUILD_CHARTER", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x2C1*/ { "MSG_PETITION_RENAME", STATUS_LOGGEDIN, &WorldSession::HandlePetitionRenameOpcode }, + /*0x2C2*/ { "SMSG_INIT_WORLD_STATES", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x2C3*/ { "SMSG_UPDATE_WORLD_STATE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x2C4*/ { "CMSG_ITEM_NAME_QUERY", STATUS_LOGGEDIN, &WorldSession::HandleItemNameQueryOpcode }, + /*0x2C5*/ { "SMSG_ITEM_NAME_QUERY_RESPONSE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x2C6*/ { "SMSG_PET_ACTION_FEEDBACK", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x2C7*/ { "CMSG_CHAR_RENAME", STATUS_AUTHED, &WorldSession::HandleChangePlayerNameOpcode }, + /*0x2C8*/ { "SMSG_CHAR_RENAME", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x2C9*/ { "CMSG_MOVE_SPLINE_DONE", STATUS_LOGGEDIN, &WorldSession::HandleTaxiNextDestinationOpcode }, + /*0x2CA*/ { "CMSG_MOVE_FALL_RESET", STATUS_LOGGEDIN, &WorldSession::HandleMovementOpcodes }, + /*0x2CB*/ { "SMSG_INSTANCE_SAVE_CREATED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x2CC*/ { "SMSG_RAID_INSTANCE_INFO", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x2CD*/ { "CMSG_REQUEST_RAID_INFO", STATUS_LOGGEDIN, &WorldSession::HandleRequestRaidInfoOpcode }, + /*0x2CE*/ { "CMSG_MOVE_TIME_SKIPPED", STATUS_LOGGEDIN, &WorldSession::HandleMoveTimeSkippedOpcode }, + /*0x2CF*/ { "CMSG_MOVE_FEATHER_FALL_ACK", STATUS_LOGGEDIN, &WorldSession::HandleFeatherFallAck }, + /*0x2D0*/ { "CMSG_MOVE_WATER_WALK_ACK", STATUS_LOGGEDIN, &WorldSession::HandleMoveWaterWalkAck }, + /*0x2D1*/ { "CMSG_MOVE_NOT_ACTIVE_MOVER", STATUS_LOGGEDIN, &WorldSession::HandleMoveNotActiveMover }, + /*0x2D2*/ { "SMSG_PLAY_SOUND", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x2D3*/ { "CMSG_BATTLEFIELD_STATUS", STATUS_LOGGEDIN, &WorldSession::HandleBattlefieldStatusOpcode }, + /*0x2D4*/ { "SMSG_BATTLEFIELD_STATUS", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x2D5*/ { "CMSG_BATTLEFIELD_PORT", STATUS_LOGGEDIN, &WorldSession::HandleBattleGroundPlayerPortOpcode}, + /*0x2D6*/ { "MSG_INSPECT_HONOR_STATS", STATUS_LOGGEDIN, &WorldSession::HandleInspectHonorStatsOpcode }, + /*0x2D7*/ { "CMSG_BATTLEMASTER_HELLO", STATUS_LOGGEDIN, &WorldSession::HandleBattleGroundHelloOpcode }, + /*0x2D8*/ { "CMSG_MOVE_START_SWIM_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x2D9*/ { "CMSG_MOVE_STOP_SWIM_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x2DA*/ { "SMSG_FORCE_WALK_SPEED_CHANGE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x2DB*/ { "CMSG_FORCE_WALK_SPEED_CHANGE_ACK", STATUS_LOGGEDIN, &WorldSession::HandleForceSpeedChangeAck }, + /*0x2DC*/ { "SMSG_FORCE_SWIM_BACK_SPEED_CHANGE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x2DD*/ { "CMSG_FORCE_SWIM_BACK_SPEED_CHANGE_ACK", STATUS_LOGGEDIN, &WorldSession::HandleForceSpeedChangeAck }, + /*0x2DE*/ { "SMSG_FORCE_TURN_RATE_CHANGE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x2DF*/ { "CMSG_FORCE_TURN_RATE_CHANGE_ACK", STATUS_LOGGEDIN, &WorldSession::HandleForceSpeedChangeAck }, + /*0x2E0*/ { "MSG_PVP_LOG_DATA", STATUS_LOGGEDIN, &WorldSession::HandleBattleGroundPVPlogdataOpcode}, + /*0x2E1*/ { "CMSG_LEAVE_BATTLEFIELD", STATUS_LOGGEDIN, &WorldSession::HandleBattleGroundLeaveOpcode }, + /*0x2E2*/ { "CMSG_AREA_SPIRIT_HEALER_QUERY", STATUS_LOGGEDIN, &WorldSession::HandleAreaSpiritHealerQueryOpcode}, + /*0x2E3*/ { "CMSG_AREA_SPIRIT_HEALER_QUEUE", STATUS_LOGGEDIN, &WorldSession::HandleAreaSpiritHealerQueueOpcode}, + /*0x2E4*/ { "SMSG_AREA_SPIRIT_HEALER_TIME", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x2E5*/ { "CMSG_GM_UNTEACH", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x2E6*/ { "SMSG_WARDEN_DATA", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x2E7*/ { "CMSG_WARDEN_DATA", STATUS_LOGGEDIN, &WorldSession::HandleWardenDataOpcode }, + /*0x2E8*/ { "SMSG_GROUP_JOINED_BATTLEGROUND", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x2E9*/ { "MSG_BATTLEGROUND_PLAYER_POSITIONS", STATUS_LOGGEDIN, &WorldSession::HandleBattleGroundPlayerPositionsOpcode}, + /*0x2EA*/ { "CMSG_PET_STOP_ATTACK", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x2EB*/ { "SMSG_BINDER_CONFIRM", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x2EC*/ { "SMSG_BATTLEGROUND_PLAYER_JOINED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x2ED*/ { "SMSG_BATTLEGROUND_PLAYER_LEFT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x2EE*/ { "CMSG_BATTLEMASTER_JOIN", STATUS_LOGGEDIN, &WorldSession::HandleBattleGroundJoinOpcode }, + /*0x2EF*/ { "SMSG_ADDON_INFO", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x2F0*/ { "CMSG_PET_UNLEARN", STATUS_LOGGEDIN, &WorldSession::HandlePetUnlearnOpcode }, + /*0x2F1*/ { "SMSG_PET_UNLEARN_CONFIRM", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x2F2*/ { "SMSG_PARTY_MEMBER_STATS_FULL", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x2F3*/ { "CMSG_PET_SPELL_AUTOCAST", STATUS_LOGGEDIN, &WorldSession::HandlePetSpellAutocastOpcode }, + /*0x2F4*/ { "SMSG_WEATHER", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x2F5*/ { "SMSG_PLAY_TIME_WARNING", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x2F6*/ { "SMSG_MINIGAME_SETUP", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x2F7*/ { "SMSG_MINIGAME_STATE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x2F8*/ { "CMSG_MINIGAME_MOVE", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x2F9*/ { "SMSG_MINIGAME_MOVE_FAILED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x2FA*/ { "SMSG_RAID_INSTANCE_MESSAGE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x2FB*/ { "SMSG_COMPRESSED_MOVES", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x2FC*/ { "CMSG_GUILD_INFO_TEXT", STATUS_LOGGEDIN, &WorldSession::HandleGuildChangeInfoOpcode }, + /*0x2FD*/ { "SMSG_CHAT_RESTRICTED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x2FE*/ { "SMSG_SPLINE_SET_RUN_SPEED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x2FF*/ { "SMSG_SPLINE_SET_RUN_BACK_SPEED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x300*/ { "SMSG_SPLINE_SET_SWIM_SPEED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x301*/ { "SMSG_SPLINE_SET_WALK_SPEED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x302*/ { "SMSG_SPLINE_SET_SWIM_BACK_SPEED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x303*/ { "SMSG_SPLINE_SET_TURN_RATE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x304*/ { "SMSG_SPLINE_MOVE_UNROOT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x305*/ { "SMSG_SPLINE_MOVE_FEATHER_FALL", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x306*/ { "SMSG_SPLINE_MOVE_NORMAL_FALL", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x307*/ { "SMSG_SPLINE_MOVE_SET_HOVER", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x308*/ { "SMSG_SPLINE_MOVE_UNSET_HOVER", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x309*/ { "SMSG_SPLINE_MOVE_WATER_WALK", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x30A*/ { "SMSG_SPLINE_MOVE_LAND_WALK", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x30B*/ { "SMSG_SPLINE_MOVE_START_SWIM", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x30C*/ { "SMSG_SPLINE_MOVE_STOP_SWIM", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x30D*/ { "SMSG_SPLINE_MOVE_SET_RUN_MODE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x30E*/ { "SMSG_SPLINE_MOVE_SET_WALK_MODE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x30F*/ { "CMSG_GM_NUKE_ACCOUNT", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x310*/ { "MSG_GM_DESTROY_CORPSE", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x311*/ { "CMSG_GM_DESTROY_ONLINE_CORPSE", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x312*/ { "CMSG_ACTIVATETAXIEXPRESS", STATUS_LOGGEDIN, &WorldSession::HandleActivateTaxiFarOpcode }, + /*0x313*/ { "SMSG_SET_FACTION_ATWAR", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x314*/ { "SMSG_GAMETIMEBIAS_SET", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x315*/ { "CMSG_DEBUG_ACTIONS_START", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x316*/ { "CMSG_DEBUG_ACTIONS_STOP", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x317*/ { "CMSG_SET_FACTION_INACTIVE", STATUS_LOGGEDIN, &WorldSession::HandleSetWatchedFactionInactiveOpcode}, + /*0x318*/ { "CMSG_SET_WATCHED_FACTION", STATUS_LOGGEDIN, &WorldSession::HandleSetWatchedFactionIndexOpcode}, + /*0x319*/ { "MSG_MOVE_TIME_SKIPPED", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x31A*/ { "SMSG_SPLINE_MOVE_ROOT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x31B*/ { "CMSG_SET_EXPLORATION_ALL", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x31C*/ { "SMSG_INVALIDATE_PLAYER", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x31D*/ { "CMSG_RESET_INSTANCES", STATUS_LOGGEDIN, &WorldSession::HandleResetInstancesOpcode }, + /*0x31E*/ { "SMSG_INSTANCE_RESET", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x31F*/ { "SMSG_INSTANCE_RESET_FAILED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x320*/ { "SMSG_UPDATE_LAST_INSTANCE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x321*/ { "MSG_RAID_TARGET_UPDATE", STATUS_LOGGEDIN, &WorldSession::HandleRaidIconTargetOpcode }, + /*0x322*/ { "MSG_RAID_READY_CHECK", STATUS_LOGGEDIN, &WorldSession::HandleRaidReadyCheckOpcode }, + /*0x323*/ { "CMSG_LUA_USAGE", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x324*/ { "SMSG_PET_ACTION_SOUND", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x325*/ { "SMSG_PET_DISMISS_SOUND", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x326*/ { "SMSG_GHOSTEE_GONE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x327*/ { "CMSG_GM_UPDATE_TICKET_STATUS", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x328*/ { "SMSG_GM_TICKET_STATUS_UPDATE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x329*/ { "MSG_SET_DUNGEON_DIFFICULTY", STATUS_LOGGEDIN, &WorldSession::HandleDungeonDifficultyOpcode }, + /*0x32A*/ { "CMSG_GMSURVEY_SUBMIT", STATUS_LOGGEDIN, &WorldSession::HandleGMSurveySubmit }, + /*0x32B*/ { "SMSG_UPDATE_INSTANCE_OWNERSHIP", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x32C*/ { "CMSG_IGNORE_KNOCKBACK_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x32D*/ { "SMSG_CHAT_PLAYER_AMBIGUOUS", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x32E*/ { "MSG_DELAY_GHOST_TELEPORT", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x32F*/ { "SMSG_SPELLINSTAKILLLOG", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x330*/ { "SMSG_SPELL_UPDATE_CHAIN_TARGETS", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x331*/ { "CMSG_CHAT_FILTERED", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x332*/ { "SMSG_EXPECTED_SPAM_RECORDS", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x333*/ { "SMSG_SPELLSTEALLOG", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x334*/ { "CMSG_LOTTERY_QUERY_OBSOLETE", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x335*/ { "SMSG_LOTTERY_QUERY_RESULT_OBSOLETE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x336*/ { "CMSG_BUY_LOTTERY_TICKET_OBSOLETE", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x337*/ { "SMSG_LOTTERY_RESULT_OBSOLETE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x338*/ { "SMSG_CHARACTER_PROFILE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x339*/ { "SMSG_CHARACTER_PROFILE_REALM_CONNECTED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x33A*/ { "SMSG_DEFENSE_MESSAGE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x33B*/ { "SMSG_INSTANCE_DIFFICULTY", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x33C*/ { "MSG_GM_RESETINSTANCELIMIT", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x33D*/ { "SMSG_MOTD", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x33E*/ { "SMSG_MOVE_SET_FLIGHT_OBSOLETE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x33F*/ { "SMSG_MOVE_UNSET_FLIGHT_OBSOLETE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x340*/ { "CMSG_MOVE_FLIGHT_ACK_OBSOLETE", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x341*/ { "MSG_MOVE_START_SWIM_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x342*/ { "MSG_MOVE_STOP_SWIM_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x343*/ { "SMSG_MOVE_SET_CAN_FLY", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x344*/ { "SMSG_MOVE_UNSET_CAN_FLY", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x345*/ { "CMSG_MOVE_SET_CAN_FLY_ACK", STATUS_LOGGEDIN, &WorldSession::HandleMoveFlyModeChangeAckOpcode}, + /*0x346*/ { "CMSG_MOVE_SET_FLY", STATUS_LOGGEDIN, &WorldSession::HandleMovementOpcodes }, + /*0x347*/ { "CMSG_SOCKET_GEMS", STATUS_LOGGEDIN, &WorldSession::HandleSocketOpcode }, + /*0x348*/ { "CMSG_ARENA_TEAM_CREATE", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x349*/ { "SMSG_ARENA_TEAM_COMMAND_RESULT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x34A*/ { "UMSG_UPDATE_ARENA_TEAM_OBSOLETE", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x34B*/ { "CMSG_ARENA_TEAM_QUERY", STATUS_LOGGEDIN, &WorldSession::HandleArenaTeamQueryOpcode }, + /*0x34C*/ { "SMSG_ARENA_TEAM_QUERY_RESPONSE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x34D*/ { "CMSG_ARENA_TEAM_ROSTER", STATUS_LOGGEDIN, &WorldSession::HandleArenaTeamRosterOpcode }, + /*0x34E*/ { "SMSG_ARENA_TEAM_ROSTER", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x34F*/ { "CMSG_ARENA_TEAM_INVITE", STATUS_LOGGEDIN, &WorldSession::HandleArenaTeamAddMemberOpcode }, + /*0x350*/ { "SMSG_ARENA_TEAM_INVITE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x351*/ { "CMSG_ARENA_TEAM_ACCEPT", STATUS_LOGGEDIN, &WorldSession::HandleArenaTeamInviteAcceptOpcode}, + /*0x352*/ { "CMSG_ARENA_TEAM_DECLINE", STATUS_LOGGEDIN, &WorldSession::HandleArenaTeamInviteDeclineOpcode}, + /*0x353*/ { "CMSG_ARENA_TEAM_LEAVE", STATUS_LOGGEDIN, &WorldSession::HandleArenaTeamLeaveOpcode }, + /*0x354*/ { "CMSG_ARENA_TEAM_REMOVE", STATUS_LOGGEDIN, &WorldSession::HandleArenaTeamRemoveFromTeamOpcode}, + /*0x355*/ { "CMSG_ARENA_TEAM_DISBAND", STATUS_LOGGEDIN, &WorldSession::HandleArenaTeamDisbandOpcode }, + /*0x356*/ { "CMSG_ARENA_TEAM_LEADER", STATUS_LOGGEDIN, &WorldSession::HandleArenaTeamPromoteToCaptainOpcode}, + /*0x357*/ { "SMSG_ARENA_TEAM_EVENT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x358*/ { "CMSG_BATTLEMASTER_JOIN_ARENA", STATUS_LOGGEDIN, &WorldSession::HandleBattleGroundArenaJoin }, + /*0x359*/ { "MSG_MOVE_START_ASCEND", STATUS_LOGGEDIN, &WorldSession::HandleMovementOpcodes }, + /*0x35A*/ { "MSG_MOVE_STOP_ASCEND", STATUS_LOGGEDIN, &WorldSession::HandleMovementOpcodes }, + /*0x35B*/ { "SMSG_ARENA_TEAM_STATS", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x35C*/ { "CMSG_LFG_SET_AUTOJOIN", STATUS_AUTHED, &WorldSession::HandleLfgAutoJoinOpcode }, + /*0x35D*/ { "CMSG_LFG_CLEAR_AUTOJOIN", STATUS_LOGGEDIN, &WorldSession::HandleLfgCancelAutoJoinOpcode }, + /*0x35E*/ { "CMSG_LFM_SET_AUTOFILL", STATUS_AUTHED, &WorldSession::HandleLfmAutoAddMembersOpcode }, + /*0x35F*/ { "CMSG_LFM_CLEAR_AUTOFILL", STATUS_LOGGEDIN, &WorldSession::HandleLfmCancelAutoAddmembersOpcode}, + /*0x360*/ { "CMSG_ACCEPT_LFG_MATCH", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x361*/ { "CMSG_DECLINE_LFG_MATCH", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x362*/ { "CMSG_CANCEL_PENDING_LFG", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x363*/ { "CMSG_CLEAR_LOOKING_FOR_GROUP", STATUS_LOGGEDIN, &WorldSession::HandleLfgClearOpcode }, + /*0x364*/ { "CMSG_CLEAR_LOOKING_FOR_MORE", STATUS_LOGGEDIN, &WorldSession::HandleLfmSetNoneOpcode }, + /*0x365*/ { "CMSG_SET_LOOKING_FOR_MORE", STATUS_LOGGEDIN, &WorldSession::HandleLfmSetOpcode }, + /*0x366*/ { "CMSG_SET_LFG_COMMENT", STATUS_LOGGEDIN, &WorldSession::HandleLfgSetCommentOpcode }, + /*0x367*/ { "SMSG_LFG_TIMEDOUT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x368*/ { "SMSG_LFG_OTHER_TIMEDOUT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x369*/ { "SMSG_LFG_AUTOJOIN_FAILED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x36A*/ { "SMSG_LFG_AUTOJOIN_FAILED_NO_PLAYER", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x36B*/ { "SMSG_LFG_LEADER_IS_LFM", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x36C*/ { "SMSG_LFG_UPDATE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x36D*/ { "SMSG_LFG_UPDATE_LFM", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x36E*/ { "SMSG_LFG_UPDATE_LFG", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x36F*/ { "SMSG_LFG_UPDATE_QUEUED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x370*/ { "SMSG_LFG_PENDING_INVITE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x371*/ { "SMSG_LFG_PENDING_MATCH", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x372*/ { "SMSG_LFG_PENDING_MATCH_DONE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x373*/ { "SMSG_TITLE_EARNED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x374*/ { "CMSG_SET_TITLE", STATUS_LOGGEDIN, &WorldSession::HandleChooseTitleOpcode }, + /*0x375*/ { "CMSG_CANCEL_MOUNT_AURA", STATUS_LOGGEDIN, &WorldSession::HandleDismountOpcode }, + /*0x376*/ { "SMSG_ARENA_ERROR", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x377*/ { "MSG_INSPECT_ARENA_TEAMS", STATUS_LOGGEDIN, &WorldSession::HandleInspectArenaStatsOpcode }, + /*0x378*/ { "SMSG_DEATH_RELEASE_LOC", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x379*/ { "CMSG_CANCEL_TEMP_ENCHANTMENT", STATUS_LOGGEDIN, &WorldSession::HandleCancelTempItemEnchantmentOpcode}, + /*0x37A*/ { "SMSG_FORCED_DEATH_UPDATE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x37B*/ { "CMSG_CHEAT_SET_HONOR_CURRENCY", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x37C*/ { "CMSG_CHEAT_SET_ARENA_CURRENCY", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x37D*/ { "MSG_MOVE_SET_FLIGHT_SPEED_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x37E*/ { "MSG_MOVE_SET_FLIGHT_SPEED", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x37F*/ { "MSG_MOVE_SET_FLIGHT_BACK_SPEED_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x380*/ { "MSG_MOVE_SET_FLIGHT_BACK_SPEED", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x381*/ { "SMSG_FORCE_FLIGHT_SPEED_CHANGE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x382*/ { "CMSG_FORCE_FLIGHT_SPEED_CHANGE_ACK", STATUS_LOGGEDIN, &WorldSession::HandleForceSpeedChangeAck }, + /*0x383*/ { "SMSG_FORCE_FLIGHT_BACK_SPEED_CHANGE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x384*/ { "CMSG_FORCE_FLIGHT_BACK_SPEED_CHANGE_ACK", STATUS_LOGGEDIN, &WorldSession::HandleForceSpeedChangeAck }, + /*0x385*/ { "SMSG_SPLINE_SET_FLIGHT_SPEED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x386*/ { "SMSG_SPLINE_SET_FLIGHT_BACK_SPEED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x387*/ { "CMSG_MAELSTROM_INVALIDATE_CACHE", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x388*/ { "SMSG_FLIGHT_SPLINE_SYNC", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x389*/ { "CMSG_SET_TAXI_BENCHMARK_MODE", STATUS_AUTHED, &WorldSession::HandleSetTaxiBenchmarkOpcode }, + /*0x38A*/ { "SMSG_JOINED_BATTLEGROUND_QUEUE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x38B*/ { "SMSG_REALM_SPLIT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x38C*/ { "CMSG_REALM_SPLIT", STATUS_AUTHED, &WorldSession::HandleRealmStateRequestOpcode }, + /*0x38D*/ { "CMSG_MOVE_CHNG_TRANSPORT", STATUS_LOGGEDIN, &WorldSession::HandleMovementOpcodes }, + /*0x38E*/ { "MSG_PARTY_ASSIGNMENT", STATUS_LOGGEDIN, &WorldSession::HandleGroupPromoteOpcode }, + /*0x38F*/ { "SMSG_OFFER_PETITION_ERROR", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x390*/ { "SMSG_TIME_SYNC_REQ", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x391*/ { "CMSG_TIME_SYNC_RESP", STATUS_LOGGEDIN, &WorldSession::HandleTimeSyncResp }, + /*0x392*/ { "CMSG_SEND_LOCAL_EVENT", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x393*/ { "CMSG_SEND_GENERAL_TRIGGER", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x394*/ { "CMSG_SEND_COMBAT_TRIGGER", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x395*/ { "CMSG_MAELSTROM_GM_SENT_MAIL", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x396*/ { "SMSG_RESET_FAILED_NOTIFY", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x397*/ { "SMSG_REAL_GROUP_UPDATE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x398*/ { "SMSG_LFG_DISABLED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x399*/ { "CMSG_ACTIVE_PVP_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x39A*/ { "CMSG_CHEAT_DUMP_ITEMS_DEBUG_ONLY", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x39B*/ { "SMSG_CHEAT_DUMP_ITEMS_DEBUG_ONLY_RESPONSE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x39C*/ { "SMSG_CHEAT_DUMP_ITEMS_DEBUG_ONLY_RESPONSE_WRITE_FILE",STATUS_NEVER,&WorldSession::Handle_ServerSide }, + /*0x39D*/ { "SMSG_UPDATE_COMBO_POINTS", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x39E*/ { "SMSG_VOICE_SESSION_ROSTER_UPDATE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x39F*/ { "SMSG_VOICE_SESSION_LEAVE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x3A0*/ { "SMSG_VOICE_SESSION_ADJUST_PRIORITY", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x3A1*/ { "CMSG_VOICE_SET_TALKER_MUTED_REQUEST", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x3A2*/ { "SMSG_VOICE_SET_TALKER_MUTED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x3A3*/ { "SMSG_INIT_EXTRA_AURA_INFO_OBSOLETE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x3A4*/ { "SMSG_SET_EXTRA_AURA_INFO_OBSOLETE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x3A5*/ { "SMSG_SET_EXTRA_AURA_INFO_NEED_UPDATE_OBSOLETE",STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x3A6*/ { "SMSG_CLEAR_EXTRA_AURA_INFO_OBSOLETE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x3A7*/ { "MSG_MOVE_START_DESCEND", STATUS_LOGGEDIN, &WorldSession::HandleMovementOpcodes }, + /*0x3A8*/ { "CMSG_IGNORE_REQUIREMENTS_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x3A9*/ { "SMSG_IGNORE_REQUIREMENTS_CHEAT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x3AA*/ { "SMSG_SPELL_CHANCE_PROC_LOG", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x3AB*/ { "CMSG_MOVE_SET_RUN_SPEED", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x3AC*/ { "SMSG_DISMOUNT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x3AD*/ { "MSG_MOVE_UPDATE_CAN_FLY", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x3AE*/ { "MSG_RAID_READY_CHECK_CONFIRM", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x3AF*/ { "CMSG_VOICE_SESSION_ENABLE", STATUS_AUTHED, &WorldSession::HandleVoiceSettingsOpcode }, + /*0x3B0*/ { "SMSG_VOICE_SESSION_ENABLE", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x3B1*/ { "SMSG_VOICE_PARENTAL_CONTROLS", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x3B2*/ { "CMSG_GM_WHISPER", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x3B3*/ { "SMSG_GM_MESSAGECHAT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x3B4*/ { "MSG_GM_GEARRATING", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x3B5*/ { "CMSG_COMMENTATOR_ENABLE", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x3B6*/ { "SMSG_COMMENTATOR_STATE_CHANGED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x3B7*/ { "CMSG_COMMENTATOR_GET_MAP_INFO", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x3B8*/ { "SMSG_COMMENTATOR_MAP_INFO", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x3B9*/ { "CMSG_COMMENTATOR_GET_PLAYER_INFO", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x3BA*/ { "SMSG_COMMENTATOR_GET_PLAYER_INFO", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x3BB*/ { "SMSG_COMMENTATOR_PLAYER_INFO", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x3BC*/ { "CMSG_COMMENTATOR_ENTER_INSTANCE", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x3BD*/ { "CMSG_COMMENTATOR_EXIT_INSTANCE", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x3BE*/ { "CMSG_COMMENTATOR_INSTANCE_COMMAND", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x3BF*/ { "SMSG_CLEAR_TARGET", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x3C0*/ { "CMSG_BOT_DETECTED", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x3C1*/ { "SMSG_CROSSED_INEBRIATION_THRESHOLD", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x3C2*/ { "CMSG_CHEAT_PLAYER_LOGIN", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x3C3*/ { "CMSG_CHEAT_PLAYER_LOOKUP", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x3C4*/ { "SMSG_CHEAT_PLAYER_LOOKUP", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x3C5*/ { "SMSG_KICK_REASON", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x3C6*/ { "MSG_RAID_READY_CHECK_FINISHED", STATUS_LOGGEDIN, &WorldSession::HandleRaidReadyCheckFinishOpcode}, + /*0x3C7*/ { "CMSG_COMPLAIN", STATUS_LOGGEDIN, &WorldSession::HandleReportSpamOpcode }, + /*0x3C8*/ { "SMSG_COMPLAIN_RESULT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x3C9*/ { "SMSG_FEATURE_SYSTEM_STATUS", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x3CA*/ { "CMSG_GM_SHOW_COMPLAINTS", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x3CB*/ { "CMSG_GM_UNSQUELCH", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x3CC*/ { "CMSG_CHANNEL_SILENCE_VOICE", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x3CD*/ { "CMSG_CHANNEL_SILENCE_ALL", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x3CE*/ { "CMSG_CHANNEL_UNSILENCE_VOICE", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x3CF*/ { "CMSG_CHANNEL_UNSILENCE_ALL", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x3D0*/ { "CMSG_TARGET_CAST", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x3D1*/ { "CMSG_TARGET_SCRIPT_CAST", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x3D2*/ { "CMSG_CHANNEL_DISPLAY_LIST", STATUS_LOGGEDIN, &WorldSession::HandleChannelRosterQuery }, + /*0x3D3*/ { "CMSG_SET_ACTIVE_VOICE_CHANNEL", STATUS_AUTHED, &WorldSession::HandleChannelVoiceChatQuery }, + /*0x3D4*/ { "CMSG_GET_CHANNEL_MEMBER_COUNT", STATUS_LOGGEDIN, &WorldSession::HandleChannelInfoQuery }, + /*0x3D5*/ { "SMSG_CHANNEL_MEMBER_COUNT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x3D6*/ { "CMSG_CHANNEL_VOICE_ON", STATUS_LOGGEDIN, &WorldSession::HandleChannelEnableVoiceOpcode }, + /*0x3D7*/ { "CMSG_CHANNEL_VOICE_OFF", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x3D8*/ { "CMSG_DEBUG_LIST_TARGETS", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x3D9*/ { "SMSG_DEBUG_LIST_TARGETS", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x3DA*/ { "SMSG_AVAILABLE_VOICE_CHANNEL", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x3DB*/ { "CMSG_ADD_VOICE_IGNORE", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x3DC*/ { "CMSG_DEL_VOICE_IGNORE", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x3DD*/ { "CMSG_PARTY_SILENCE", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x3DE*/ { "CMSG_PARTY_UNSILENCE", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x3DF*/ { "MSG_NOTIFY_PARTY_SQUELCH", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x3E0*/ { "SMSG_COMSAT_RECONNECT_TRY", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x3E1*/ { "SMSG_COMSAT_DISCONNECT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x3E2*/ { "SMSG_COMSAT_CONNECT_FAIL", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x3E3*/ { "SMSG_VOICE_CHAT_STATUS", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x3E4*/ { "CMSG_REPORT_PVP_AFK", STATUS_LOGGEDIN, &WorldSession::HandleBattleGroundReportAFK }, + /*0x3E5*/ { "CMSG_REPORT_PVP_AFK_RESULT", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x3E6*/ { "CMSG_GUILD_BANKER_ACTIVATE", STATUS_LOGGEDIN, &WorldSession::HandleGuildBankQuery }, + /*0x3E7*/ { "CMSG_GUILD_BANK_QUERY_TAB", STATUS_LOGGEDIN, &WorldSession::HandleGuildBankTabColon }, + /*0x3E8*/ { "SMSG_GUILD_BANK_LIST", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x3E9*/ { "CMSG_GUILD_BANK_SWAP_ITEMS", STATUS_LOGGEDIN, &WorldSession::HandleGuildBankDepositItem }, + /*0x3EA*/ { "CMSG_GUILD_BANK_BUY_TAB", STATUS_LOGGEDIN, &WorldSession::HandleGuildBankBuyTab }, + /*0x3EB*/ { "CMSG_GUILD_BANK_UPDATE_TAB", STATUS_LOGGEDIN, &WorldSession::HandleGuildBankModifyTab }, + /*0x3EC*/ { "CMSG_GUILD_BANK_DEPOSIT_MONEY", STATUS_LOGGEDIN, &WorldSession::HandleGuildBankDeposit }, + /*0x3ED*/ { "CMSG_GUILD_BANK_WITHDRAW_MONEY", STATUS_LOGGEDIN, &WorldSession::HandleGuildBankWithdraw }, + /*0x3EE*/ { "MSG_GUILD_BANK_LOG_QUERY", STATUS_LOGGEDIN, &WorldSession::HandleGuildBankLog }, + /*0x3EF*/ { "CMSG_SET_CHANNEL_WATCH", STATUS_LOGGEDIN, &WorldSession::HandleChannelJoinNotify }, + /*0x3F0*/ { "SMSG_USERLIST_ADD", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x3F1*/ { "SMSG_USERLIST_REMOVE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x3F2*/ { "SMSG_USERLIST_UPDATE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x3F3*/ { "CMSG_CLEAR_CHANNEL_WATCH", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x3F4*/ { "SMSG_INSPECT_TALENT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x3F5*/ { "SMSG_GOGOGO_OBSOLETE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x3F6*/ { "SMSG_ECHO_PARTY_SQUELCH", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x3F7*/ { "CMSG_SET_TITLE_SUFFIX", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x3F8*/ { "CMSG_SPELLCLICK", STATUS_LOGGEDIN, &WorldSession::HandleSpellClick }, + /*0x3F9*/ { "SMSG_LOOT_LIST", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x3FA*/ { "CMSG_GM_CHARACTER_RESTORE", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x3FB*/ { "CMSG_GM_CHARACTER_SAVE", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x3FC*/ { "SMSG_VOICESESSION_FULL", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x3FD*/ { "MSG_GUILD_PERMISSIONS", STATUS_LOGGEDIN, &WorldSession::HandleGuildBankGetRights }, + /*0x3FE*/ { "MSG_GUILD_BANK_MONEY_WITHDRAWN", STATUS_LOGGEDIN, &WorldSession::HandleGuildBankGetMoneyAmount }, + /*0x3FF*/ { "MSG_GUILD_EVENT_LOG_QUERY", STATUS_LOGGEDIN, &WorldSession::HandleGuildEventLogOpcode }, + /*0x400*/ { "CMSG_MAELSTROM_RENAME_GUILD", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x401*/ { "CMSG_GET_MIRRORIMAGE_DATA", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x402*/ { "SMSG_MIRRORIMAGE_DATA", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x403*/ { "SMSG_FORCE_DISPLAY_UPDATE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x404*/ { "SMSG_SPELL_CHANCE_RESIST_PUSHBACK", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x405*/ { "CMSG_IGNORE_DIMINISHING_RETURNS_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x406*/ { "SMSG_IGNORE_DIMINISHING_RETURNS_CHEAT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x407*/ { "CMSG_KEEP_ALIVE", STATUS_NEVER, &WorldSession::Handle_EarlyProccess }, + /*0x408*/ { "SMSG_RAID_READY_CHECK_ERROR", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x409*/ { "CMSG_OPT_OUT_OF_LOOT", STATUS_AUTHED, &WorldSession::HandleGroupPassOnLootOpcode }, + /*0x40A*/ { "MSG_QUERY_GUILD_BANK_TEXT", STATUS_LOGGEDIN, &WorldSession::HandleGuildBankTabText }, + /*0x40B*/ { "CMSG_SET_GUILD_BANK_TEXT", STATUS_LOGGEDIN, &WorldSession::HandleGuildBankSetTabText }, + /*0x40C*/ { "CMSG_SET_GRANTABLE_LEVELS", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x40D*/ { "CMSG_GRANT_LEVEL", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x40E*/ { "CMSG_REFER_A_FRIEND", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x40F*/ { "MSG_GM_CHANGE_ARENA_RATING", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x410*/ { "CMSG_DECLINE_CHANNEL_INVITE", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x411*/ { "CMSG_GROUPACTION_THROTTLED", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x412*/ { "SMSG_OVERRIDE_LIGHT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x413*/ { "SMSG_TOTEM_CREATED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x414*/ { "CMSG_TOTEM_DESTROYED", STATUS_LOGGEDIN, &WorldSession::HandleTotemDestroy }, + /*0x415*/ { "CMSG_EXPIRE_RAID_INSTANCE", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x416*/ { "CMSG_NO_SPELL_VARIANCE", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x417*/ { "CMSG_QUESTGIVER_STATUS_MULTIPLE_QUERY", STATUS_LOGGEDIN, &WorldSession::HandleQuestgiverStatusQueryMultipleOpcode}, + /*0x418*/ { "SMSG_QUESTGIVER_STATUS_MULTIPLE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x419*/ { "CMSG_SET_PLAYER_DECLINED_NAMES", STATUS_AUTHED, &WorldSession::HandleDeclinedPlayerNameOpcode }, + /*0x41A*/ { "SMSG_SET_PLAYER_DECLINED_NAMES_RESULT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x41B*/ { "CMSG_QUERY_SERVER_BUCK_DATA", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x41C*/ { "CMSG_CLEAR_SERVER_BUCK_DATA", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x41D*/ { "SMSG_SERVER_BUCK_DATA", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x41E*/ { "SMSG_SEND_UNLEARN_SPELLS", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x41F*/ { "SMSG_PROPOSE_LEVEL_GRANT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x420*/ { "CMSG_ACCEPT_LEVEL_GRANT", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x421*/ { "SMSG_REFER_A_FRIEND_FAILURE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x422*/ { "SMSG_SPLINE_MOVE_SET_FLYING", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x423*/ { "SMSG_SPLINE_MOVE_UNSET_FLYING", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x424*/ { "SMSG_SUMMON_CANCEL", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x425*/ { "CMSG_CHANGE_PERSONAL_ARENA_RATING", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x426*/ { "CMSG_ALTER_APPEARANCE", STATUS_LOGGEDIN, &WorldSession::HandleAlterAppearance }, + /*0x427*/ { "SMSG_ENABLE_BARBER_SHOP", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x428*/ { "SMSG_BARBER_SHOP_RESULT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x429*/ { "CMSG_CALENDAR_GET_CALENDAR", STATUS_LOGGEDIN, &WorldSession::HandleCalendarGetCalendar }, + /*0x42A*/ { "CMSG_CALENDAR_GET_EVENT", STATUS_LOGGEDIN, &WorldSession::HandleCalendarGetEvent }, + /*0x42B*/ { "CMSG_CALENDAR_GUILD_FILTER", STATUS_LOGGEDIN, &WorldSession::HandleCalendarGuildFilter }, + /*0x42C*/ { "CMSG_CALENDAR_ARENA_TEAM", STATUS_LOGGEDIN, &WorldSession::HandleCalendarArenaTeam }, + /*0x42D*/ { "CMSG_CALENDAR_ADD_EVENT", STATUS_LOGGEDIN, &WorldSession::HandleCalendarAddEvent }, + /*0x42E*/ { "CMSG_CALENDAR_UPDATE_EVENT", STATUS_LOGGEDIN, &WorldSession::HandleCalendarUpdateEvent }, + /*0x42F*/ { "CMSG_CALENDAR_REMOVE_EVENT", STATUS_LOGGEDIN, &WorldSession::HandleCalendarRemoveEvent }, + /*0x430*/ { "CMSG_CALENDAR_COPY_EVENT", STATUS_LOGGEDIN, &WorldSession::HandleCalendarCopyEvent }, + /*0x431*/ { "CMSG_CALENDAR_EVENT_INVITE", STATUS_LOGGEDIN, &WorldSession::HandleCalendarEventInvite }, + /*0x432*/ { "CMSG_CALENDAR_EVENT_RSVP", STATUS_LOGGEDIN, &WorldSession::HandleCalendarEventRsvp }, + /*0x433*/ { "CMSG_CALENDAR_EVENT_REMOVE_INVITE", STATUS_LOGGEDIN, &WorldSession::HandleCalendarEventRemoveInvite }, + /*0x434*/ { "CMSG_CALENDAR_EVENT_STATUS", STATUS_LOGGEDIN, &WorldSession::HandleCalendarEventStatus }, + /*0x435*/ { "CMSG_CALENDAR_EVENT_MODERATOR_STATUS", STATUS_LOGGEDIN, &WorldSession::HandleCalendarEventModeratorStatus}, + /*0x436*/ { "SMSG_CALENDAR_SEND_CALENDAR", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x437*/ { "SMSG_CALENDAR_SEND_EVENT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x438*/ { "SMSG_CALENDAR_FILTER_GUILD", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x439*/ { "SMSG_CALENDAR_ARENA_TEAM", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x43A*/ { "SMSG_CALENDAR_EVENT_INVITE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x43B*/ { "SMSG_CALENDAR_EVENT_INVITE_REMOVED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x43C*/ { "SMSG_CALENDAR_EVENT_STATUS", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x43D*/ { "SMSG_CALENDAR_COMMAND_RESULT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x43E*/ { "SMSG_CALENDAR_RAID_LOCKOUT_ADDED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x43F*/ { "SMSG_CALENDAR_RAID_LOCKOUT_REMOVED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x440*/ { "SMSG_CALENDAR_EVENT_INVITE_ALERT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x441*/ { "SMSG_CALENDAR_EVENT_INVITE_REMOVED_ALERT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x442*/ { "SMSG_CALENDAR_EVENT_INVITE_STATUS_ALERT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x443*/ { "SMSG_CALENDAR_EVENT_REMOVED_ALERT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x444*/ { "SMSG_CALENDAR_EVENT_UPDATED_ALERT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x445*/ { "SMSG_CALENDAR_EVENT_MODERATOR_STATUS_ALERT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x446*/ { "CMSG_CALENDAR_COMPLAIN", STATUS_LOGGEDIN, &WorldSession::HandleCalendarComplain }, + /*0x447*/ { "CMSG_CALENDAR_GET_NUM_PENDING", STATUS_LOGGEDIN, &WorldSession::HandleCalendarGetNumPending }, + /*0x448*/ { "SMSG_CALENDAR_SEND_NUM_PENDING", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x449*/ { "CMSG_SAVE_DANCE", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x44A*/ { "SMSG_NOTIFY_DANCE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x44B*/ { "CMSG_PLAY_DANCE", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x44C*/ { "SMSG_PLAY_DANCE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x44D*/ { "CMSG_LOAD_DANCES", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x44E*/ { "CMSG_STOP_DANCE", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x44F*/ { "SMSG_STOP_DANCE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x450*/ { "CMSG_SYNC_DANCE", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x451*/ { "CMSG_DANCE_QUERY", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x452*/ { "SMSG_DANCE_QUERY_RESPONSE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x453*/ { "SMSG_INVALIDATE_DANCE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x454*/ { "CMSG_DELETE_DANCE", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x455*/ { "SMSG_LEARNED_DANCE_MOVES", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x456*/ { "CMSG_LEARN_DANCE_MOVE", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x457*/ { "CMSG_UNLEARN_DANCE_MOVE", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x458*/ { "CMSG_SET_RUNE_COUNT", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x459*/ { "CMSG_SET_RUNE_COOLDOWN", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x45A*/ { "MSG_MOVE_SET_PITCH_RATE_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x45B*/ { "MSG_MOVE_SET_PITCH_RATE", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x45C*/ { "SMSG_FORCE_PITCH_RATE_CHANGE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x45D*/ { "CMSG_FORCE_PITCH_RATE_CHANGE_ACK", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x45E*/ { "SMSG_SPLINE_SET_PITCH_RATE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x45F*/ { "SMSG_MOVE_ABANDON_TRANSPORT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x460*/ { "MSG_MOVE_ABANDON_TRANSPORT", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x461*/ { "CMSG_MOVE_ABANDON_TRANSPORT_ACK", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x462*/ { "CMSG_UPDATE_MISSILE_TRAJECTORY", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x463*/ { "SMSG_UPDATE_ACCOUNT_DATA_COMPLETE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x464*/ { "SMSG_TRIGGER_MOVIE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x465*/ { "CMSG_COMPLETE_MOVIE", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x466*/ { "CMSG_SET_GLYPH_SLOT", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x467*/ { "CMSG_SET_GLYPH", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x468*/ { "SMSG_ACHIEVEMENT_EARNED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x469*/ { "SMSG_DYNAMIC_DROP_ROLL_RESULT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x46A*/ { "SMSG_CRITERIA_UPDATE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x46B*/ { "CMSG_QUERY_INSPECT_ACHIEVEMENTS", STATUS_LOGGEDIN, &WorldSession::HandleInspectAchievements }, + /*0x46C*/ { "SMSG_RESPOND_INSPECT_ACHIEVEMENTS", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x46D*/ { "CMSG_DISMISS_CONTROLLED_VEHICLE", STATUS_LOGGEDIN, &WorldSession::HandleDismissControlledVehicle }, + /*0x46E*/ { "CMSG_COMPLETE_ACHIEVEMENT_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x46F*/ { "SMSG_QUESTUPDATE_ADD_PVP_KILL", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x470*/ { "CMSG_SET_CRITERIA_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x471*/ { "SMSG_GROUP_SWAP_FAILED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x472*/ { "CMSG_UNITANIMTIER_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x473*/ { "CMSG_CHAR_CUSTOMIZE", STATUS_AUTHED, &WorldSession::HandleCharCustomize }, + /*0x474*/ { "SMSG_CHAR_CUSTOMIZE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x475*/ { "SMSG_PET_RENAMEABLE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x476*/ { "CMSG_REQUEST_VEHICLE_EXIT", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x477*/ { "CMSG_REQUEST_VEHICLE_PREV_SEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x478*/ { "CMSG_REQUEST_VEHICLE_NEXT_SEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x479*/ { "CMSG_REQUEST_VEHICLE_SWITCH_SEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x47A*/ { "CMSG_PET_LEARN_TALENT", STATUS_LOGGEDIN, &WorldSession::HandlePetLearnTalent }, + /*0x47B*/ { "CMSG_PET_UNLEARN_TALENTS", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x47C*/ { "SMSG_SET_PHASE_SHIFT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x47D*/ { "SMSG_ALL_ACHIEVEMENT_DATA", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x47E*/ { "CMSG_FORCE_SAY_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x47F*/ { "SMSG_HEALTH_UPDATE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x480*/ { "SMSG_POWER_UPDATE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x481*/ { "CMSG_GAMEOBJ_REPORT_USE", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x482*/ { "SMSG_HIGHEST_THREAT_UPDATE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x483*/ { "SMSG_THREAT_UPDATE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x484*/ { "SMSG_THREAT_REMOVE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x485*/ { "SMSG_THREAT_CLEAR", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x486*/ { "SMSG_CONVERT_RUNE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x487*/ { "SMSG_RESYNC_RUNES", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x488*/ { "SMSG_ADD_RUNE_POWER", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x489*/ { "CMSG_START_QUEST", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x48A*/ { "CMSG_REMOVE_GLYPH", STATUS_LOGGEDIN, &WorldSession::HandleRemoveGlyph }, + /*0x48B*/ { "CMSG_DUMP_OBJECTS", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x48C*/ { "SMSG_DUMP_OBJECTS_DATA", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x48D*/ { "CMSG_DISMISS_CRITTER", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x48E*/ { "SMSG_NOTIFY_DEST_LOC_SPELL_CAST", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x48F*/ { "CMSG_AUCTION_LIST_PENDING_SALES", STATUS_LOGGEDIN, &WorldSession::HandleAuctionListPendingSales }, + /*0x490*/ { "SMSG_AUCTION_LIST_PENDING_SALES", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x491*/ { "SMSG_MODIFY_COOLDOWN", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x492*/ { "SMSG_PET_UPDATE_COMBO_POINTS", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x493*/ { "CMSG_ENABLETAXI", STATUS_LOGGEDIN, &WorldSession::HandleTaxiQueryAvailableNodes }, + /*0x494*/ { "SMSG_PRE_RESURRECT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x495*/ { "SMSG_AURA_UPDATE_ALL", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x496*/ { "SMSG_AURA_UPDATE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x497*/ { "CMSG_FLOOD_GRACE_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x498*/ { "SMSG_SERVER_FIRST_ACHIEVEMENT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x499*/ { "SMSG_PET_LEARNED_SPELL", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x49A*/ { "SMSG_PET_REMOVED_SPELL", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x49B*/ { "CMSG_CHANGE_SEATS_ON_CONTROLLED_VEHICLE", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x49C*/ { "CMSG_HEARTH_AND_RESURRECT", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x49D*/ { "SMSG_ON_CANCEL_EXPECTED_RIDE_VEHICLE_AURA", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x49E*/ { "SMSG_CRITERIA_DELETED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x49F*/ { "SMSG_ACHIEVEMENT_DELETED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x4A0*/ { "CMSG_SERVER_INFO_QUERY", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x4A1*/ { "SMSG_SERVER_INFO_RESPONSE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x4A2*/ { "CMSG_CHECK_LOGIN_CRITERIA", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x4A3*/ { "SMSG_SERVER_BUCK_DATA_START", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x4A4*/ { "CMSG_QUERY_VEHICLE_STATUS", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x4A5*/ { "SMSG_PET_GUIDS", STATUS_NEVER, &WorldSession::Handle_ServerSide }, }; diff --git a/src/game/Opcodes.h b/src/game/Opcodes.h index a706fdea8..124a03c68 100644 --- a/src/game/Opcodes.h +++ b/src/game/Opcodes.h @@ -25,6 +25,12 @@ #include "Common.h" +// Note: this include need for be sure have full definition of class WorldSession +// if this class definition not complite then VS for x64 release use different size for +// struct OpcodeHandler in this header and Opcode.cpp and get totally wrong data from +// table opcodeTable in source when Opcode.h included but WorldSession.h not included +#include "WorldSession.h" + /// List of Opcodes enum Opcodes { @@ -41,8 +47,8 @@ enum Opcodes CMSG_ZONE_MAP = 0x00A, SMSG_ZONE_MAP = 0x00B, CMSG_DEBUG_CHANGECELLZONE = 0x00C, - CMSG_EMBLAZON_TABARD_OBSOLETE = 0x00D, - CMSG_UNEMBLAZON_TABARD_OBSOLETE = 0x00E, + CMSG_MOVE_CHARACTER_CHEAT = 0x00D, + SMSG_MOVE_CHARACTER_CHEAT = 0x00E, CMSG_RECHARGE = 0x00F, CMSG_LEARN_SPELL = 0x010, CMSG_CREATEMONSTER = 0x011, @@ -58,7 +64,7 @@ enum Opcodes SMSG_FORCEACTIONSHOW = 0x01B, CMSG_PETGODMODE = 0x01C, SMSG_PETGODMODE = 0x01D, - SMSG_DEBUGINFOSPELLMISS_OBSOLETE = 0x01E, + SMSG_REFER_A_FRIEND_EXPIRED = 0x01E, CMSG_WEATHER_SPEED_CHEAT = 0x01F, CMSG_UNDRESSPLAYER = 0x020, CMSG_BEASTMASTER = 0x021, @@ -78,7 +84,7 @@ enum Opcodes SMSG_DEBUG_AISTATE = 0x02F, CMSG_DISABLE_PVP_CHEAT = 0x030, CMSG_ADVANCE_SPAWN_TIME = 0x031, - CMSG_PVP_PORT_OBSOLETE = 0x032, + SMSG_DESTRUCTIBLE_BUILDING_DAMAGE = 0x032, CMSG_AUTH_SRP6_BEGIN = 0x033, CMSG_AUTH_SRP6_PROOF = 0x034, CMSG_AUTH_SRP6_RECODE = 0x035, @@ -206,7 +212,7 @@ enum Opcodes SMSG_READ_ITEM_FAILED = 0x0AF, SMSG_ITEM_COOLDOWN = 0x0B0, CMSG_GAMEOBJ_USE = 0x0B1, - CMSG_GAMEOBJ_CHAIR_USE_OBSOLETE = 0x0B2, + CMSG_DESTROY_ITEMS = 0x0B2, SMSG_GAMEOBJECT_CUSTOM_ANIM = 0x0B3, CMSG_AREATRIGGER = 0x0B4, MSG_MOVE_START_FORWARD = 0x0B5, @@ -339,7 +345,7 @@ enum Opcodes SMSG_SPELL_COOLDOWN = 0x134, SMSG_COOLDOWN_EVENT = 0x135, CMSG_CANCEL_AURA = 0x136, - SMSG_UPDATE_AURA_DURATION = 0x137, + SMSG_UPDATE_AURA_DURATION_OBSOLETE = 0x137, SMSG_PET_CAST_FAILED = 0x138, MSG_CHANNEL_START = 0x139, MSG_CHANNEL_UPDATE = 0x13A, @@ -363,10 +369,10 @@ enum Opcodes SMSG_DAMAGE_DONE_OBSOLETE = 0x14C, SMSG_DAMAGE_TAKEN_OBSOLETE = 0x14D, SMSG_CANCEL_COMBAT = 0x14E, - SMSG_PLAYER_COMBAT_XP_GAIN_OBSOLETE = 0x14F, + SMSG_SPELLBREAKLOG = 0x14F, SMSG_SPELLHEALLOG = 0x150, SMSG_SPELLENERGIZELOG = 0x151, - CMSG_SHEATHE_OBSOLETE = 0x152, + SMSG_BREAK_TARGET = 0x152, CMSG_SAVE_PLAYER = 0x153, CMSG_SETDEATHBINDPOINT = 0x154, SMSG_BINDPOINTUPDATE = 0x155, @@ -570,7 +576,7 @@ enum Opcodes SMSG_GMTICKET_SYSTEMSTATUS = 0x21B, CMSG_SPIRIT_HEALER_ACTIVATE = 0x21C, CMSG_SET_STAT_CHEAT = 0x21D, - SMSG_SET_REST_START = 0x21E, + SMSG_SET_REST_START_OBSOLETE = 0x21E, CMSG_SKILL_BUY_STEP = 0x21F, CMSG_SKILL_BUY_RANK = 0x220, CMSG_XP_CHEAT = 0x221, @@ -725,8 +731,8 @@ enum Opcodes SMSG_SCRIPT_MESSAGE = 0x2B6, SMSG_DUEL_COUNTDOWN = 0x2B7, SMSG_AREA_TRIGGER_MESSAGE = 0x2B8, - CMSG_TOGGLE_HELM = 0x2B9, - CMSG_TOGGLE_CLOAK = 0x2BA, + CMSG_SHOWING_HELM = 0x2B9, + CMSG_SHOWING_CLOAK = 0x2BA, SMSG_MEETINGSTONE_JOINFAILED = 0x2BB, SMSG_PLAYER_SKINNED = 0x2BC, SMSG_DURABILITY_DAMAGE_DEATH = 0x2BD, @@ -959,10 +965,10 @@ enum Opcodes SMSG_VOICE_SESSION_ADJUST_PRIORITY = 0x3A0, CMSG_VOICE_SET_TALKER_MUTED_REQUEST = 0x3A1, SMSG_VOICE_SET_TALKER_MUTED = 0x3A2, - SMSG_INIT_EXTRA_AURA_INFO = 0x3A3, - SMSG_SET_EXTRA_AURA_INFO = 0x3A4, - SMSG_SET_EXTRA_AURA_INFO_NEED_UPDATE = 0x3A5, - SMSG_CLEAR_EXTRA_AURA_INFO = 0x3A6, + SMSG_INIT_EXTRA_AURA_INFO_OBSOLETE = 0x3A3, + SMSG_SET_EXTRA_AURA_INFO_OBSOLETE = 0x3A4, + SMSG_SET_EXTRA_AURA_INFO_NEED_UPDATE_OBSOLETE = 0x3A5, + SMSG_CLEAR_EXTRA_AURA_INFO_OBSOLETE = 0x3A6, MSG_MOVE_START_DESCEND = 0x3A7, CMSG_IGNORE_REQUIREMENTS_CHEAT = 0x3A8, SMSG_IGNORE_REQUIREMENTS_CHEAT = 0x3A9, @@ -972,127 +978,255 @@ enum Opcodes MSG_MOVE_UPDATE_CAN_FLY = 0x3AD, MSG_RAID_READY_CHECK_CONFIRM = 0x3AE, CMSG_VOICE_SESSION_ENABLE = 0x3AF, - SMSG_VOICE_PARENTAL_CONTROLS = 0x3B0, - CMSG_GM_WHISPER = 0x3B1, - SMSG_GM_MESSAGECHAT = 0x3B2, - MSG_GM_GEARRATING = 0x3B3, - CMSG_COMMENTATOR_ENABLE = 0x3B4, - SMSG_COMMENTATOR_STATE_CHANGED = 0x3B5, - CMSG_COMMENTATOR_GET_MAP_INFO = 0x3B6, - SMSG_COMMENTATOR_MAP_INFO = 0x3B7, - CMSG_COMMENTATOR_GET_PLAYER_INFO = 0x3B8, - SMSG_COMMENTATOR_GET_PLAYER_INFO = 0x3B9, - SMSG_COMMENTATOR_PLAYER_INFO = 0x3BA, - CMSG_COMMENTATOR_ENTER_INSTANCE = 0x3BB, - CMSG_COMMENTATOR_EXIT_INSTANCE = 0x3BC, - CMSG_COMMENTATOR_INSTANCE_COMMAND = 0x3BD, - SMSG_CLEAR_TARGET = 0x3BE, - CMSG_BOT_DETECTED = 0x3BF, - SMSG_CROSSED_INEBRIATION_THRESHOLD = 0x3C0, - CMSG_CHEAT_PLAYER_LOGIN = 0x3C1, - CMSG_CHEAT_PLAYER_LOOKUP = 0x3C2, - SMSG_CHEAT_PLAYER_LOOKUP = 0x3C3, - SMSG_KICK_REASON = 0x3C4, - MSG_RAID_READY_CHECK_FINISHED = 0x3C5, - CMSG_COMPLAIN = 0x3C6, - SMSG_COMPLAIN_RESULT = 0x3C7, - SMSG_FEATURE_SYSTEM_STATUS = 0x3C8, - CMSG_GM_SHOW_COMPLAINTS = 0x3C9, - CMSG_GM_UNSQUELCH = 0x3CA, - CMSG_CHANNEL_SILENCE_VOICE = 0x3CB, - CMSG_CHANNEL_SILENCE_ALL = 0x3CC, - CMSG_CHANNEL_UNSILENCE_VOICE = 0x3CD, - CMSG_CHANNEL_UNSILENCE_ALL = 0x3CE, - CMSG_TARGET_CAST = 0x3CF, - CMSG_TARGET_SCRIPT_CAST = 0x3D0, - CMSG_CHANNEL_DISPLAY_LIST = 0x3D1, - CMSG_SET_ACTIVE_VOICE_CHANNEL = 0x3D2, - CMSG_GET_CHANNEL_MEMBER_COUNT = 0x3D3, - SMSG_CHANNEL_MEMBER_COUNT = 0x3D4, - CMSG_CHANNEL_VOICE_ON = 0x3D5, - CMSG_CHANNEL_VOICE_OFF = 0x3D6, - CMSG_DEBUG_LIST_TARGETS = 0x3D7, - SMSG_DEBUG_LIST_TARGETS = 0x3D8, - SMSG_AVAILABLE_VOICE_CHANNEL = 0x3D9, - CMSG_ADD_VOICE_IGNORE = 0x3DA, - CMSG_DEL_VOICE_IGNORE = 0x3DB, - CMSG_PARTY_SILENCE = 0x3DC, - CMSG_PARTY_UNSILENCE = 0x3DD, - MSG_NOTIFY_PARTY_SQUELCH = 0x3DE, - SMSG_COMSAT_RECONNECT_TRY = 0x3DF, - SMSG_COMSAT_DISCONNECT = 0x3E0, - SMSG_COMSAT_CONNECT_FAIL = 0x3E1, - SMSG_VOICE_CHAT_STATUS = 0x3E2, - CMSG_REPORT_PVP_AFK = 0x3E3, - CMSG_REPORT_PVP_AFK_RESULT = 0x3E4, - CMSG_GUILD_BANKER_ACTIVATE = 0x3E5, - CMSG_GUILD_BANK_QUERY_TAB = 0x3E6, - SMSG_GUILD_BANK_LIST = 0x3E7, - CMSG_GUILD_BANK_SWAP_ITEMS = 0x3E8, - CMSG_GUILD_BANK_BUY_TAB = 0x3E9, - CMSG_GUILD_BANK_UPDATE_TAB = 0x3EA, - CMSG_GUILD_BANK_DEPOSIT_MONEY = 0x3EB, - CMSG_GUILD_BANK_WITHDRAW_MONEY = 0x3EC, - MSG_GUILD_BANK_LOG_QUERY = 0x3ED, - CMSG_SET_CHANNEL_WATCH = 0x3EE, - SMSG_USERLIST_ADD = 0x3EF, - SMSG_USERLIST_REMOVE = 0x3F0, - SMSG_USERLIST_UPDATE = 0x3F1, - CMSG_CLEAR_CHANNEL_WATCH = 0x3F2, - SMSG_INSPECT_TALENT = 0x3F3, - SMSG_GOGOGO_OBSOLETE = 0x3F4, - SMSG_ECHO_PARTY_SQUELCH = 0x3F5, - CMSG_SET_TITLE_SUFFIX = 0x3F6, - CMSG_SPELLCLICK = 0x3F7, - SMSG_LOOT_LIST = 0x3F8, - CMSG_GM_CHARACTER_RESTORE = 0x3F9, - CMSG_GM_CHARACTER_SAVE = 0x3FA, - SMSG_VOICESESSION_FULL = 0x3FB, - MSG_GUILD_PERMISSIONS = 0x3FC, - MSG_GUILD_BANK_MONEY_WITHDRAWN = 0x3FD, - MSG_GUILD_EVENT_LOG_QUERY = 0x3FE, - CMSG_MAELSTROM_RENAME_GUILD = 0x3FF, - CMSG_GET_MIRRORIMAGE_DATA = 0x400, - SMSG_MIRRORIMAGE_DATA = 0x401, - SMSG_FORCE_DISPLAY_UPDATE = 0x402, - SMSG_SPELL_CHANCE_RESIST_PUSHBACK = 0x403, - CMSG_IGNORE_DIMINISHING_RETURNS_CHEAT = 0x404, - SMSG_IGNORE_DIMINISHING_RETURNS_CHEAT = 0x405, - CMSG_KEEP_ALIVE = 0x406, - SMSG_RAID_READY_CHECK_ERROR = 0x407, - CMSG_OPT_OUT_OF_LOOT = 0x408, - MSG_QUERY_GUILD_BANK_TEXT = 0x409, - CMSG_SET_GUILD_BANK_TEXT = 0x40A, - CMSG_SET_GRANTABLE_LEVELS = 0x40B, - CMSG_GRANT_LEVEL = 0x40C, - CMSG_REFER_A_FRIEND = 0x40D, - MSG_GM_CHANGE_ARENA_RATING = 0x40E, - CMSG_DECLINE_CHANNEL_INVITE = 0x40F, - CMSG_GROUPACTION_THROTTLED = 0x410, - SMSG_OVERRIDE_LIGHT = 0x411, - SMSG_TOTEM_CREATED = 0x412, - CMSG_TOTEM_DESTROYED = 0x413, - CMSG_EXPIRE_RAID_INSTANCE = 0x414, - CMSG_NO_SPELL_VARIANCE = 0x415, - CMSG_QUESTGIVER_STATUS_MULTIPLE_QUERY = 0x416, - SMSG_QUESTGIVER_STATUS_MULTIPLE = 0x417, - CMSG_SET_PLAYER_DECLINED_NAMES = 0x418, - SMSG_SET_PLAYER_DECLINED_NAMES_RESULT = 0x419, - CMSG_QUERY_SERVER_BUCK_DATA = 0x41A, - CMSG_CLEAR_SERVER_BUCK_DATA = 0x41B, - SMSG_SERVER_BUCK_DATA = 0x41C, - SMSG_SEND_UNLEARN_SPELLS = 0x41D, - SMSG_PROPOSE_LEVEL_GRANT = 0x41E, - CMSG_ACCEPT_LEVEL_GRANT = 0x41F, - SMSG_REFER_A_FRIEND_FAILURE = 0x420, - SMSG_SPLINE_MOVE_SET_FLYING = 0x421, - SMSG_SPLINE_MOVE_UNSET_FLYING = 0x422, - SMSG_SUMMON_CANCEL = 0x423 + SMSG_VOICE_SESSION_ENABLE = 0x3B0, + SMSG_VOICE_PARENTAL_CONTROLS = 0x3B1, + CMSG_GM_WHISPER = 0x3B2, + SMSG_GM_MESSAGECHAT = 0x3B3, + MSG_GM_GEARRATING = 0x3B4, + CMSG_COMMENTATOR_ENABLE = 0x3B5, + SMSG_COMMENTATOR_STATE_CHANGED = 0x3B6, + CMSG_COMMENTATOR_GET_MAP_INFO = 0x3B7, + SMSG_COMMENTATOR_MAP_INFO = 0x3B8, + CMSG_COMMENTATOR_GET_PLAYER_INFO = 0x3B9, + SMSG_COMMENTATOR_GET_PLAYER_INFO = 0x3BA, + SMSG_COMMENTATOR_PLAYER_INFO = 0x3BB, + CMSG_COMMENTATOR_ENTER_INSTANCE = 0x3BC, + CMSG_COMMENTATOR_EXIT_INSTANCE = 0x3BD, + CMSG_COMMENTATOR_INSTANCE_COMMAND = 0x3BE, + SMSG_CLEAR_TARGET = 0x3BF, + CMSG_BOT_DETECTED = 0x3C0, + SMSG_CROSSED_INEBRIATION_THRESHOLD = 0x3C1, + CMSG_CHEAT_PLAYER_LOGIN = 0x3C2, + CMSG_CHEAT_PLAYER_LOOKUP = 0x3C3, + SMSG_CHEAT_PLAYER_LOOKUP = 0x3C4, + SMSG_KICK_REASON = 0x3C5, + MSG_RAID_READY_CHECK_FINISHED = 0x3C6, + CMSG_COMPLAIN = 0x3C7, + SMSG_COMPLAIN_RESULT = 0x3C8, + SMSG_FEATURE_SYSTEM_STATUS = 0x3C9, + CMSG_GM_SHOW_COMPLAINTS = 0x3CA, + CMSG_GM_UNSQUELCH = 0x3CB, + CMSG_CHANNEL_SILENCE_VOICE = 0x3CC, + CMSG_CHANNEL_SILENCE_ALL = 0x3CD, + CMSG_CHANNEL_UNSILENCE_VOICE = 0x3CE, + CMSG_CHANNEL_UNSILENCE_ALL = 0x3CF, + CMSG_TARGET_CAST = 0x3D0, + CMSG_TARGET_SCRIPT_CAST = 0x3D1, + CMSG_CHANNEL_DISPLAY_LIST = 0x3D2, + CMSG_SET_ACTIVE_VOICE_CHANNEL = 0x3D3, + CMSG_GET_CHANNEL_MEMBER_COUNT = 0x3D4, + SMSG_CHANNEL_MEMBER_COUNT = 0x3D5, + CMSG_CHANNEL_VOICE_ON = 0x3D6, + CMSG_CHANNEL_VOICE_OFF = 0x3D7, + CMSG_DEBUG_LIST_TARGETS = 0x3D8, + SMSG_DEBUG_LIST_TARGETS = 0x3D9, + SMSG_AVAILABLE_VOICE_CHANNEL = 0x3DA, + CMSG_ADD_VOICE_IGNORE = 0x3DB, + CMSG_DEL_VOICE_IGNORE = 0x3DC, + CMSG_PARTY_SILENCE = 0x3DD, + CMSG_PARTY_UNSILENCE = 0x3DE, + MSG_NOTIFY_PARTY_SQUELCH = 0x3DF, + SMSG_COMSAT_RECONNECT_TRY = 0x3E0, + SMSG_COMSAT_DISCONNECT = 0x3E1, + SMSG_COMSAT_CONNECT_FAIL = 0x3E2, + SMSG_VOICE_CHAT_STATUS = 0x3E3, + CMSG_REPORT_PVP_AFK = 0x3E4, + CMSG_REPORT_PVP_AFK_RESULT = 0x3E5, + CMSG_GUILD_BANKER_ACTIVATE = 0x3E6, + CMSG_GUILD_BANK_QUERY_TAB = 0x3E7, + SMSG_GUILD_BANK_LIST = 0x3E8, + CMSG_GUILD_BANK_SWAP_ITEMS = 0x3E9, + CMSG_GUILD_BANK_BUY_TAB = 0x3EA, + CMSG_GUILD_BANK_UPDATE_TAB = 0x3EB, + CMSG_GUILD_BANK_DEPOSIT_MONEY = 0x3EC, + CMSG_GUILD_BANK_WITHDRAW_MONEY = 0x3ED, + MSG_GUILD_BANK_LOG_QUERY = 0x3EE, + CMSG_SET_CHANNEL_WATCH = 0x3EF, + SMSG_USERLIST_ADD = 0x3F0, + SMSG_USERLIST_REMOVE = 0x3F1, + SMSG_USERLIST_UPDATE = 0x3F2, + CMSG_CLEAR_CHANNEL_WATCH = 0x3F3, + SMSG_INSPECT_TALENT = 0x3F4, + SMSG_GOGOGO_OBSOLETE = 0x3F5, + SMSG_ECHO_PARTY_SQUELCH = 0x3F6, + CMSG_SET_TITLE_SUFFIX = 0x3F7, + CMSG_SPELLCLICK = 0x3F8, + SMSG_LOOT_LIST = 0x3F9, + CMSG_GM_CHARACTER_RESTORE = 0x3FA, + CMSG_GM_CHARACTER_SAVE = 0x3FB, + SMSG_VOICESESSION_FULL = 0x3FC, + MSG_GUILD_PERMISSIONS = 0x3FD, + MSG_GUILD_BANK_MONEY_WITHDRAWN = 0x3FE, + MSG_GUILD_EVENT_LOG_QUERY = 0x3FF, + CMSG_MAELSTROM_RENAME_GUILD = 0x400, + CMSG_GET_MIRRORIMAGE_DATA = 0x401, + SMSG_MIRRORIMAGE_DATA = 0x402, + SMSG_FORCE_DISPLAY_UPDATE = 0x403, + SMSG_SPELL_CHANCE_RESIST_PUSHBACK = 0x404, + CMSG_IGNORE_DIMINISHING_RETURNS_CHEAT = 0x405, + SMSG_IGNORE_DIMINISHING_RETURNS_CHEAT = 0x406, + CMSG_KEEP_ALIVE = 0x407, + SMSG_RAID_READY_CHECK_ERROR = 0x408, + CMSG_OPT_OUT_OF_LOOT = 0x409, + MSG_QUERY_GUILD_BANK_TEXT = 0x40A, + CMSG_SET_GUILD_BANK_TEXT = 0x40B, + CMSG_SET_GRANTABLE_LEVELS = 0x40C, + CMSG_GRANT_LEVEL = 0x40D, + CMSG_REFER_A_FRIEND = 0x40E, + MSG_GM_CHANGE_ARENA_RATING = 0x40F, + CMSG_DECLINE_CHANNEL_INVITE = 0x410, + CMSG_GROUPACTION_THROTTLED = 0x411, + SMSG_OVERRIDE_LIGHT = 0x412, + SMSG_TOTEM_CREATED = 0x413, + CMSG_TOTEM_DESTROYED = 0x414, + CMSG_EXPIRE_RAID_INSTANCE = 0x415, + CMSG_NO_SPELL_VARIANCE = 0x416, + CMSG_QUESTGIVER_STATUS_MULTIPLE_QUERY = 0x417, + SMSG_QUESTGIVER_STATUS_MULTIPLE = 0x418, + CMSG_SET_PLAYER_DECLINED_NAMES = 0x419, + SMSG_SET_PLAYER_DECLINED_NAMES_RESULT = 0x41A, + CMSG_QUERY_SERVER_BUCK_DATA = 0x41B, + CMSG_CLEAR_SERVER_BUCK_DATA = 0x41C, + SMSG_SERVER_BUCK_DATA = 0x41D, + SMSG_SEND_UNLEARN_SPELLS = 0x41E, + SMSG_PROPOSE_LEVEL_GRANT = 0x41F, + CMSG_ACCEPT_LEVEL_GRANT = 0x420, + SMSG_REFER_A_FRIEND_FAILURE = 0x421, + SMSG_SPLINE_MOVE_SET_FLYING = 0x422, + SMSG_SPLINE_MOVE_UNSET_FLYING = 0x423, + SMSG_SUMMON_CANCEL = 0x424, + CMSG_CHANGE_PERSONAL_ARENA_RATING = 0x425, + CMSG_ALTER_APPEARANCE = 0x426, + SMSG_ENABLE_BARBER_SHOP = 0x427, + SMSG_BARBER_SHOP_RESULT = 0x428, + CMSG_CALENDAR_GET_CALENDAR = 0x429, + CMSG_CALENDAR_GET_EVENT = 0x42A, + CMSG_CALENDAR_GUILD_FILTER = 0x42B, + CMSG_CALENDAR_ARENA_TEAM = 0x42C, + CMSG_CALENDAR_ADD_EVENT = 0x42D, + CMSG_CALENDAR_UPDATE_EVENT = 0x42E, + CMSG_CALENDAR_REMOVE_EVENT = 0x42F, + CMSG_CALENDAR_COPY_EVENT = 0x430, + CMSG_CALENDAR_EVENT_INVITE = 0x431, + CMSG_CALENDAR_EVENT_RSVP = 0x432, + CMSG_CALENDAR_EVENT_REMOVE_INVITE = 0x433, + CMSG_CALENDAR_EVENT_STATUS = 0x434, + CMSG_CALENDAR_EVENT_MODERATOR_STATUS = 0x435, + SMSG_CALENDAR_SEND_CALENDAR = 0x436, + SMSG_CALENDAR_SEND_EVENT = 0x437, + SMSG_CALENDAR_FILTER_GUILD = 0x438, + SMSG_CALENDAR_ARENA_TEAM = 0x439, + SMSG_CALENDAR_EVENT_INVITE = 0x43A, + SMSG_CALENDAR_EVENT_INVITE_REMOVED = 0x43B, + SMSG_CALENDAR_EVENT_STATUS = 0x43C, + SMSG_CALENDAR_COMMAND_RESULT = 0x43D, + SMSG_CALENDAR_RAID_LOCKOUT_ADDED = 0x43E, + SMSG_CALENDAR_RAID_LOCKOUT_REMOVED = 0x43F, + SMSG_CALENDAR_EVENT_INVITE_ALERT = 0x440, + SMSG_CALENDAR_EVENT_INVITE_REMOVED_ALERT = 0x441, + SMSG_CALENDAR_EVENT_INVITE_STATUS_ALERT = 0x442, + SMSG_CALENDAR_EVENT_REMOVED_ALERT = 0x443, + SMSG_CALENDAR_EVENT_UPDATED_ALERT = 0x444, + SMSG_CALENDAR_EVENT_MODERATOR_STATUS_ALERT = 0x445, + CMSG_CALENDAR_COMPLAIN = 0x446, + CMSG_CALENDAR_GET_NUM_PENDING = 0x447, + SMSG_CALENDAR_SEND_NUM_PENDING = 0x448, + CMSG_SAVE_DANCE = 0x449, + SMSG_NOTIFY_DANCE = 0x44A, + CMSG_PLAY_DANCE = 0x44B, + SMSG_PLAY_DANCE = 0x44C, + CMSG_LOAD_DANCES = 0x44D, + CMSG_STOP_DANCE = 0x44E, + SMSG_STOP_DANCE = 0x44F, + CMSG_SYNC_DANCE = 0x450, + CMSG_DANCE_QUERY = 0x451, + SMSG_DANCE_QUERY_RESPONSE = 0x452, + SMSG_INVALIDATE_DANCE = 0x453, + CMSG_DELETE_DANCE = 0x454, + SMSG_LEARNED_DANCE_MOVES = 0x455, + CMSG_LEARN_DANCE_MOVE = 0x456, + CMSG_UNLEARN_DANCE_MOVE = 0x457, + CMSG_SET_RUNE_COUNT = 0x458, + CMSG_SET_RUNE_COOLDOWN = 0x459, + MSG_MOVE_SET_PITCH_RATE_CHEAT = 0x45A, + MSG_MOVE_SET_PITCH_RATE = 0x45B, + SMSG_FORCE_PITCH_RATE_CHANGE = 0x45C, + CMSG_FORCE_PITCH_RATE_CHANGE_ACK = 0x45D, + SMSG_SPLINE_SET_PITCH_RATE = 0x45E, + SMSG_MOVE_ABANDON_TRANSPORT = 0x45F, + MSG_MOVE_ABANDON_TRANSPORT = 0x460, + CMSG_MOVE_ABANDON_TRANSPORT_ACK = 0x461, + CMSG_UPDATE_MISSILE_TRAJECTORY = 0x462, + SMSG_UPDATE_ACCOUNT_DATA_COMPLETE = 0x463, + SMSG_TRIGGER_MOVIE = 0x464, + CMSG_COMPLETE_MOVIE = 0x465, + CMSG_SET_GLYPH_SLOT = 0x466, + CMSG_SET_GLYPH = 0x467, + SMSG_ACHIEVEMENT_EARNED = 0x468, + SMSG_DYNAMIC_DROP_ROLL_RESULT = 0x469, + SMSG_CRITERIA_UPDATE = 0x46A, + CMSG_QUERY_INSPECT_ACHIEVEMENTS = 0x46B, + SMSG_RESPOND_INSPECT_ACHIEVEMENTS = 0x46C, + CMSG_DISMISS_CONTROLLED_VEHICLE = 0x46D, + CMSG_COMPLETE_ACHIEVEMENT_CHEAT = 0x46E, + SMSG_QUESTUPDATE_ADD_PVP_KILL = 0x46F, + CMSG_SET_CRITERIA_CHEAT = 0x470, + SMSG_GROUP_SWAP_FAILED = 0x471, + CMSG_UNITANIMTIER_CHEAT = 0x472, + CMSG_CHAR_CUSTOMIZE = 0x473, + SMSG_CHAR_CUSTOMIZE = 0x474, + SMSG_PET_RENAMEABLE = 0x475, + CMSG_REQUEST_VEHICLE_EXIT = 0x476, + CMSG_REQUEST_VEHICLE_PREV_SEAT = 0x477, + CMSG_REQUEST_VEHICLE_NEXT_SEAT = 0x478, + CMSG_REQUEST_VEHICLE_SWITCH_SEAT = 0x479, + CMSG_PET_LEARN_TALENT = 0x47A, + CMSG_PET_UNLEARN_TALENTS = 0x47B, + SMSG_SET_PHASE_SHIFT = 0x47C, + SMSG_ALL_ACHIEVEMENT_DATA = 0x47D, + CMSG_FORCE_SAY_CHEAT = 0x47E, + SMSG_HEALTH_UPDATE = 0x47F, + SMSG_POWER_UPDATE = 0x480, + CMSG_GAMEOBJ_REPORT_USE = 0x481, + SMSG_HIGHEST_THREAT_UPDATE = 0x482, + SMSG_THREAT_UPDATE = 0x483, + SMSG_THREAT_REMOVE = 0x484, + SMSG_THREAT_CLEAR = 0x485, + SMSG_CONVERT_RUNE = 0x486, + SMSG_RESYNC_RUNES = 0x487, + SMSG_ADD_RUNE_POWER = 0x488, + CMSG_START_QUEST = 0x489, + CMSG_REMOVE_GLYPH = 0x48A, + CMSG_DUMP_OBJECTS = 0x48B, + SMSG_DUMP_OBJECTS_DATA = 0x48C, + CMSG_DISMISS_CRITTER = 0x48D, + SMSG_NOTIFY_DEST_LOC_SPELL_CAST = 0x48E, + CMSG_AUCTION_LIST_PENDING_SALES = 0x48F, + SMSG_AUCTION_LIST_PENDING_SALES = 0x490, + SMSG_MODIFY_COOLDOWN = 0x491, + SMSG_PET_UPDATE_COMBO_POINTS = 0x492, + CMSG_ENABLETAXI = 0x493, + SMSG_PRE_RESURRECT = 0x494, + SMSG_AURA_UPDATE_ALL = 0x495, + SMSG_AURA_UPDATE = 0x496, + CMSG_FLOOD_GRACE_CHEAT = 0x497, + SMSG_SERVER_FIRST_ACHIEVEMENT = 0x498, + SMSG_PET_LEARNED_SPELL = 0x499, + SMSG_PET_REMOVED_SPELL = 0x49A, + CMSG_CHANGE_SEATS_ON_CONTROLLED_VEHICLE = 0x49B, + CMSG_HEARTH_AND_RESURRECT = 0x49C, + SMSG_ON_CANCEL_EXPECTED_RIDE_VEHICLE_AURA = 0x49D, + SMSG_CRITERIA_DELETED = 0x49E, + SMSG_ACHIEVEMENT_DELETED = 0x49F, + CMSG_SERVER_INFO_QUERY = 0x4A0, + SMSG_SERVER_INFO_RESPONSE = 0x4A1, + CMSG_CHECK_LOGIN_CRITERIA = 0x4A2, + SMSG_SERVER_BUCK_DATA_START = 0x4A3, + CMSG_QUERY_VEHICLE_STATUS = 0x4A4, + SMSG_PET_GUIDS = 0x4A5, + NUM_MSG_TYPES = 0x4A6 }; -// Don't forget to change this value and add opcode name to Opcodes.cpp when you add new opcode! -#define NUM_MSG_TYPES 0x424 - /// Player state enum SessionStatus { @@ -1102,7 +1236,6 @@ enum SessionStatus STATUS_NEVER ///< Opcode not accepted from client (deprecated or server side only) }; -class WorldSession; class WorldPacket; struct OpcodeHandler diff --git a/src/game/Pet.cpp b/src/game/Pet.cpp index 04cc6de0b..be46cc21a 100644 --- a/src/game/Pet.cpp +++ b/src/game/Pet.cpp @@ -39,27 +39,6 @@ char const* petTypeSuffix[MAX_PET_TYPE] = "'s Companion" // MINI_PET }; -//numbers represent minutes * 100 while happy (you get 100 loyalty points per min while happy) -uint32 const LevelUpLoyalty[6] = -{ - 5500, - 11500, - 17000, - 23500, - 31000, - 39500, -}; - -uint32 const LevelStartLoyalty[6] = -{ - 2000, - 4500, - 7000, - 10000, - 13500, - 17500, -}; - Pet::Pet(PetType type) : Creature() { m_isPet = true; @@ -69,17 +48,16 @@ Pet::Pet(PetType type) : Creature() m_removed = false; m_regenTimer = 4000; m_happinessTimer = 7500; - m_loyaltyTimer = 12000; m_duration = 0; m_bonusdamage = 0; - m_loyaltyPoints = 0; - m_TrainingPoints = 0; m_resetTalentsCost = 0; m_resetTalentsTime = 0; m_auraUpdateMask = 0; + m_loading = false; + // pets always have a charminfo, even if they are not actually charmed CharmInfo* charmInfo = InitCharmInfo(this); @@ -125,24 +103,26 @@ void Pet::RemoveFromWorld() bool Pet::LoadPetFromDB( Unit* owner, uint32 petentry, uint32 petnumber, bool current ) { + m_loading = true; + uint32 ownerid = owner->GetGUIDLow(); QueryResult *result; if(petnumber) - // known petnumber entry 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 - result = CharacterDatabase.PQuery("SELECT id, entry, owner, modelid, level, exp, Reactstate, loyaltypoints, loyalty, trainpoint, slot, name, renamed, curhealth, curmana, curhappiness, abdata, TeachSpelldata, savetime, resettalents_cost, resettalents_time, CreatedBySpell, PetType FROM character_pet WHERE owner = '%u' AND id = '%u'",ownerid, petnumber); + // known petnumber entry 0 1 2(?) 3 4 5 6 7 8(?) 9 10 11 12 13 14 15 16 17 18 19 20 + result = CharacterDatabase.PQuery("SELECT id, entry, owner, modelid, level, exp, Reactstate, talentpoints, slot, name, renamed, curhealth, curmana, curhappiness, abdata, TeachSpelldata, savetime, resettalents_cost, resettalents_time, CreatedBySpell, PetType FROM character_pet WHERE owner = '%u' AND id = '%u'",ownerid, petnumber); else if(current) - // current pet (slot 0) 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 - result = CharacterDatabase.PQuery("SELECT id, entry, owner, modelid, level, exp, Reactstate, loyaltypoints, loyalty, trainpoint, slot, name, renamed, curhealth, curmana, curhappiness, abdata, TeachSpelldata, savetime, resettalents_cost, resettalents_time, CreatedBySpell, PetType FROM character_pet WHERE owner = '%u' AND slot = '0'",ownerid ); + // current pet (slot 0) 0 1 2(?) 3 4 5 6 7 8(?) 9 10 11 12 13 14 15 16 17 18 19 20 + result = CharacterDatabase.PQuery("SELECT id, entry, owner, modelid, level, exp, Reactstate, talentpoints, slot, name, renamed, curhealth, curmana, curhappiness, abdata, TeachSpelldata, savetime, resettalents_cost, resettalents_time, CreatedBySpell, PetType FROM character_pet WHERE owner = '%u' AND slot = '0'",ownerid ); else if(petentry) // known petentry entry (unique for summoned pet, but non unique for hunter pet (only from current or not stabled pets) - // 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 - result = CharacterDatabase.PQuery("SELECT id, entry, owner, modelid, level, exp, Reactstate, loyaltypoints, loyalty, trainpoint, slot, name, renamed, curhealth, curmana, curhappiness, abdata, TeachSpelldata, savetime, resettalents_cost, resettalents_time, CreatedBySpell, PetType FROM character_pet WHERE owner = '%u' AND entry = '%u' AND (slot = '0' OR slot = '3') ",ownerid, petentry ); + // 0 1 2(?) 3 4 5 6 7 8(?) 9 10 11 12 13 14 15 16 17 18 19 20 + result = CharacterDatabase.PQuery("SELECT id, entry, owner, modelid, level, exp, Reactstate, talentpoints, slot, name, renamed, curhealth, curmana, curhappiness, abdata, TeachSpelldata, savetime, resettalents_cost, resettalents_time, CreatedBySpell, PetType FROM character_pet WHERE owner = '%u' AND entry = '%u' AND (slot = '0' OR slot = '3') ",ownerid, petentry ); else // any current or other non-stabled pet (for hunter "call pet") - // 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 - result = CharacterDatabase.PQuery("SELECT id, entry, owner, modelid, level, exp, Reactstate, loyaltypoints, loyalty, trainpoint, slot, name, renamed, curhealth, curmana, curhappiness, abdata, TeachSpelldata, savetime, resettalents_cost, resettalents_time, CreatedBySpell, PetType FROM character_pet WHERE owner = '%u' AND (slot = '0' OR slot = '3') ",ownerid); + // 0 1 2(?) 3 4 5 6 7 8(?) 9 10 11 12 13 14 15 16 17 18 19 20 + result = CharacterDatabase.PQuery("SELECT id, entry, owner, modelid, level, exp, Reactstate, talentpoints, slot, name, renamed, curhealth, curmana, curhappiness, abdata, TeachSpelldata, savetime, resettalents_cost, resettalents_time, CreatedBySpell, PetType FROM character_pet WHERE owner = '%u' AND (slot = '0' OR slot = '3') ",ownerid); if(!result) return false; @@ -157,7 +137,7 @@ bool Pet::LoadPetFromDB( Unit* owner, uint32 petentry, uint32 petnumber, bool cu return false; } - uint32 summon_spell_id = fields[21].GetUInt32(); + uint32 summon_spell_id = fields[19].GetUInt32(); SpellEntry const* spellInfo = sSpellStore.LookupEntry(summon_spell_id); bool is_temporary_summoned = spellInfo && GetSpellDuration(spellInfo) > 0; @@ -191,8 +171,8 @@ bool Pet::LoadPetFromDB( Unit* owner, uint32 petentry, uint32 petnumber, bool cu return false; } - setPetType(PetType(fields[22].GetUInt8())); - SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE,owner->getFaction()); + setPetType(PetType(fields[20].GetUInt8())); + SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE, owner->getFaction()); SetUInt32Value(UNIT_CREATED_BY_SPELL, summon_spell_id); CreatureInfo const *cinfo = GetCreatureInfo(); @@ -203,72 +183,67 @@ bool Pet::LoadPetFromDB( Unit* owner, uint32 petentry, uint32 petnumber, bool cu delete result; return true; } - if(getPetType()==HUNTER_PET || (getPetType()==SUMMON_PET && cinfo->type == CREATURE_TYPE_DEMON && owner->getClass() == CLASS_WARLOCK)) + + if(getPetType() == HUNTER_PET || (getPetType() == SUMMON_PET && cinfo->type == CREATURE_TYPE_DEMON && owner->getClass() == CLASS_WARLOCK)) m_charmInfo->SetPetNumber(pet_number, true); else m_charmInfo->SetPetNumber(pet_number, false); - SetUInt64Value(UNIT_FIELD_SUMMONEDBY, owner->GetGUID()); + + SetOwnerGUID(owner->GetGUID()); SetDisplayId(fields[3].GetUInt32()); SetNativeDisplayId(fields[3].GetUInt32()); - uint32 petlevel=fields[4].GetUInt32(); - SetUInt32Value(UNIT_NPC_FLAGS , 0); - SetName(fields[11].GetString()); + uint32 petlevel = fields[4].GetUInt32(); + SetUInt32Value(UNIT_NPC_FLAGS, 0); + SetName(fields[9].GetString()); switch(getPetType()) { - case SUMMON_PET: petlevel=owner->getLevel(); - SetUInt32Value(UNIT_FIELD_BYTES_0,2048); + SetUInt32Value(UNIT_FIELD_BYTES_0, 2048); SetUInt32Value(UNIT_FIELD_FLAGS, UNIT_FLAG_PVP_ATTACKABLE); // this enables popup window (pet dismiss, cancel) break; case HUNTER_PET: SetUInt32Value(UNIT_FIELD_BYTES_0, 0x02020100); - SetByteValue(UNIT_FIELD_BYTES_1, 1, fields[8].GetUInt32()); - SetByteValue(UNIT_FIELD_BYTES_2, 0, SHEATH_STATE_MELEE ); - SetByteValue(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_UNK3 | UNIT_BYTE2_FLAG_AURAS | UNIT_BYTE2_FLAG_UNK5 ); - - if(fields[12].GetBool()) - SetByteValue(UNIT_FIELD_BYTES_2, 2, UNIT_RENAME_NOT_ALLOWED); - else - SetByteValue(UNIT_FIELD_BYTES_2, 2, UNIT_RENAME_ALLOWED); + SetByteValue(UNIT_FIELD_BYTES_1, 1, fields[7].GetUInt32()); + SetByteValue(UNIT_FIELD_BYTES_2, 0, SHEATH_STATE_MELEE); + SetByteValue(UNIT_FIELD_BYTES_2, 2, fields[10].GetBool() ? UNIT_RENAME_NOT_ALLOWED : UNIT_RENAME_ALLOWED); SetUInt32Value(UNIT_FIELD_FLAGS, UNIT_FLAG_PVP_ATTACKABLE); // this enables popup window (pet abandon, cancel) - SetTP(fields[9].GetInt32()); - SetMaxPower(POWER_HAPPINESS,GetCreatePowers(POWER_HAPPINESS)); - SetPower( POWER_HAPPINESS,fields[15].GetUInt32()); + SetMaxPower(POWER_HAPPINESS, GetCreatePowers(POWER_HAPPINESS)); + SetPower(POWER_HAPPINESS, fields[13].GetUInt32()); setPowerType(POWER_FOCUS); break; default: - sLog.outError("Pet have incorrect type (%u) for pet loading.",getPetType()); + sLog.outError("Pet have incorrect type (%u) for pet loading.", getPetType()); } - InitStatsForLevel( petlevel); + + InitStatsForLevel(petlevel); SetUInt32Value(UNIT_FIELD_PET_NAME_TIMESTAMP, time(NULL)); SetUInt32Value(UNIT_FIELD_PETEXPERIENCE, fields[5].GetUInt32()); - SetUInt64Value(UNIT_FIELD_CREATEDBY, owner->GetGUID()); + SetCreatorGUID(owner->GetGUID()); - m_charmInfo->SetReactState( ReactStates( fields[6].GetUInt8() )); - m_loyaltyPoints = fields[7].GetInt32(); + m_charmInfo->SetReactState(ReactStates(fields[6].GetUInt8())); - uint32 savedhealth = fields[13].GetUInt32(); - uint32 savedmana = fields[14].GetUInt32(); + uint32 savedhealth = fields[11].GetUInt32(); + uint32 savedmana = fields[12].GetUInt32(); // set current pet as current - if(fields[10].GetUInt32() != 0) + if(fields[8].GetUInt32() != 0) { CharacterDatabase.BeginTransaction(); - CharacterDatabase.PExecute("UPDATE character_pet SET slot = '3' WHERE owner = '%u' AND slot = '0' AND id <> '%u'",ownerid, m_charmInfo->GetPetNumber()); - CharacterDatabase.PExecute("UPDATE character_pet SET slot = '0' WHERE owner = '%u' AND id = '%u'",ownerid, m_charmInfo->GetPetNumber()); + CharacterDatabase.PExecute("UPDATE character_pet SET slot = '3' WHERE owner = '%u' AND slot = '0' AND id <> '%u'", ownerid, m_charmInfo->GetPetNumber()); + CharacterDatabase.PExecute("UPDATE character_pet SET slot = '0' WHERE owner = '%u' AND id = '%u'", ownerid, m_charmInfo->GetPetNumber()); CharacterDatabase.CommitTransaction(); } if(!is_temporary_summoned) { // permanent controlled pets store state in DB - Tokens tokens = StrSplit(fields[16].GetString(), " "); + Tokens tokens = StrSplit(fields[14].GetString(), " "); if(tokens.size() != 20) { @@ -286,7 +261,7 @@ bool Pet::LoadPetFromDB( Unit* owner, uint32 petentry, uint32 petnumber, bool cu } //init teach spells - tokens = StrSplit(fields[17].GetString(), " "); + tokens = StrSplit(fields[15].GetString(), " "); for (iter = tokens.begin(), index = 0; index < 4; ++iter, ++index) { uint32 tmp = atol((*iter).c_str()); @@ -301,7 +276,10 @@ bool Pet::LoadPetFromDB( Unit* owner, uint32 petentry, uint32 petnumber, bool cu } // since last save (in seconds) - uint32 timediff = (time(NULL) - fields[18].GetUInt32()); + uint32 timediff = (time(NULL) - fields[16].GetUInt32()); + + m_resetTalentsCost = fields[17].GetUInt32(); + m_resetTalentsTime = fields[18].GetUInt64(); delete result; @@ -367,6 +345,7 @@ bool Pet::LoadPetFromDB( Unit* owner, uint32 petentry, uint32 petnumber, bool cu } } + m_loading = false; return true; } @@ -409,10 +388,6 @@ void Pet::SavePetToDB(PetSaveMode mode) case PET_SAVE_IN_STABLE_SLOT_2: case PET_SAVE_NOT_IN_SLOT: { - uint32 loyalty =1; - if(getPetType()!=HUNTER_PET) - loyalty = GetLoyaltyLevel(); - uint32 owner = GUID_LOPART(GetOwnerGUID()); std::string name = m_name; CharacterDatabase.escape_string(name); @@ -429,7 +404,7 @@ void Pet::SavePetToDB(PetSaveMode mode) CharacterDatabase.PExecute("DELETE FROM character_pet WHERE owner = '%u' AND (slot = '0' OR slot = '3')", owner ); // save pet std::ostringstream ss; - ss << "INSERT INTO character_pet ( id, entry, owner, modelid, level, exp, Reactstate, loyaltypoints, loyalty, trainpoint, slot, name, renamed, curhealth, curmana, curhappiness, abdata,TeachSpelldata,savetime,resettalents_cost,resettalents_time,CreatedBySpell,PetType) " + ss << "INSERT INTO character_pet ( id, entry, owner, modelid, level, exp, Reactstate, talentpoints, slot, name, renamed, curhealth, curmana, curhappiness, abdata, TeachSpelldata, savetime, resettalents_cost, resettalents_time, CreatedBySpell, PetType) " << "VALUES (" << m_charmInfo->GetPetNumber() << ", " << GetEntry() << ", " @@ -438,9 +413,7 @@ void Pet::SavePetToDB(PetSaveMode mode) << getLevel() << ", " << GetUInt32Value(UNIT_FIELD_PETEXPERIENCE) << ", " << uint32(m_charmInfo->GetReactState()) << ", " - << m_loyaltyPoints << ", " - << GetLoyaltyLevel() << ", " - << m_TrainingPoints << ", " + << uint32(GetFreeTalentPoints()) << ", " << uint32(mode) << ", '" << name.c_str() << "', " << uint32((GetByteValue(UNIT_FIELD_BYTES_2, 2) == UNIT_RENAME_ALLOWED)?0:1) << ", " @@ -513,12 +486,12 @@ void Pet::setDeathState(DeathState s) // overwrite virtual if(!mapEntry || (mapEntry->map_type != MAP_ARENA && mapEntry->map_type != MAP_BATTLEGROUND)) ModifyPower(POWER_HAPPINESS, -HAPPINESS_LEVEL_SIZE); - SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_ROTATE); + SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_STUNNED); } } else if(getDeathState()==ALIVE) { - RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_ROTATE); + RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_STUNNED); CastPetAuras(true); } } @@ -544,7 +517,7 @@ void Pet::Update(uint32 diff) { // unsummon pet that lost owner Unit* owner = GetOwner(); - if(!owner || !IsWithinDistInMap(owner, OWNER_MAX_DISTANCE) || isControlled() && !owner->GetPetGUID()) + if(!owner || (!IsWithinDistInMap(owner, OWNER_MAX_DISTANCE) && (owner->GetCharmGUID() && (owner->GetCharmGUID() != GetGUID()))) || (isControlled() && !owner->GetPetGUID())) { Remove(PET_SAVE_NOT_IN_SLOT, true); return; @@ -590,14 +563,6 @@ void Pet::Update(uint32 diff) else m_happinessTimer -= diff; - if(m_loyaltyTimer <= diff) - { - TickLoyaltyChange(); - m_loyaltyTimer = 12000; - } - else - m_loyaltyTimer -= diff; - break; } default: @@ -629,83 +594,12 @@ void Pet::LooseHappiness() uint32 curValue = GetPower(POWER_HAPPINESS); if (curValue <= 0) return; - int32 addvalue = (140 >> GetLoyaltyLevel()) * 125; //value is 70/35/17/8/4 (per min) * 1000 / 8 (timer 7.5 secs) + int32 addvalue = 670; //value is 70/35/17/8/4 (per min) * 1000 / 8 (timer 7.5 secs) if(isInCombat()) //we know in combat happiness fades faster, multiplier guess addvalue = int32(addvalue * 1.5); ModifyPower(POWER_HAPPINESS, -addvalue); } -void Pet::ModifyLoyalty(int32 addvalue) -{ - uint32 loyaltylevel = GetLoyaltyLevel(); - - if(addvalue > 0) //only gain influenced, not loss - addvalue = int32((float)addvalue * sWorld.getRate(RATE_LOYALTY)); - - if(loyaltylevel >= BEST_FRIEND && (addvalue + m_loyaltyPoints) > int32(GetMaxLoyaltyPoints(loyaltylevel))) - return; - - m_loyaltyPoints += addvalue; - - if(m_loyaltyPoints < 0) - { - if(loyaltylevel > REBELLIOUS) - { - //level down - --loyaltylevel; - SetLoyaltyLevel(LoyaltyLevel(loyaltylevel)); - m_loyaltyPoints = GetStartLoyaltyPoints(loyaltylevel); - SetTP(m_TrainingPoints - int32(getLevel())); - } - else - { - m_loyaltyPoints = 0; - Unit* owner = GetOwner(); - if(owner && owner->GetTypeId() == TYPEID_PLAYER) - { - WorldPacket data(SMSG_PET_BROKEN, 0); - ((Player*)owner)->GetSession()->SendPacket(&data); - - //run away - ((Player*)owner)->RemovePet(this,PET_SAVE_AS_DELETED); - } - } - } - //level up - else if(m_loyaltyPoints > int32(GetMaxLoyaltyPoints(loyaltylevel))) - { - ++loyaltylevel; - SetLoyaltyLevel(LoyaltyLevel(loyaltylevel)); - m_loyaltyPoints = GetStartLoyaltyPoints(loyaltylevel); - SetTP(m_TrainingPoints + getLevel()); - } -} - -void Pet::TickLoyaltyChange() -{ - int32 addvalue; - - switch(GetHappinessState()) - { - case HAPPY: addvalue = 20; break; - case CONTENT: addvalue = 10; break; - case UNHAPPY: addvalue = -20; break; - default: - return; - } - ModifyLoyalty(addvalue); -} - -void Pet::KillLoyaltyBonus(uint32 level) -{ - if(level > 100) - return; - - //at lower levels gain is faster | the lower loyalty the more loyalty is gained - uint32 bonus = uint32(((100 - level) / 10) + (6 - GetLoyaltyLevel())); - ModifyLoyalty(bonus); -} - HappinessState Pet::GetHappinessState() { if(GetPower(POWER_HAPPINESS) < HAPPINESS_LEVEL_SIZE) @@ -716,11 +610,6 @@ HappinessState Pet::GetHappinessState() return CONTENT; } -void Pet::SetLoyaltyLevel(LoyaltyLevel level) -{ - SetByteValue(UNIT_FIELD_BYTES_1, 1, level); -} - bool Pet::CanTakeMoreActiveSpells(uint32 spellid) { uint8 activecount = 1; @@ -757,82 +646,6 @@ bool Pet::CanTakeMoreActiveSpells(uint32 spellid) return true; } -bool Pet::HasTPForSpell(uint32 spellid) -{ - int32 neededtrainp = GetTPForSpell(spellid); - if((m_TrainingPoints - neededtrainp < 0 || neededtrainp < 0) && neededtrainp != 0) - return false; - return true; -} - -int32 Pet::GetTPForSpell(uint32 spellid) -{ - uint32 basetrainp = 0; - - SkillLineAbilityMap::const_iterator lower = spellmgr.GetBeginSkillLineAbilityMap(spellid); - SkillLineAbilityMap::const_iterator upper = spellmgr.GetEndSkillLineAbilityMap(spellid); - for(SkillLineAbilityMap::const_iterator _spell_idx = lower; _spell_idx != upper; ++_spell_idx) - { - if(!_spell_idx->second->reqtrainpoints) - return 0; - - basetrainp = _spell_idx->second->reqtrainpoints; - break; - } - - uint32 spenttrainp = 0; - uint32 chainstart = spellmgr.GetFirstSpellInChain(spellid); - - for (PetSpellMap::iterator itr = m_spells.begin(); itr != m_spells.end(); ++itr) - { - if(itr->second->state == PETSPELL_REMOVED) - continue; - - if(spellmgr.GetFirstSpellInChain(itr->first) == chainstart) - { - SkillLineAbilityMap::const_iterator _lower = spellmgr.GetBeginSkillLineAbilityMap(itr->first); - SkillLineAbilityMap::const_iterator _upper = spellmgr.GetEndSkillLineAbilityMap(itr->first); - - for(SkillLineAbilityMap::const_iterator _spell_idx2 = _lower; _spell_idx2 != _upper; ++_spell_idx2) - { - if(_spell_idx2->second->reqtrainpoints > spenttrainp) - { - spenttrainp = _spell_idx2->second->reqtrainpoints; - break; - } - } - } - } - - return int32(basetrainp) - int32(spenttrainp); -} - -uint32 Pet::GetMaxLoyaltyPoints(uint32 level) -{ - return LevelUpLoyalty[level - 1]; -} - -uint32 Pet::GetStartLoyaltyPoints(uint32 level) -{ - return LevelStartLoyalty[level - 1]; -} - -void Pet::SetTP(int32 TP) -{ - m_TrainingPoints = TP; - SetUInt32Value(UNIT_TRAINING_POINTS, (uint32)GetDispTP()); -} - -int32 Pet::GetDispTP() -{ - if(getPetType()!= HUNTER_PET) - return(0); - if(m_TrainingPoints < 0) - return -m_TrainingPoints; - else - return -(m_TrainingPoints + 1); -} - void Pet::Remove(PetSaveMode mode, bool returnreagent) { Unit* owner = GetOwner(); @@ -895,9 +708,6 @@ void Pet::GivePetXP(uint32 xp) } SetUInt32Value(UNIT_FIELD_PETEXPERIENCE, newXP); - - if(getPetType() == HUNTER_PET) - KillLoyaltyBonus(level); } void Pet::GivePetLevel(uint32 level) @@ -905,9 +715,7 @@ void Pet::GivePetLevel(uint32 level) if(!level) return; - InitStatsForLevel( level); - - SetTP(m_TrainingPoints + (GetLoyaltyLevel() - 1)); + InitStatsForLevel(level); } bool Pet::CreateBaseAtCreature(Creature* creature) @@ -965,16 +773,12 @@ bool Pet::CreateBaseAtCreature(Creature* creature) else SetName(creature->GetName()); - m_loyaltyPoints = 1000; if(cinfo->type == CREATURE_TYPE_BEAST) { SetUInt32Value(UNIT_FIELD_BYTES_0, 0x02020100); SetByteValue(UNIT_FIELD_BYTES_2, 0, SHEATH_STATE_MELEE ); - SetByteValue(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_UNK3 | UNIT_BYTE2_FLAG_AURAS | UNIT_BYTE2_FLAG_UNK5 ); SetByteValue(UNIT_FIELD_BYTES_2, 2, UNIT_RENAME_ALLOWED); - - SetUInt32Value(UNIT_MOD_CAST_SPEED, creature->GetUInt32Value(UNIT_MOD_CAST_SPEED) ); - SetLoyaltyLevel(REBELLIOUS); + SetUInt32Value(UNIT_MOD_CAST_SPEED, creature->GetUInt32Value(UNIT_MOD_CAST_SPEED)); } return true; } @@ -1104,7 +908,7 @@ bool Pet::InitStatsForLevel(uint32 petlevel) case HUNTER_PET: { SetUInt32Value(UNIT_FIELD_PETNEXTLEVELEXP, uint32((MaNGOS::XP::xp_to_level(petlevel))/4)); - + learnLevelupSpells(); //these formula may not be correct; however, it is designed to be close to what it should be //this makes dps 0.5 of pets level SetBaseWeaponDamage(BASE_ATTACK, MINDAMAGE, float(petlevel - (petlevel / 4)) ); @@ -1315,10 +1119,6 @@ void Pet::_LoadAuras(uint32 timediff) for (int i = 0; i < TOTAL_AURAS; i++) m_modAuras[i].clear(); - // all aura related fields - for(int i = UNIT_FIELD_AURA; i <= UNIT_FIELD_AURASTATE; ++i) - SetUInt32Value(i, 0); - QueryResult *result = CharacterDatabase.PQuery("SELECT caster_guid,spell,effect_index,stackcount,amount,maxduration,remaintime,remaincharges FROM pet_aura WHERE guid = '%u'",m_charmInfo->GetPetNumber()); if(result) @@ -1507,11 +1307,12 @@ bool Pet::addSpell(uint16 spell_id, uint16 active, PetSpellState state, uint16 s ToggleAutocast(itr->first, false); oldspell_id = itr->first; - removeSpell(itr->first); + unlearnSpell(itr->first); + break; } } - uint16 tmpslot=slot_id; + uint16 tmpslot = slot_id; if (tmpslot == 0xffff) { @@ -1545,20 +1346,65 @@ bool Pet::learnSpell(uint16 spell_id) if (!addSpell(spell_id)) return false; + if(GetOwner()->GetTypeId() == TYPEID_PLAYER) + { + if(!m_loading) + { + WorldPacket data(SMSG_PET_LEARNED_SPELL, 2); + data << uint16(spell_id); + ((Player*)GetOwner())->GetSession()->SendPacket(&data); + } + } + Unit* owner = GetOwner(); - if(owner->GetTypeId()==TYPEID_PLAYER) + if(owner->GetTypeId() == TYPEID_PLAYER) ((Player*)owner)->PetSpellInitialize(); return true; } -void Pet::removeSpell(uint16 spell_id) +void Pet::learnLevelupSpells() +{ + PetLevelupSpellSet const *levelupSpells = spellmgr.GetPetLevelupSpellList(GetCreatureInfo()->family); + if(!levelupSpells) + return; + + uint32 level = getLevel(); + + for(PetLevelupSpellSet::const_iterator itr = levelupSpells->begin(); itr != levelupSpells->end(); ++itr) + { + if(itr->first <= level) + learnSpell(itr->second); + else + unlearnSpell(itr->second); + } +} + +bool Pet::unlearnSpell(uint16 spell_id) +{ + if(removeSpell(spell_id)) + { + if(GetOwner()->GetTypeId() == TYPEID_PLAYER) + { + if(!m_loading) + { + WorldPacket data(SMSG_PET_REMOVED_SPELL, 2); + data << uint16(spell_id); + ((Player*)GetOwner())->GetSession()->SendPacket(&data); + } + } + return true; + } + return false; +} + +bool Pet::removeSpell(uint16 spell_id) { PetSpellMap::iterator itr = m_spells.find(spell_id); if (itr == m_spells.end()) - return; + return false; if(itr->second->state == PETSPELL_REMOVED) - return; + return false; if(itr->second->state == PETSPELL_NEW) { @@ -1569,6 +1415,8 @@ void Pet::removeSpell(uint16 spell_id) itr->second->state = PETSPELL_REMOVED; RemoveAurasDueToSpell(spell_id); + + return true; } bool Pet::_removeSpell(uint16 spell_id) @@ -1588,7 +1436,7 @@ void Pet::InitPetCreateSpells() m_charmInfo->InitPetActionBar(); m_spells.clear(); - int32 usedtrainpoints = 0, petspellid; + int32 petspellid; PetCreateSpellEntry const* CreateSpells = objmgr.GetPetCreateSpellEntry(GetEntry()); if(CreateSpells) { @@ -1617,23 +1465,12 @@ void Pet::InitPetCreateSpells() petspellid = learn_spellproto->Id; addSpell(petspellid); - - SkillLineAbilityMap::const_iterator lower = spellmgr.GetBeginSkillLineAbilityMap(learn_spellproto->EffectTriggerSpell[0]); - SkillLineAbilityMap::const_iterator upper = spellmgr.GetEndSkillLineAbilityMap(learn_spellproto->EffectTriggerSpell[0]); - - for(SkillLineAbilityMap::const_iterator _spell_idx = lower; _spell_idx != upper; ++_spell_idx) - { - usedtrainpoints += _spell_idx->second->reqtrainpoints; - break; - } } } LearnPetPassives(); CastPetAuras(false); - - SetTP(-usedtrainpoints); } void Pet::CheckLearning(uint32 spellid) @@ -1687,7 +1524,9 @@ void Pet::ToggleAutocast(uint32 spellid, bool apply) if(apply) { - for (i = 0; i < m_autospells.size() && m_autospells[i] != spellid; i++); + for (i = 0; i < m_autospells.size() && m_autospells[i] != spellid; i++) + ; // just search + if (i == m_autospells.size()) { m_autospells.push_back(spellid); @@ -1698,7 +1537,9 @@ void Pet::ToggleAutocast(uint32 spellid, bool apply) else { AutoSpellList::iterator itr2 = m_autospells.begin(); - for (i = 0; i < m_autospells.size() && m_autospells[i] != spellid; i++, itr2++); + for (i = 0; i < m_autospells.size() && m_autospells[i] != spellid; i++, itr2++) + ; // just search + if (i < m_autospells.size()) { m_autospells.erase(itr2); @@ -1721,8 +1562,7 @@ bool Pet::Create(uint32 guidlow, Map *map, uint32 Entry, uint32 pet_number) if(!InitEntry(Entry)) return false; - SetByteValue(UNIT_FIELD_BYTES_2, 0, SHEATH_STATE_MELEE ); - SetByteValue(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_UNK3 | UNIT_BYTE2_FLAG_AURAS | UNIT_BYTE2_FLAG_UNK5 ); + SetByteValue(UNIT_FIELD_BYTES_2, 0, SHEATH_STATE_MELEE); if(getPetType() == MINI_PET) // always non-attackable SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); diff --git a/src/game/Pet.h b/src/game/Pet.h index 0a8f46767..29c96dcc1 100644 --- a/src/game/Pet.h +++ b/src/game/Pet.h @@ -50,16 +50,6 @@ enum HappinessState HAPPY = 3 }; -enum LoyaltyLevel -{ - REBELLIOUS = 1, - UNRULY = 2, - SUBMISSIVE = 3, - DEPENDABLE = 4, - FAITHFUL = 5, - BEST_FRIEND = 6 -}; - enum PetSpellState { PETSPELL_UNCHANGED = 0, @@ -120,9 +110,6 @@ typedef std::vector AutoSpellList; #define HAPPINESS_LEVEL_SIZE 333000 -extern const uint32 LevelUpLoyalty[6]; -extern const uint32 LevelStartLoyalty[6]; - #define ACTIVE_SPELLS_MAX 4 #define OWNER_MAX_DISTANCE 100 @@ -165,14 +152,7 @@ class Pet : public Creature void RegenerateFocus(); void LooseHappiness(); - void TickLoyaltyChange(); - void ModifyLoyalty(int32 addvalue); HappinessState GetHappinessState(); - uint32 GetMaxLoyaltyPoints(uint32 level); - uint32 GetStartLoyaltyPoints(uint32 level); - void KillLoyaltyBonus(uint32 level); - uint32 GetLoyaltyLevel() { return GetByteValue(UNIT_FIELD_BYTES_1, 1); } - void SetLoyaltyLevel(LoyaltyLevel level); void GivePetXP(uint32 xp); void GivePetLevel(uint32 level); bool InitStatsForLevel(uint32 level); @@ -192,10 +172,8 @@ class Pet : public Creature void UpdateAttackPowerAndDamage(bool ranged = false); void UpdateDamagePhysical(WeaponAttackType attType); - bool CanTakeMoreActiveSpells(uint32 SpellIconID); - void ToggleAutocast(uint32 spellid, bool apply); - bool HasTPForSpell(uint32 spellid); - int32 GetTPForSpell(uint32 spellid); + bool CanTakeMoreActiveSpells(uint32 SpellIconID); + void ToggleAutocast(uint32 spellid, bool apply); bool HasSpell(uint32 spell) const; void AddTeachSpell(uint32 learned_id, uint32 source_id) { m_teachspells[learned_id] = source_id; } @@ -213,7 +191,9 @@ class Pet : public Creature bool addSpell(uint16 spell_id,uint16 active = ACT_DECIDE, PetSpellState state = PETSPELL_NEW, uint16 slot_id=0xffff, PetSpellType type = PETSPELL_NORMAL); bool learnSpell(uint16 spell_id); - void removeSpell(uint16 spell_id); + void learnLevelupSpells(); + bool unlearnSpell(uint16 spell_id); + bool removeSpell(uint16 spell_id); bool _removeSpell(uint16 spell_id); PetSpellMap m_spells; @@ -223,11 +203,10 @@ class Pet : public Creature void InitPetCreateSpells(); void CheckLearning(uint32 spellid); uint32 resetTalentsCost() const; + uint8 GetMaxTalentPointsForLevel(uint32 level) { return (level >= 20) ? ((level - 16) / 4) : 0; } + uint8 GetFreeTalentPoints() { return GetByteValue(UNIT_FIELD_BYTES_1, 1); } + void SetFreeTalentPoints(uint8 points) { SetByteValue(UNIT_FIELD_BYTES_1, 1, points); } - void SetTP(int32 TP); - int32 GetDispTP(); - - int32 m_TrainingPoints; uint32 m_resetTalentsCost; time_t m_resetTalentsTime; @@ -242,14 +221,12 @@ class Pet : public Creature bool m_removed; // prevent overwrite pet state in DB at next Pet::Update if pet already removed(saved) protected: - uint32 m_regenTimer; uint32 m_happinessTimer; - uint32 m_loyaltyTimer; PetType m_petType; int32 m_duration; // time until unsummon (used mostly for summoned guardians and not used for controlled pets) - int32 m_loyaltyPoints; int32 m_bonusdamage; uint64 m_auraUpdateMask; + bool m_loading; DeclinedName *m_declinedname; diff --git a/src/game/PetHandler.cpp b/src/game/PetHandler.cpp index eb51544d3..1a34358f0 100644 --- a/src/game/PetHandler.cpp +++ b/src/game/PetHandler.cpp @@ -157,9 +157,9 @@ void WorldSession::HandlePetAction( WorldPacket & recv_data ) break; } break; - case ACT_DISABLED: //0x8100 spell (disabled), ignore - case ACT_CAST: //0x0100 - case ACT_ENABLED: //0xc100 spell + case ACT_DISABLED: // 0x8100 spell (disabled), ignore + case ACT_PASSIVE: // 0x0100 + case ACT_ENABLED: // 0xC100 spell { Unit* unit_target; if(guid2) @@ -240,7 +240,7 @@ void WorldSession::HandlePetAction( WorldPacket & recv_data ) if(pet->HasAuraType(SPELL_AURA_MOD_POSSESS)) { WorldPacket data(SMSG_CAST_FAILED, (4+1+1)); - data << uint32(spellid) << uint8(2) << uint8(result); + data << uint8(0) << uint32(spellid) << uint8(result); switch (result) { case SPELL_FAILED_REQUIRES_SPELL_FOCUS: @@ -352,7 +352,7 @@ void WorldSession::HandlePetSetAction( WorldPacket & recv_data ) sLog.outDetail( "Player %s has changed pet spell action. Position: %u, Spell: %u, State: 0x%X\n", _player->GetName(), position, spell_id, act_state); //if it's act for spell (en/disable/cast) and there is a spell given (0 = remove spell) which pet doesn't know, don't add - if(!((act_state == ACT_ENABLED || act_state == ACT_DISABLED || act_state == ACT_CAST) && spell_id && !pet->HasSpell(spell_id))) + if(!((act_state == ACT_ENABLED || act_state == ACT_DISABLED || act_state == ACT_PASSIVE) && spell_id && !pet->HasSpell(spell_id))) { //sign for autocast if(act_state == ACT_ENABLED && spell_id) @@ -522,11 +522,10 @@ void WorldSession::HandlePetUnlearnOpcode(WorldPacket& recvPacket) { uint32 spell_id = itr->first; // Pet::removeSpell can invalidate iterator at erase NEW spell ++itr; - pet->removeSpell(spell_id); + //pet->removeSpell(spell_id); + pet->unlearnSpell(spell_id); } - pet->SetTP(pet->getLevel() * (pet->GetLoyaltyLevel() - 1)); - for(uint8 i = 0; i < 10; i++) { if(charmInfo->GetActionBarEntry(i)->SpellOrAction && charmInfo->GetActionBarEntry(i)->Type == ACT_ENABLED || charmInfo->GetActionBarEntry(i)->Type == ACT_DISABLED) @@ -596,11 +595,15 @@ void WorldSession::HandlePetCastSpellOpcode( WorldPacket& recvPacket ) { sLog.outDetail("WORLD: CMSG_PET_CAST_SPELL"); - CHECK_PACKET_SIZE(recvPacket,8+4); + CHECK_PACKET_SIZE(recvPacket,8+1+4+1); uint64 guid; uint32 spellid; + uint8 cast_count; + uint8 unk_flags; // flags (if 0x02 - some additional data are received) - recvPacket >> guid >> spellid; + recvPacket >> guid >> cast_count >> spellid >> unk_flags; + + sLog.outDebug("WORLD: CMSG_PET_CAST_SPELL, cast_count: %u, spellid %u, unk_flags %u", cast_count, spellid, unk_flags); if(!_player->GetPet() && !_player->GetCharm()) return; @@ -637,6 +640,7 @@ void WorldSession::HandlePetCastSpellOpcode( WorldPacket& recvPacket ) pet->clearUnitState(UNIT_STAT_FOLLOW); Spell *spell = new Spell(pet, spellInfo, false); + spell->m_cast_count = cast_count; // probably pending spell cast spell->m_targets = targets; int16 result = spell->PetCanCast(NULL); @@ -668,7 +672,7 @@ void WorldSession::HandlePetCastSpellOpcode( WorldPacket& recvPacket ) } } -void WorldSession::SendPetNameInvalid(uint32 error, std::string name, DeclinedName *declinedName) +void WorldSession::SendPetNameInvalid(uint32 error, const std::string& name, DeclinedName *declinedName) { WorldPacket data(SMSG_PET_NAME_INVALID, 4 + name.size() + 1 + 1); data << uint32(error); @@ -683,3 +687,132 @@ void WorldSession::SendPetNameInvalid(uint32 error, std::string name, DeclinedNa data << uint8(0); SendPacket(&data); } + +void WorldSession::HandlePetLearnTalent( WorldPacket & recv_data ) +{ + sLog.outDebug("WORLD: CMSG_PET_LEARN_TALENT"); + recv_data.hexlike(); + + CHECK_PACKET_SIZE(recv_data, 8+4+4); + + uint64 guid; + uint32 talent_id, requested_rank; + recv_data >> guid >> talent_id >> requested_rank; + + Pet *pet = _player->GetPet(); + + if(!pet) + return; + + if(guid != pet->GetGUID()) + return; + + uint32 CurTalentPoints = pet->GetFreeTalentPoints(); + + if(CurTalentPoints == 0) + return; + + if (requested_rank > 4) + return; + + TalentEntry const *talentInfo = sTalentStore.LookupEntry(talent_id); + + if(!talentInfo) + return; + + TalentTabEntry const *talentTabInfo = sTalentTabStore.LookupEntry(talentInfo->TalentTab); + + if(!talentTabInfo) + return; + + CreatureInfo const *ci = pet->GetCreatureInfo(); + + if(!ci) + return; + + CreatureFamilyEntry const *pet_family = sCreatureFamilyStore.LookupEntry(ci->family); + + if(!pet_family) + return; + + if(pet_family->petTalentType < 0) // not hunter pet + return; + + // prevent learn talent for different family (cheating) + if(!((1 << pet_family->petTalentType) & talentTabInfo->petTalentMask)) + return; + + // prevent skip talent ranks (cheating) + if(requested_rank > 0 && !pet->HasSpell(talentInfo->RankID[requested_rank-1])) + return; + + // Check if it requires another talent + if (talentInfo->DependsOn > 0) + { + if(TalentEntry const *depTalentInfo = sTalentStore.LookupEntry(talentInfo->DependsOn)) + { + bool hasEnoughRank = false; + for (int i = talentInfo->DependsOnRank; i <= 4; i++) + { + if (depTalentInfo->RankID[i] != 0) + if (pet->HasSpell(depTalentInfo->RankID[i])) + hasEnoughRank = true; + } + if (!hasEnoughRank) + return; + } + } + + // Find out how many points we have in this field + uint32 spentPoints = 0; + + uint32 tTab = talentInfo->TalentTab; + if (talentInfo->Row > 0) + { + unsigned int numRows = sTalentStore.GetNumRows(); + for (unsigned int i = 0; i < numRows; i++) // Loop through all talents. + { + // Someday, someone needs to revamp + const TalentEntry *tmpTalent = sTalentStore.LookupEntry(i); + if (tmpTalent) // the way talents are tracked + { + if (tmpTalent->TalentTab == tTab) + { + for (int j = 0; j <= 4; j++) + { + if (tmpTalent->RankID[j] != 0) + { + if (pet->HasSpell(tmpTalent->RankID[j])) + { + spentPoints += j + 1; + } + } + } + } + } + } + } + + // not have required min points spent in talent tree + if(spentPoints < (talentInfo->Row * 3)) + return; + + // spell not set in talent.dbc + uint32 spellid = talentInfo->RankID[requested_rank]; + if( spellid == 0 ) + { + sLog.outError("Talent.dbc have for talent: %u Rank: %u spell id = 0", talent_id, requested_rank); + return; + } + + // already known + if(pet->HasSpell(spellid)) + return; + + // learn! (other talent ranks will unlearned at learning) + pet->learnSpell(spellid); + sLog.outDetail("TalentID: %u Rank: %u Spell: %u\n", talent_id, requested_rank, spellid); + + // update free talent points + pet->SetFreeTalentPoints(CurTalentPoints - 1); +} diff --git a/src/game/PetitionsHandler.cpp b/src/game/PetitionsHandler.cpp index 1064bd23f..712d8bc36 100644 --- a/src/game/PetitionsHandler.cpp +++ b/src/game/PetitionsHandler.cpp @@ -111,18 +111,10 @@ void WorldSession::HandlePetitionBuyOpcode(WorldPacket & recv_data) // TODO: find correct opcode if(_player->getLevel() < sWorld.getConfig(CONFIG_MAX_PLAYER_LEVEL)) { - SendNotification(LANG_ARENA_ONE_TOOLOW, 70); + SendNotification(LANG_ARENA_ONE_TOOLOW, sWorld.getConfig(CONFIG_MAX_PLAYER_LEVEL)); return; } - for(uint8 i = 0; i < MAX_ARENA_SLOT; i++) - { - if(_player->GetArenaTeamId(i) && (i == (unk10-1))) - { - SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, name, "", ERR_ALREADY_IN_ARENA_TEAM); - return; - } - } switch(unk10) { case 1: @@ -144,6 +136,12 @@ void WorldSession::HandlePetitionBuyOpcode(WorldPacket & recv_data) sLog.outDebug("unknown selection at buy petition: %u", unk10); return; } + + if(_player->GetArenaTeamId(unk10-1)) + { + SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, name, "", ERR_ALREADY_IN_ARENA_TEAM); + return; + } } if(type == 9) @@ -153,12 +151,7 @@ void WorldSession::HandlePetitionBuyOpcode(WorldPacket & recv_data) SendGuildCommandResult(GUILD_CREATE_S, name, GUILD_NAME_EXISTS); return; } - if(objmgr.IsReservedName(name)) - { - SendGuildCommandResult(GUILD_CREATE_S, name, GUILD_NAME_INVALID); - return; - } - if(!ObjectMgr::IsValidCharterName(name)) + if(objmgr.IsReservedName(name) || !ObjectMgr::IsValidCharterName(name)) { SendGuildCommandResult(GUILD_CREATE_S, name, GUILD_NAME_INVALID); return; @@ -171,12 +164,7 @@ void WorldSession::HandlePetitionBuyOpcode(WorldPacket & recv_data) SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, name, "", ERR_ARENA_TEAM_NAME_EXISTS_S); return; } - if(objmgr.IsReservedName(name)) - { - SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, name, "", ERR_ARENA_TEAM_NAME_INVALID); - return; - } - if(!ObjectMgr::IsValidCharterName(name)) + if(objmgr.IsReservedName(name) || !ObjectMgr::IsValidCharterName(name)) { SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, name, "", ERR_ARENA_TEAM_NAME_INVALID); return; @@ -209,13 +197,15 @@ void WorldSession::HandlePetitionBuyOpcode(WorldPacket & recv_data) if(!charter) return; - charter->SetUInt32Value(ITEM_FIELD_ENCHANTMENT, charter->GetGUIDLow()); - // ITEM_FIELD_ENCHANTMENT is guild/arenateam id - // ITEM_FIELD_ENCHANTMENT+1 is current signatures count (showed on item) + charter->SetUInt32Value(ITEM_FIELD_ENCHANTMENT_1_1, charter->GetGUIDLow()); + // ITEM_FIELD_ENCHANTMENT_1_1 is guild/arenateam id + // ITEM_FIELD_ENCHANTMENT_1_1+1 is current signatures count (showed on item) charter->SetState(ITEM_CHANGED, _player); _player->SendNewItem(charter, 1, true, false); // a petition is invalid, if both the owner and the type matches + // we checked above, if this player is in an arenateam, so this must be + // datacorruption QueryResult *result = CharacterDatabase.PQuery("SELECT petitionguid FROM petition WHERE ownerguid = '%u' AND type = '%u'", _player->GetGUIDLow(), type); std::ostringstream ssInvalidPetitionGUIDs; @@ -260,15 +250,16 @@ void WorldSession::HandlePetitionShowSignOpcode(WorldPacket & recv_data) // solve (possible) some strange compile problems with explicit use GUID_LOPART(petitionguid) at some GCC versions (wrong code optimization in compiler?) uint32 petitionguid_low = GUID_LOPART(petitionguid); - QueryResult *result = CharacterDatabase.PQuery("SELECT petitionguid, type FROM petition WHERE petitionguid = '%u'", petitionguid_low); + QueryResult *result = CharacterDatabase.PQuery("SELECT type FROM petition WHERE petitionguid = '%u'", petitionguid_low); if(!result) { sLog.outError("any petition on server..."); return; } Field *fields = result->Fetch(); - uint32 type = fields[1].GetUInt32(); + uint32 type = fields[0].GetUInt32(); delete result; + // if guild petition and has guild => error, return; if(type==9 && _player->GetGuildId()) return; @@ -326,7 +317,8 @@ void WorldSession::SendPetitionQueryOpcode(uint64 petitionguid) QueryResult *result = CharacterDatabase.PQuery( "SELECT ownerguid, name, " - " (SELECT COUNT(playerguid) FROM petition_sign WHERE petition_sign.petitionguid = '%u') AS signs " + " (SELECT COUNT(playerguid) FROM petition_sign WHERE petition_sign.petitionguid = '%u') AS signs, " + " type " "FROM petition WHERE petitionguid = '%u'", GUID_LOPART(petitionguid), GUID_LOPART(petitionguid)); if(result) @@ -335,6 +327,7 @@ void WorldSession::SendPetitionQueryOpcode(uint64 petitionguid) ownerguid = MAKE_NEW_GUID(fields[0].GetUInt32(), 0, HIGHGUID_PLAYER); name = fields[1].GetCppString(); signs = fields[2].GetUInt8(); + type = fields[3].GetUInt32(); delete result; } else @@ -343,20 +336,6 @@ void WorldSession::SendPetitionQueryOpcode(uint64 petitionguid) return; } - QueryResult *result2 = CharacterDatabase.PQuery("SELECT type FROM petition WHERE petitionguid = '%u'", GUID_LOPART(petitionguid)); - - if(result2) - { - Field* fields = result2->Fetch(); - type = fields[0].GetUInt32(); - delete result2; - } - else - { - sLog.outDebug("CMSG_PETITION_QUERY failed for petition (GUID: %u)", GUID_LOPART(petitionguid)); - return; - } - WorldPacket data(SMSG_PETITION_QUERY_RESPONSE, (4+8+name.size()+1+1+4*13)); data << GUID_LOPART(petitionguid); // guild/team guid (in mangos always same as GUID_LOPART(petition guid) data << ownerguid; // charter owner guid @@ -408,13 +387,13 @@ void WorldSession::HandlePetitionRenameOpcode(WorldPacket & recv_data) if(!item) return; - QueryResult *result2 = CharacterDatabase.PQuery("SELECT type FROM petition WHERE petitionguid = '%u'", GUID_LOPART(petitionguid)); + QueryResult *result = CharacterDatabase.PQuery("SELECT type FROM petition WHERE petitionguid = '%u'", GUID_LOPART(petitionguid)); - if(result2) + if(result) { - Field* fields = result2->Fetch(); + Field* fields = result->Fetch(); type = fields[0].GetUInt32(); - delete result2; + delete result; } else { @@ -429,12 +408,7 @@ void WorldSession::HandlePetitionRenameOpcode(WorldPacket & recv_data) SendGuildCommandResult(GUILD_CREATE_S, newname, GUILD_NAME_EXISTS); return; } - if(objmgr.IsReservedName(newname)) - { - SendGuildCommandResult(GUILD_CREATE_S, newname, GUILD_NAME_INVALID); - return; - } - if(!ObjectMgr::IsValidCharterName(newname)) + if(objmgr.IsReservedName(newname) || !ObjectMgr::IsValidCharterName(newname)) { SendGuildCommandResult(GUILD_CREATE_S, newname, GUILD_NAME_INVALID); return; @@ -447,12 +421,7 @@ void WorldSession::HandlePetitionRenameOpcode(WorldPacket & recv_data) SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, newname, "", ERR_ARENA_TEAM_NAME_EXISTS_S); return; } - if(objmgr.IsReservedName(newname)) - { - SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, newname, "", ERR_ARENA_TEAM_NAME_INVALID); - return; - } - if(!ObjectMgr::IsValidCharterName(newname)) + if(objmgr.IsReservedName(newname) || !ObjectMgr::IsValidCharterName(newname)) { SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, newname, "", ERR_ARENA_TEAM_NAME_INVALID); return; @@ -480,17 +449,14 @@ void WorldSession::HandlePetitionSignOpcode(WorldPacket & recv_data) Field *fields; uint64 petitionguid; - uint32 type; uint8 unk; - uint64 ownerguid; recv_data >> petitionguid; // petition guid recv_data >> unk; - uint8 signs = 0; - QueryResult *result = CharacterDatabase.PQuery( "SELECT ownerguid, " - " (SELECT COUNT(playerguid) FROM petition_sign WHERE petition_sign.petitionguid = '%u') AS signs " + " (SELECT COUNT(playerguid) FROM petition_sign WHERE petition_sign.petitionguid = '%u') AS signs, " + " type " "FROM petition WHERE petitionguid = '%u'", GUID_LOPART(petitionguid), GUID_LOPART(petitionguid)); if(!result) @@ -500,8 +466,9 @@ void WorldSession::HandlePetitionSignOpcode(WorldPacket & recv_data) } fields = result->Fetch(); - ownerguid = MAKE_NEW_GUID(fields[0].GetUInt32(), 0, HIGHGUID_PLAYER); - signs = fields[1].GetUInt8(); + uint64 ownerguid = MAKE_NEW_GUID(fields[0].GetUInt32(), 0, HIGHGUID_PLAYER); + uint8 signs = fields[1].GetUInt8(); + uint32 type = fields[2].GetUInt32(); delete result; @@ -511,31 +478,53 @@ void WorldSession::HandlePetitionSignOpcode(WorldPacket & recv_data) // not let enemies sign guild charter if(!sWorld.getConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_GUILD) && GetPlayer()->GetTeam() != objmgr.GetPlayerTeamByGUID(ownerguid)) - return; - - QueryResult *result2 = CharacterDatabase.PQuery("SELECT type FROM petition WHERE petitionguid = '%u'", GUID_LOPART(petitionguid)); - - if(result2) { - Field* fields = result2->Fetch(); - type = fields[0].GetUInt32(); - delete result2; + if(type != 9) + SendArenaTeamCommandResult(ERR_ARENA_TEAM_INVITE_SS, "", "", ERR_ARENA_TEAM_NOT_ALLIED); + else + SendGuildCommandResult(GUILD_CREATE_S, "", GUILD_NOT_ALLIED); + return; + } + + if(type != 9) + { + if(_player->getLevel() < sWorld.getConfig(CONFIG_MAX_PLAYER_LEVEL)) + { + SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, "", _player->GetName(), ERR_ARENA_TEAM_PLAYER_TO_LOW); + return; + } + + uint8 slot = ArenaTeam::GetSlotByType(type); + if(slot >= MAX_ARENA_SLOT) + return; + + if(_player->GetArenaTeamId(slot)) + { + SendArenaTeamCommandResult(ERR_ARENA_TEAM_INVITE_SS, "", _player->GetName(), ERR_ALREADY_IN_ARENA_TEAM_S); + return; + } + + if(_player->GetArenaTeamIdInvited()) + { + SendArenaTeamCommandResult(ERR_ARENA_TEAM_INVITE_SS, "", _player->GetName(), ERR_ALREADY_INVITED_TO_ARENA_TEAM_S); + return; + } } else { - sLog.outDebug("CMSG_PETITION_QUERY failed for petition (GUID: %u)", GUID_LOPART(petitionguid)); - return; + if(_player->GetGuildId()) + { + SendGuildCommandResult(GUILD_INVITE_S, _player->GetName(), ALREADY_IN_GUILD); + return; + } + if(_player->GetGuildIdInvited()) + { + SendGuildCommandResult(GUILD_INVITE_S, _player->GetName(), ALREADY_INVITED_TO_GUILD); + return; + } } - if(type != 9 && _player->getLevel() < sWorld.getConfig(CONFIG_MAX_PLAYER_LEVEL)) - { - // player is too low level to join an arena team - SendNotification(LANG_YOUR_ARENA_LEVEL_REQ_ERROR,sWorld.getConfig(CONFIG_MAX_PLAYER_LEVEL)); - return; - } - - signs += 1; - if(signs > type) // client signs maximum + if(++signs > type) // client signs maximum return; //client doesn't allow to sign petition two times by one character, but not check sign by another character from same account @@ -574,7 +563,7 @@ void WorldSession::HandlePetitionSignOpcode(WorldPacket & recv_data) // update signs count on charter, required testing... //Item *item = _player->GetItemByGuid(petitionguid)); //if(item) - // item->SetUInt32Value(ITEM_FIELD_ENCHANTMENT+1, signs); + // item->SetUInt32Value(ITEM_FIELD_ENCHANTMENT_1_1+1, signs); // update for owner if online if(Player *owner = objmgr.GetPlayer(ownerguid)) @@ -619,29 +608,75 @@ void WorldSession::HandleOfferPetitionOpcode(WorldPacket & recv_data) uint8 signs = 0; uint64 petitionguid, plguid; - uint32 petitiontype; + uint32 type, junk; Player *player; - recv_data >> petitiontype; // 2.0.8 - petition type? + recv_data >> junk; // this is not petition type! recv_data >> petitionguid; // petition guid recv_data >> plguid; // player guid - sLog.outDebug("OFFER PETITION: type %u, GUID1 %u, to player id: %u", petitiontype, GUID_LOPART(petitionguid), GUID_LOPART(plguid)); player = ObjectAccessor::FindPlayer(plguid); - if(!player || player->GetSocial()->HasIgnore(GetPlayer()->GetGUIDLow())) + if (!player) return; - // not let offer to enemies + QueryResult *result = CharacterDatabase.PQuery("SELECT type FROM petition WHERE petitionguid = '%u'", GUID_LOPART(petitionguid)); + if (!result) + return; + + Field *fields = result->Fetch(); + type = fields[0].GetUInt32(); + delete result; + + sLog.outDebug("OFFER PETITION: type %u, GUID1 %u, to player id: %u", type, GUID_LOPART(petitionguid), GUID_LOPART(plguid)); + if (!sWorld.getConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_GUILD) && GetPlayer()->GetTeam() != player->GetTeam() ) - return; - - QueryResult *result = CharacterDatabase.PQuery("SELECT petitionguid FROM petition WHERE petitionguid = '%u'", GUID_LOPART(petitionguid)); - if(!result) { - sLog.outError("any petition on server..."); + if(type != 9) + SendArenaTeamCommandResult(ERR_ARENA_TEAM_INVITE_SS, "", "", ERR_ARENA_TEAM_NOT_ALLIED); + else + SendGuildCommandResult(GUILD_CREATE_S, "", GUILD_NOT_ALLIED); return; } - delete result; + if(type != 9) + { + if(player->getLevel() < sWorld.getConfig(CONFIG_MAX_PLAYER_LEVEL)) + { + // player is too low level to join an arena team + SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, player->GetName(), "", ERR_ARENA_TEAM_PLAYER_TO_LOW); + return; + } + + uint8 slot = ArenaTeam::GetSlotByType(type); + if(slot >= MAX_ARENA_SLOT) + return; + + if(player->GetArenaTeamId(slot)) + { + // player is already in an arena team + SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, player->GetName(), "", ERR_ALREADY_IN_ARENA_TEAM_S); + return; + } + + if(player->GetArenaTeamIdInvited()) + { + SendArenaTeamCommandResult(ERR_ARENA_TEAM_INVITE_SS, "", _player->GetName(), ERR_ALREADY_INVITED_TO_ARENA_TEAM_S); + return; + } + } + else + { + if(player->GetGuildId()) + { + SendGuildCommandResult(GUILD_INVITE_S, _player->GetName(), ALREADY_IN_GUILD); + return; + } + + if(player->GetGuildIdInvited()) + { + SendGuildCommandResult(GUILD_INVITE_S, _player->GetName(), ALREADY_INVITED_TO_GUILD); + return; + } + } result = CharacterDatabase.PQuery("SELECT playerguid FROM petition_sign WHERE petitionguid = '%u'", GUID_LOPART(petitionguid)); // result==NULL also correct charter without signs @@ -811,7 +846,7 @@ void WorldSession::HandleTurnInPetitionOpcode(WorldPacket & recv_data) else // or arena team { ArenaTeam* at = new ArenaTeam; - if(!at->create(_player->GetGUID(), type, name)) + if(!at->Create(_player->GetGUID(), type, name)) { sLog.outError("PetitionsHandler: arena team create failed."); delete at; diff --git a/src/game/Player.cpp b/src/game/Player.cpp index ca2041947..5352759db 100644 --- a/src/game/Player.cpp +++ b/src/game/Player.cpp @@ -58,6 +58,7 @@ #include "Database/DatabaseImpl.h" #include "Spell.h" #include "SocialMgr.h" +#include "AchievementMgr.h" #include @@ -126,7 +127,7 @@ PlayerTaxi::PlayerTaxi() memset(m_taximask, 0, sizeof(m_taximask)); } -void PlayerTaxi::InitTaxiNodesForLevel(uint32 race, uint32 level) +void PlayerTaxi::InitTaxiNodesForLevel(uint32 race, uint32 chrClass, uint32 level) { // capital and taxi hub masks switch(race) @@ -143,6 +144,13 @@ void PlayerTaxi::InitTaxiNodesForLevel(uint32 race, uint32 level) case RACE_BLOODELF: SetTaximaskNode(82); break; // Blood Elf case RACE_DRAENEI: SetTaximaskNode(94); break; // Draenei } + + switch(chrClass) + { + case CLASS_DEATH_KNIGHT: // TODO: figure out initial known nodes + break; + } + // new continent starting masks (It will be accessible only at new map) switch(Player::TeamForRace(race)) { @@ -182,7 +190,7 @@ void PlayerTaxi::AppendTaximaskTo( ByteBuffer& data, bool all ) } } -bool PlayerTaxi::LoadTaxiDestinationsFromString( std::string values ) +bool PlayerTaxi::LoadTaxiDestinationsFromString( const std::string& values ) { ClearTaxiDestinations(); @@ -245,7 +253,7 @@ const int32 Player::ReputationRank_Length[MAX_REPUTATION_RANK] = {36000, 3000, 3 UpdateMask Player::updateVisualBits; -Player::Player (WorldSession *session): Unit() +Player::Player (WorldSession *session): Unit(), m_achievementMgr(this) { m_transport = 0; @@ -346,8 +354,8 @@ Player::Player (WorldSession *session): Unit() m_bgBattleGroundID = 0; for (int j=0; j < PLAYER_MAX_BATTLEGROUND_QUEUES; j++) { - m_bgBattleGroundQueueID[j].bgType = 0; - m_bgBattleGroundQueueID[j].invited = false; + m_bgBattleGroundQueueID[j].bgQueueType = 0; + m_bgBattleGroundQueueID[j].invitedToInstance = 0; } m_bgTeam = 0; @@ -358,6 +366,7 @@ Player::Player (WorldSession *session): Unit() m_canParry = false; m_canBlock = false; m_canDualWield = false; + m_canTitanGrip = false; m_ammoDPS = 0.0f; m_temporaryUnsummonedPetNumber = 0; @@ -402,6 +411,9 @@ Player::Player (WorldSession *session): Unit() m_auraBaseMod[i][PCT_MOD] = 1.0f; } + for (int i = 0; i < MAX_COMBAT_RATING; i++) + m_baseRatingValue[i] = 0; + // Honor System m_lastHonorUpdateTime = time(NULL); @@ -415,11 +427,14 @@ Player::Player (WorldSession *session): Unit() //Default movement to run mode m_unit_movement_flags = 0; + m_mover = NULL; + m_miniPet = 0; m_bgAfkReportedTimer = 0; m_contestedPvPTimer = 0; m_declinedname = NULL; + m_runes = NULL; } Player::~Player () @@ -464,6 +479,7 @@ Player::~Player () itr->second.save->RemovePlayer(this); delete m_declinedname; + delete m_runes; } void Player::CleanupsBeforeDelete() @@ -476,7 +492,7 @@ void Player::CleanupsBeforeDelete() Unit::CleanupsBeforeDelete(); } -bool Player::Create( uint32 guidlow, std::string name, uint8 race, uint8 class_, uint8 gender, uint8 skin, uint8 face, uint8 hairStyle, uint8 hairColor, uint8 facialHair, uint8 outfitId ) +bool Player::Create( uint32 guidlow, const std::string& name, uint8 race, uint8 class_, uint8 gender, uint8 skin, uint8 face, uint8 hairStyle, uint8 hairColor, uint8 facialHair, uint8 outfitId ) { //FIXME: outfitId not used in player creating @@ -509,9 +525,9 @@ bool Player::Create( uint32 guidlow, std::string name, uint8 race, uint8 class_, uint8 powertype = cEntry->powerType; - uint32 unitfield; + //uint32 unitfield; - switch(powertype) + /*switch(powertype) { case POWER_ENERGY: case POWER_MANA: @@ -520,13 +536,16 @@ bool Player::Create( uint32 guidlow, std::string name, uint8 race, uint8 class_, case POWER_RAGE: unitfield = 0x00110000; break; + case POWER_RUNIC_POWER: + unitfield = 0x0000EE00; //TODO: find correct unitfield here + break; default: sLog.outError("Invalid default powertype %u for player (class %u)",powertype,class_); return false; - } + }*/ - SetFloatValue(UNIT_FIELD_BOUNDINGRADIUS, DEFAULT_WORLD_OBJECT_SIZE ); - SetFloatValue(UNIT_FIELD_COMBATREACH, 1.5f ); + SetFloatValue(UNIT_FIELD_BOUNDINGRADIUS, DEFAULT_WORLD_OBJECT_SIZE); + SetFloatValue(UNIT_FIELD_COMBATREACH, 1.5f); switch(gender) { @@ -549,12 +568,14 @@ bool Player::Create( uint32 guidlow, std::string name, uint8 race, uint8 class_, uint32 RaceClassGender = ( race ) | ( class_ << 8 ) | ( gender << 16 ); SetUInt32Value(UNIT_FIELD_BYTES_0, ( RaceClassGender | ( powertype << 24 ) ) ); - SetUInt32Value(UNIT_FIELD_BYTES_1, unitfield); - SetByteValue(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_UNK3 | UNIT_BYTE2_FLAG_UNK5 ); - SetUInt32Value(UNIT_FIELD_FLAGS, UNIT_FLAG_PVP_ATTACKABLE ); + //SetUInt32Value(UNIT_FIELD_BYTES_1, unitfield); + SetByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_PVP ); + SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PVP_ATTACKABLE ); + SetFlag(UNIT_FIELD_FLAGS_2, UNIT_FLAG2_REGENERATE_POWER); SetFloatValue(UNIT_MOD_CAST_SPEED, 1.0f); // fix cast time showed in spell tooltip on client + SetFloatValue(UNIT_FIELD_HOVERHEIGHT, 1.0f); // default for players in 3.0.3 - //-1 is default value + // -1 is default value SetUInt32Value(PLAYER_FIELD_WATCHED_FACTION_INDEX, uint32(-1)); SetUInt32Value(PLAYER_BYTES, (skin | (face << 8) | (hairStyle << 16) | (hairColor << 24))); @@ -566,17 +587,35 @@ bool Player::Create( uint32 guidlow, std::string name, uint8 race, uint8 class_, SetUInt32Value( PLAYER_GUILD_TIMESTAMP, 0 ); SetUInt64Value( PLAYER__FIELD_KNOWN_TITLES, 0 ); // 0=disabled + SetUInt64Value( PLAYER__FIELD_KNOWN_TITLES1, 0 ); // 0=disabled SetUInt32Value( PLAYER_CHOSEN_TITLE, 0 ); SetUInt32Value( PLAYER_FIELD_KILLS, 0 ); SetUInt32Value( PLAYER_FIELD_LIFETIME_HONORBALE_KILLS, 0 ); SetUInt32Value( PLAYER_FIELD_TODAY_CONTRIBUTION, 0 ); SetUInt32Value( PLAYER_FIELD_YESTERDAY_CONTRIBUTION, 0 ); + for(uint32 i = 0; i < sGlyphSlotStore.GetNumRows(); ++i) + { + GlyphSlotEntry const * gs = sGlyphSlotStore.LookupEntry(i); + if(gs && gs->Order) + SetGlyphSlot(gs->Order - 1, gs->Id); + } + // set starting level + uint32 start_level = getClass() != CLASS_DEATH_KNIGHT + ? sWorld.getConfig(CONFIG_START_PLAYER_LEVEL) + : sWorld.getConfig(CONFIG_START_HEROIC_PLAYER_LEVEL); + if (GetSession()->GetSecurity() >= SEC_MODERATOR) - SetUInt32Value (UNIT_FIELD_LEVEL, sWorld.getConfig(CONFIG_START_GM_LEVEL)); - else - SetUInt32Value (UNIT_FIELD_LEVEL, sWorld.getConfig(CONFIG_START_PLAYER_LEVEL)); + { + uint32 gm_level = sWorld.getConfig(CONFIG_START_GM_LEVEL); + if(gm_level > start_level) + start_level = gm_level; + } + + SetUInt32Value(UNIT_FIELD_LEVEL, start_level); + + InitRunes(); SetUInt32Value (PLAYER_FIELD_COINAGE, sWorld.getConfig(CONFIG_START_PLAYER_MONEY)); SetUInt32Value (PLAYER_FIELD_HONOR_CURRENCY, sWorld.getConfig(CONFIG_START_HONOR_POINTS)); @@ -590,6 +629,7 @@ bool Player::Create( uint32 guidlow, std::string name, uint8 race, uint8 class_, // base stats and related field values InitStatsForLevel(); InitTaxiNodesForLevel(); + InitGlyphsForLevel(); InitTalentForLevel(); InitPrimaryProffesions(); // to max set before any spell added @@ -602,6 +642,14 @@ bool Player::Create( uint32 guidlow, std::string name, uint8 race, uint8 class_, SetPower(POWER_MANA,GetMaxPower(POWER_MANA)); } + if(getPowerType() == POWER_RUNIC_POWER) + { + SetPower(POWER_RUNE, 8); + SetMaxPower(POWER_RUNE, 8); + SetPower(POWER_RUNIC_POWER, 0); + SetMaxPower(POWER_RUNIC_POWER, 1000); + } + // original spells learnDefaultSpells(true); @@ -645,6 +693,11 @@ bool Player::Create( uint32 guidlow, std::string name, uint8 race, uint8 class_, uint32 item_id = oEntry->ItemId[j]; + + // Hack for not existed item id in dbc 3.0.3 + if(item_id==40582) + continue; + ItemPrototype const* iProto = objmgr.GetItemPrototype(item_id); if(!iProto) { @@ -668,12 +721,12 @@ bool Player::Create( uint32 guidlow, std::string name, uint8 race, uint8 class_, } } - StoreNewItemInBestSlot(item_id, count); + StoreNewItemInBestSlots(item_id, count); } } for (PlayerCreateInfoItems::const_iterator item_id_itr = info->item.begin(); item_id_itr!=info->item.end(); ++item_id_itr++) - StoreNewItemInBestSlot(item_id_itr->item_id, item_id_itr->item_amount); + StoreNewItemInBestSlots(item_id_itr->item_id, item_id_itr->item_amount); // bags and main-hand weapon must equipped at this moment // now second pass for not equipped (offhand weapon/shield if it attempt equipped before main-hand weapon) @@ -713,24 +766,30 @@ bool Player::Create( uint32 guidlow, std::string name, uint8 race, uint8 class_, return true; } -bool Player::StoreNewItemInBestSlot(uint32 titem_id, uint32 titem_amount) +bool Player::StoreNewItemInBestSlots(uint32 titem_id, uint32 titem_amount) { sLog.outDebug("STORAGE: Creating initial item, itemId = %u, count = %u",titem_id, titem_amount); - // attempt equip - uint16 eDest; - uint8 msg = CanEquipNewItem( NULL_SLOT, eDest, titem_id, titem_amount, false ); - if( msg == EQUIP_ERR_OK ) + // attempt equip by one + while(titem_amount > 0) { - EquipNewItem( eDest, titem_id, titem_amount, true); + uint16 eDest; + uint8 msg = CanEquipNewItem( NULL_SLOT, eDest, titem_id, false ); + if( msg != EQUIP_ERR_OK ) + break; + + EquipNewItem( eDest, titem_id, true); AutoUnequipOffhandIfNeed(); - return true; // equipped + --titem_amount; } + if(titem_amount == 0) + return true; // equipped + // attempt store ItemPosCountVec sDest; // store in main bag to simplify second pass (special bags can be not equipped yet at this moment) - msg = CanStoreNewItem( INVENTORY_SLOT_BAG_0, NULL_SLOT, sDest, titem_id, titem_amount ); + uint8 msg = CanStoreNewItem( INVENTORY_SLOT_BAG_0, NULL_SLOT, sDest, titem_id, titem_amount ); if( msg == EQUIP_ERR_OK ) { StoreNewItem( sDest, titem_id, true, Item::GenerateItemRandomPropertyId(titem_id) ); @@ -866,53 +925,29 @@ void Player::HandleDrowning() void Player::HandleLava() { - bool ValidArea = false; - if ((m_isunderwater & 0x80) && isAlive()) { - //Single trigger Set BreathTimer + // Single trigger Set BreathTimer if (!(m_isunderwater & 0x80)) { m_isunderwater|= 0x04; m_breathTimer = 1000; } - //Reset BreathTimer and still in the lava + + // Reset BreathTimer and still in the lava if (!m_breathTimer) { uint64 guid = GetGUID(); uint32 damage = urand(600, 700); // TODO: Get more detailed information about lava damage - uint32 dmgZone = GetZoneId(); // TODO: Find correct "lava dealing zone" flag in Area Table - // Deal lava damage only in lava zones. - switch(dmgZone) - { - case 0x8D: - ValidArea = false; - break; - case 0x94: - ValidArea = false; - break; - case 0x2CE: - ValidArea = false; - break; - case 0x2CF: - ValidArea = false; - break; - default: - if (dmgZone / 5 & 0x408) - ValidArea = true; - } - - // if is valid area and is not gamemaster then deal damage - if ( ValidArea && !isGameMaster() ) + // if not gamemaster then deal damage + if ( !isGameMaster() ) EnvironmentalDamage(guid, DAMAGE_LAVA, damage); m_breathTimer = 1000; } - } - //Death timer disabled and WaterFlags reset - else if (m_deathState == DEAD) + else if (m_deathState == DEAD) // Disable breath timer and reset underwater flags { m_breathTimer = 0; m_isunderwater = 0; @@ -1253,7 +1288,7 @@ void Player::Update( uint32 p_time ) SendUpdateToOutOfRangeGroupMembers(); Pet* pet = GetPet(); - if(pet && !IsWithinDistInMap(pet, OWNER_MAX_DISTANCE)) + if(pet && !IsWithinDistInMap(pet, OWNER_MAX_DISTANCE) && (GetCharmGUID() && (pet->GetGUID() != GetCharmGUID()))) { RemovePet(pet, PET_SAVE_NOT_IN_SLOT, true); return; @@ -1291,6 +1326,7 @@ void Player::setDeathState(DeathState s) // passive spell if(!ressSpellId) ressSpellId = GetResurrectionSpellId(); + GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_DEATH_AT_MAP, 1); } Unit::setDeathState(s); @@ -1311,13 +1347,15 @@ void Player::setDeathState(DeathState s) void Player::BuildEnumData( QueryResult * result, WorldPacket * p_data ) { - *p_data << GetGUID(); + Field *fields = result->Fetch(); + + *p_data << uint64(GetGUID()); *p_data << m_name; - *p_data << getRace(); + *p_data << uint8(getRace()); uint8 pClass = getClass(); - *p_data << pClass; - *p_data << getGender(); + *p_data << uint8(pClass); + *p_data << uint8(getGender()); uint32 bytes = GetUInt32Value(PLAYER_BYTES); *p_data << uint8(bytes); @@ -1332,14 +1370,15 @@ void Player::BuildEnumData( QueryResult * result, WorldPacket * p_data ) // do not use GetMap! it will spawn a new instance since the bound instances are not loaded uint32 zoneId = MapManager::Instance().GetZoneId(GetMapId(), GetPositionX(),GetPositionY()); sLog.outDebug("Player::BuildEnumData: m:%u, x:%f, y:%f, z:%f zone:%u", GetMapId(), GetPositionX(), GetPositionY(), GetPositionZ(), zoneId); - *p_data << zoneId; - *p_data << GetMapId(); + *p_data << uint32(zoneId); + *p_data << uint32(GetMapId()); *p_data << GetPositionX(); *p_data << GetPositionY(); *p_data << GetPositionZ(); - *p_data << (result ? result->Fetch()[13].GetUInt32() : 0); + // guild id + *p_data << (result ? fields[13].GetUInt32() : 0); uint32 char_flags = 0; if(HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_HIDE_HELM)) @@ -1350,14 +1389,13 @@ void Player::BuildEnumData( QueryResult * result, WorldPacket * p_data ) char_flags |= CHARACTER_FLAG_GHOST; if(HasAtLoginFlag(AT_LOGIN_RENAME)) char_flags |= CHARACTER_FLAG_RENAME; - // always send the flag if declined names aren't used - // to let the client select a default method of declining the name - if(!sWorld.getConfig(CONFIG_DECLINED_NAMES_USED) || (result && result->Fetch()[14].GetCppString() != "")) + if(sWorld.getConfig(CONFIG_DECLINED_NAMES_USED) && (fields[14].GetCppString() != "")) char_flags |= CHARACTER_FLAG_DECLINED; - *p_data << (uint32)char_flags; // character flags - - *p_data << (uint8)1; // unknown + *p_data << uint32(char_flags); // character flags + // character customize (flags?) + *p_data << uint32(HasAtLoginFlag(AT_LOGIN_CUSTOMIZE) ? 1 : 0); + *p_data << uint8(1); // unknown // Pets info { @@ -1368,8 +1406,6 @@ void Player::BuildEnumData( QueryResult * result, WorldPacket * p_data ) // show pet at selection character in character list only for non-ghost character if(result && isAlive() && (pClass == CLASS_WARLOCK || pClass == CLASS_HUNTER)) { - Field* fields = result->Fetch(); - uint32 entry = fields[10].GetUInt32(); CreatureInfo const* cInfo = sCreatureStorage.LookupEntry(entry); if(cInfo) @@ -1380,36 +1416,11 @@ void Player::BuildEnumData( QueryResult * result, WorldPacket * p_data ) } } - *p_data << (uint32)petDisplayId; - *p_data << (uint32)petLevel; - *p_data << (uint32)petFamily; + *p_data << uint32(petDisplayId); + *p_data << uint32(petLevel); + *p_data << uint32(petFamily); } - /*ItemPrototype const *items[EQUIPMENT_SLOT_END]; - for (int i = 0; i < EQUIPMENT_SLOT_END; i++) - items[i] = NULL; - - QueryResult *result = CharacterDatabase.PQuery("SELECT slot,item_template FROM character_inventory WHERE guid = '%u' AND bag = 0",GetGUIDLow()); - if (result) - { - do - { - Field *fields = result->Fetch(); - uint8 slot = fields[0].GetUInt8() & 255; - uint32 item_id = fields[1].GetUInt32(); - if( slot >= EQUIPMENT_SLOT_END ) - continue; - - items[slot] = objmgr.GetItemPrototype(item_id); - if(!items[slot]) - { - sLog.outError( "Player::BuildEnumData: Player %s have unknown item (id: #%u) in inventory, skipped.", GetName(),item_id ); - continue; - } - } while (result->NextRow()); - delete result; - }*/ - for (uint8 slot = 0; slot < EQUIPMENT_SLOT_END; slot++) { uint32 visualbase = PLAYER_VISIBLE_ITEM_1_0 + (slot * MAX_VISIBLE_ITEM_OFFSET); @@ -1426,20 +1437,20 @@ void Player::BuildEnumData( QueryResult * result, WorldPacket * p_data ) if (proto != NULL) { - *p_data << (uint32)proto->DisplayInfoID; - *p_data << (uint8)proto->InventoryType; - *p_data << (uint32)(enchant?enchant->aura_id:0); + *p_data << uint32(proto->DisplayInfoID); + *p_data << uint8(proto->InventoryType); + *p_data << uint32(enchant ? enchant->aura_id : 0); } else { - *p_data << (uint32)0; - *p_data << (uint8)0; - *p_data << (uint32)0; // enchant? + *p_data << uint32(0); + *p_data << uint8(0); + *p_data << uint32(0); // enchant? } } - *p_data << (uint32)0; // first bag display id - *p_data << (uint8)0; // first bag inventory type - *p_data << (uint32)0; // enchant? + *p_data << uint32(0); // first bag display id + *p_data << uint8(0); // first bag inventory type + *p_data << uint32(0); // enchant? } bool Player::ToggleAFK() @@ -1493,7 +1504,8 @@ bool Player::TeleportTo(uint32 mapid, float x, float y, float z, float orientati MapEntry const* mEntry = sMapStore.LookupEntry(mapid); // don't let enter battlegrounds without assigned battleground id (for example through areatrigger)... - if(!InBattleGround() && mEntry->IsBattleGround() && !GetSession()->GetSecurity()) + // don't let gm level > 1 either + if(!InBattleGround() && mEntry->IsBattleGroundOrArena()) return false; // client without expansion support @@ -1504,7 +1516,7 @@ bool Player::TeleportTo(uint32 mapid, float x, float y, float z, float orientati if(GetTransport()) RepopAtGraveyard(); // teleport to near graveyard if on transport, looks blizz like :) - SendTransferAborted(mapid, TRANSFER_ABORT_INSUF_EXPAN_LVL1); + SendTransferAborted(mapid, TRANSFER_ABORT_INSUF_EXPAN_LVL, mEntry->Expansion()); return false; // normal client can't teleport to this map... } @@ -1799,13 +1811,20 @@ void Player::RegenerateAll() { RegenerateHealth(); if (!isInCombat() && !HasAuraType(SPELL_AURA_INTERRUPT_REGEN)) + { Regenerate(POWER_RAGE); + if(getClass() == CLASS_DEATH_KNIGHT) + Regenerate(POWER_RUNIC_POWER); + } } Regenerate( POWER_ENERGY ); Regenerate( POWER_MANA ); + if(getClass() == CLASS_DEATH_KNIGHT) + Regenerate( POWER_RUNE ); + m_regenTimer = regenDelay; } @@ -1825,11 +1844,11 @@ void Player::Regenerate(Powers power) if (recentCast) { // Mangos Updates Mana in intervals of 2s, which is correct - addvalue = GetFloatValue(PLAYER_FIELD_MOD_MANA_REGEN_INTERRUPT) * ManaIncreaseRate * 2.00f; + addvalue = GetFloatValue(UNIT_FIELD_POWER_REGEN_INTERRUPTED_FLAT_MODIFIER) * ManaIncreaseRate * 2.00f; } else { - addvalue = GetFloatValue(PLAYER_FIELD_MOD_MANA_REGEN) * ManaIncreaseRate * 2.00f; + addvalue = GetFloatValue(UNIT_FIELD_POWER_REGEN_FLAT_MODIFIER) * ManaIncreaseRate * 2.00f; } } break; case POWER_RAGE: // Regenerate rage @@ -1840,6 +1859,17 @@ void Player::Regenerate(Powers power) case POWER_ENERGY: // Regenerate energy (rogue) addvalue = 20; break; + case POWER_RUNIC_POWER: + { + float RunicPowerDecreaseRate = sWorld.getRate(RATE_POWER_RUNICPOWER_LOSS); + addvalue = 30 * RunicPowerDecreaseRate; // 3 RunicPower by tick + } break; + case POWER_RUNE: + { + for(uint32 i = 0; i < MAX_RUNES; ++i) + if(uint8 cd = GetRuneCooldown(i)) // if we have cooldown, reduce it... + SetRuneCooldown(i, cd - 1); // ... by 2 sec (because update is every 2 sec) + } break; case POWER_FOCUS: case POWER_HAPPINESS: break; @@ -1855,7 +1885,7 @@ void Player::Regenerate(Powers power) addvalue *= ((*i)->GetModifier()->m_amount + 100) / 100.0f; } - if (power != POWER_RAGE) + if (power != POWER_RAGE && power != POWER_RUNIC_POWER) { curValue += uint32(addvalue); if (curValue > maxValue) @@ -2138,6 +2168,8 @@ void Player::GiveLevel(uint32 level) data << uint32(0); data << uint32(0); data << uint32(0); + data << uint32(0); + data << uint32(0); // end for for(int i = STAT_STRENGTH; i < MAX_STATS; ++i) // Stats loop (0-4) data << uint32(int32(info.stats[i]) - GetCreateStat(Stats(i))); @@ -2161,6 +2193,7 @@ void Player::GiveLevel(uint32 level) InitTalentForLevel(); InitTaxiNodesForLevel(); + InitGlyphsForLevel(); UpdateAllStats(); @@ -2177,6 +2210,7 @@ void Player::GiveLevel(uint32 level) Pet* pet = GetPet(); if(pet && pet->getPetType()==SUMMON_PET) pet->GivePetLevel(level); + GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_REACH_LEVEL); } void Player::InitTalentForLevel() @@ -2313,6 +2347,9 @@ void Player::InitStatsForLevel(bool reapplyMods) SetFloatValue(UNIT_FIELD_POWER_COST_MODIFIER+i,0.0f); SetFloatValue(UNIT_FIELD_POWER_COST_MULTIPLIER+i,0.0f); } + // Reset no reagent cost field + for(int i = 0; i < 3; i++) + SetUInt32Value(PLAYER_NO_REAGENT_COST_1 + i, 0); // Init data for form but skip reapply item mods for form InitDataForForm(reapplyMods); @@ -2329,7 +2366,7 @@ void Player::InitStatsForLevel(bool reapplyMods) RemoveFlag( UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_DISABLE_MOVE | UNIT_FLAG_NOT_ATTACKABLE_1 | UNIT_FLAG_PET_IN_COMBAT | UNIT_FLAG_SILENCED | UNIT_FLAG_PACIFIED | - UNIT_FLAG_DISABLE_ROTATE | UNIT_FLAG_IN_COMBAT | UNIT_FLAG_DISARMED | + UNIT_FLAG_STUNNED | UNIT_FLAG_IN_COMBAT | UNIT_FLAG_DISARMED | UNIT_FLAG_CONFUSED | UNIT_FLAG_FLEEING | UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_SKINNABLE | UNIT_FLAG_MOUNT | UNIT_FLAG_TAXI_FLIGHT ); SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PVP_ATTACKABLE ); // must be set @@ -2353,6 +2390,7 @@ void Player::InitStatsForLevel(bool reapplyMods) SetPower(POWER_RAGE, GetMaxPower(POWER_RAGE)); SetPower(POWER_FOCUS, 0); SetPower(POWER_HAPPINESS, 0); + SetPower(POWER_RUNIC_POWER, 0); } void Player::SendInitialSpells() @@ -2767,8 +2805,6 @@ bool Player::addSpell(uint32 spell_id, bool active, bool learning, bool loading, continue; if(_spell_idx->second->learnOnGetSkill == ABILITY_LEARNED_ON_GET_RACE_OR_CLASS_SKILL || - // poison special case, not have ABILITY_LEARNED_ON_GET_RACE_OR_CLASS_SKILL - pSkill->id==SKILL_POISONS && _spell_idx->second->max_value==0 || // lockpicking special case, not have ABILITY_LEARNED_ON_GET_RACE_OR_CLASS_SKILL pSkill->id==SKILL_LOCKPICKING && _spell_idx->second->max_value==0 ) { @@ -2805,6 +2841,12 @@ bool Player::addSpell(uint32 spell_id, bool active, bool learning, bool loading, } } + if(!loading) + { + GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_LEARN_SPELL); + GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_LEARN_SKILLLINE_SPELLS); + } + // return true (for send learn packet) only if spell active (in case ranked spells) and not replace old spell return active && !disabled && !superceded_old; } @@ -2947,8 +2989,6 @@ void Player::removeSpell(uint32 spell_id, bool disabled) continue; if(_spell_idx->second->learnOnGetSkill == ABILITY_LEARNED_ON_GET_RACE_OR_CLASS_SKILL || - // poison special case, not have ABILITY_LEARNED_ON_GET_RACE_OR_CLASS_SKILL - pSkill->id==SKILL_POISONS && _spell_idx->second->max_value==0 || // lockpicking special case, not have ABILITY_LEARNED_ON_GET_RACE_OR_CLASS_SKILL pSkill->id==SKILL_LOCKPICKING && _spell_idx->second->max_value==0 ) { @@ -3248,50 +3288,46 @@ void Player::InitVisibleBits() { updateVisualBits.SetCount(PLAYER_END); - // TODO: really implement OWNER_ONLY and GROUP_ONLY. Flags can be found in UpdateFields.h - updateVisualBits.SetBit(OBJECT_FIELD_GUID); updateVisualBits.SetBit(OBJECT_FIELD_TYPE); + updateVisualBits.SetBit(OBJECT_FIELD_ENTRY); updateVisualBits.SetBit(OBJECT_FIELD_SCALE_X); - - updateVisualBits.SetBit(UNIT_FIELD_CHARM); - updateVisualBits.SetBit(UNIT_FIELD_CHARM+1); - - updateVisualBits.SetBit(UNIT_FIELD_SUMMON); - updateVisualBits.SetBit(UNIT_FIELD_SUMMON+1); - - updateVisualBits.SetBit(UNIT_FIELD_CHARMEDBY); - updateVisualBits.SetBit(UNIT_FIELD_CHARMEDBY+1); - - updateVisualBits.SetBit(UNIT_FIELD_TARGET); - updateVisualBits.SetBit(UNIT_FIELD_TARGET+1); - - updateVisualBits.SetBit(UNIT_FIELD_CHANNEL_OBJECT); - updateVisualBits.SetBit(UNIT_FIELD_CHANNEL_OBJECT+1); - + updateVisualBits.SetBit(UNIT_FIELD_CHARM + 0); + updateVisualBits.SetBit(UNIT_FIELD_CHARM + 1); + updateVisualBits.SetBit(UNIT_FIELD_SUMMON + 0); + updateVisualBits.SetBit(UNIT_FIELD_SUMMON + 1); + updateVisualBits.SetBit(UNIT_FIELD_CHARMEDBY + 0); + updateVisualBits.SetBit(UNIT_FIELD_CHARMEDBY + 1); + updateVisualBits.SetBit(UNIT_FIELD_TARGET + 0); + updateVisualBits.SetBit(UNIT_FIELD_TARGET + 1); + updateVisualBits.SetBit(UNIT_FIELD_CHANNEL_OBJECT + 0); + updateVisualBits.SetBit(UNIT_FIELD_CHANNEL_OBJECT + 1); + updateVisualBits.SetBit(UNIT_FIELD_BYTES_0); updateVisualBits.SetBit(UNIT_FIELD_HEALTH); updateVisualBits.SetBit(UNIT_FIELD_POWER1); updateVisualBits.SetBit(UNIT_FIELD_POWER2); updateVisualBits.SetBit(UNIT_FIELD_POWER3); updateVisualBits.SetBit(UNIT_FIELD_POWER4); updateVisualBits.SetBit(UNIT_FIELD_POWER5); - + updateVisualBits.SetBit(UNIT_FIELD_POWER6); + updateVisualBits.SetBit(UNIT_FIELD_POWER7); updateVisualBits.SetBit(UNIT_FIELD_MAXHEALTH); updateVisualBits.SetBit(UNIT_FIELD_MAXPOWER1); updateVisualBits.SetBit(UNIT_FIELD_MAXPOWER2); updateVisualBits.SetBit(UNIT_FIELD_MAXPOWER3); updateVisualBits.SetBit(UNIT_FIELD_MAXPOWER4); updateVisualBits.SetBit(UNIT_FIELD_MAXPOWER5); - + updateVisualBits.SetBit(UNIT_FIELD_MAXPOWER6); + updateVisualBits.SetBit(UNIT_FIELD_MAXPOWER7); updateVisualBits.SetBit(UNIT_FIELD_LEVEL); updateVisualBits.SetBit(UNIT_FIELD_FACTIONTEMPLATE); - updateVisualBits.SetBit(UNIT_FIELD_BYTES_0); + updateVisualBits.SetBit(UNIT_VIRTUAL_ITEM_SLOT_ID + 0); + updateVisualBits.SetBit(UNIT_VIRTUAL_ITEM_SLOT_ID + 1); + updateVisualBits.SetBit(UNIT_VIRTUAL_ITEM_SLOT_ID + 2); updateVisualBits.SetBit(UNIT_FIELD_FLAGS); updateVisualBits.SetBit(UNIT_FIELD_FLAGS_2); - for(uint16 i = UNIT_FIELD_AURA; i < UNIT_FIELD_AURASTATE; ++i) - updateVisualBits.SetBit(i); updateVisualBits.SetBit(UNIT_FIELD_AURASTATE); - updateVisualBits.SetBit(UNIT_FIELD_BASEATTACKTIME); + updateVisualBits.SetBit(UNIT_FIELD_BASEATTACKTIME + 0); updateVisualBits.SetBit(UNIT_FIELD_BASEATTACKTIME + 1); updateVisualBits.SetBit(UNIT_FIELD_BOUNDINGRADIUS); updateVisualBits.SetBit(UNIT_FIELD_COMBATREACH); @@ -3304,10 +3340,12 @@ void Player::InitVisibleBits() updateVisualBits.SetBit(UNIT_DYNAMIC_FLAGS); updateVisualBits.SetBit(UNIT_CHANNEL_SPELL); updateVisualBits.SetBit(UNIT_MOD_CAST_SPEED); + updateVisualBits.SetBit(UNIT_FIELD_BASE_MANA); updateVisualBits.SetBit(UNIT_FIELD_BYTES_2); + updateVisualBits.SetBit(UNIT_FIELD_HOVERHEIGHT); - updateVisualBits.SetBit(PLAYER_DUEL_ARBITER); - updateVisualBits.SetBit(PLAYER_DUEL_ARBITER+1); + updateVisualBits.SetBit(PLAYER_DUEL_ARBITER + 0); + updateVisualBits.SetBit(PLAYER_DUEL_ARBITER + 1); updateVisualBits.SetBit(PLAYER_FLAGS); updateVisualBits.SetBit(PLAYER_GUILDID); updateVisualBits.SetBit(PLAYER_GUILDRANK); @@ -3318,29 +3356,29 @@ void Player::InitVisibleBits() updateVisualBits.SetBit(PLAYER_GUILD_TIMESTAMP); // PLAYER_QUEST_LOG_x also visible bit on official (but only on party/raid)... - for(uint16 i = PLAYER_QUEST_LOG_1_1; i < PLAYER_QUEST_LOG_25_2; i+=4) + for(uint16 i = PLAYER_QUEST_LOG_1_1; i < PLAYER_QUEST_LOG_25_2; i += 4) updateVisualBits.SetBit(i); - //Players visible items are not inventory stuff - //431) = 884 (0x374) = main weapon - for(uint16 i = 0; i < EQUIPMENT_SLOT_END; i++) + // Players visible items are not inventory stuff + for(uint16 i = 0; i < EQUIPMENT_SLOT_END; ++i) { - // item creator - updateVisualBits.SetBit(PLAYER_VISIBLE_ITEM_1_CREATOR + (i*MAX_VISIBLE_ITEM_OFFSET) + 0); - updateVisualBits.SetBit(PLAYER_VISIBLE_ITEM_1_CREATOR + (i*MAX_VISIBLE_ITEM_OFFSET) + 1); + uint32 offset = i * MAX_VISIBLE_ITEM_OFFSET; - uint16 visual_base = PLAYER_VISIBLE_ITEM_1_0 + (i*MAX_VISIBLE_ITEM_OFFSET); + // item creator + updateVisualBits.SetBit(PLAYER_VISIBLE_ITEM_1_CREATOR + 0 + offset); + updateVisualBits.SetBit(PLAYER_VISIBLE_ITEM_1_CREATOR + 1 + offset); // item entry - updateVisualBits.SetBit(visual_base + 0); + updateVisualBits.SetBit(PLAYER_VISIBLE_ITEM_1_0 + 0 + offset); - // item enchantment IDs - for(uint8 j = 0; j < MAX_INSPECTED_ENCHANTMENT_SLOT; ++j) - updateVisualBits.SetBit(visual_base + 1 + j); + // item enchantments + for(uint8 j = 0; j < MAX_ENCHANTMENT_SLOT; ++j) + updateVisualBits.SetBit(PLAYER_VISIBLE_ITEM_1_0 + 1 + j + offset); // random properties - updateVisualBits.SetBit(PLAYER_VISIBLE_ITEM_1_PROPERTIES + 0 + (i*MAX_VISIBLE_ITEM_OFFSET)); - updateVisualBits.SetBit(PLAYER_VISIBLE_ITEM_1_PROPERTIES + 1 + (i*MAX_VISIBLE_ITEM_OFFSET)); + updateVisualBits.SetBit(PLAYER_VISIBLE_ITEM_1_PROPERTIES + offset); + updateVisualBits.SetBit(PLAYER_VISIBLE_ITEM_1_SEED + offset); + updateVisualBits.SetBit(PLAYER_VISIBLE_ITEM_1_PAD + offset); } updateVisualBits.SetBit(PLAYER_CHOSEN_TITLE); @@ -3358,7 +3396,6 @@ void Player::BuildCreateUpdateBlockForPlayer( UpdateData *data, Player *target ) if(target == this) { - for(int i = INVENTORY_SLOT_BAG_START; i < BANK_SLOT_BAG_END; i++) { if(m_items[i] == NULL) @@ -3366,7 +3403,7 @@ void Player::BuildCreateUpdateBlockForPlayer( UpdateData *data, Player *target ) m_items[i]->BuildCreateUpdateBlockForPlayer( data, target ); } - for(int i = KEYRING_SLOT_START; i < KEYRING_SLOT_END; i++) + for(int i = KEYRING_SLOT_START; i < QUESTBAG_SLOT_END; i++) { if(m_items[i] == NULL) continue; @@ -3399,7 +3436,7 @@ void Player::DestroyForPlayer( Player *target ) const m_items[i]->DestroyForPlayer( target ); } - for(int i = KEYRING_SLOT_START; i < KEYRING_SLOT_END; i++) + for(int i = KEYRING_SLOT_START; i < QUESTBAG_SLOT_END; i++) { if(m_items[i] == NULL) continue; @@ -3483,6 +3520,29 @@ void Player::DeleteFromDB(uint64 playerguid, uint32 accountId, bool updateRealmC guild->DelMember(guid); } + // remove from arena teams + uint32 at_id = GetArenaTeamIdFromDB(playerguid,ARENA_TEAM_2v2); + if(at_id != 0) + { + ArenaTeam * at = objmgr.GetArenaTeamById(at_id); + if(at) + at->DelMember(playerguid); + } + at_id = GetArenaTeamIdFromDB(playerguid,ARENA_TEAM_3v3); + if(at_id != 0) + { + ArenaTeam * at = objmgr.GetArenaTeamById(at_id); + if(at) + at->DelMember(playerguid); + } + at_id = GetArenaTeamIdFromDB(playerguid,ARENA_TEAM_5v5); + if(at_id != 0) + { + ArenaTeam * at = objmgr.GetArenaTeamById(at_id); + if(at) + at->DelMember(playerguid); + } + // the player was uninvited already on logout so just remove from group QueryResult *resultGroup = CharacterDatabase.PQuery("SELECT leaderGuid FROM group_member WHERE memberGuid='%u'", guid); if(resultGroup) @@ -3603,6 +3663,8 @@ void Player::DeleteFromDB(uint64 playerguid, uint32 accountId, bool updateRealmC CharacterDatabase.PExecute("DELETE FROM mail_items WHERE receiver = '%u'",guid); CharacterDatabase.PExecute("DELETE FROM character_pet WHERE owner = '%u'",guid); CharacterDatabase.PExecute("DELETE FROM character_pet_declinedname WHERE owner = '%u'",guid); + CharacterDatabase.PExecute("DELETE FROM character_achievement WHERE guid = '%u'",guid); + CharacterDatabase.PExecute("DELETE FROM character_achievement_progress WHERE guid = '%u'",guid); CharacterDatabase.CommitTransaction(); //loginDatabase.PExecute("UPDATE realmcharacters SET numchars = numchars - 1 WHERE acctid = %d AND realmid = %d", accountId, realmID); @@ -3633,6 +3695,10 @@ void Player::SetMovement(PlayerMovementType pType) */ void Player::BuildPlayerRepop() { + WorldPacket data(SMSG_PRE_RESURRECT, GetPackGUID().size()); + data.append(GetPackGUID()); + GetSession()->SendPacket(&data); + if(getRace() == RACE_NIGHTELF) CastSpell(this, 20584, true); // auras SPELL_AURA_INCREASE_SPEED(+speed in wisp form), SPELL_AURA_INCREASE_SWIM_SPEED(+swim speed in wisp form), SPELL_AURA_TRANSFORM (to wisp form) CastSpell(this, 8326, true); // auras SPELL_AURA_GHOST, SPELL_AURA_INCREASE_SPEED(why?), SPELL_AURA_INCREASE_SWIM_SPEED(why?) @@ -3752,7 +3818,7 @@ void Player::ResurrectPlayer(float restore_percent, bool applySickness) if(Aura* Aur = GetAura(SPELL_ID_PASSIVE_RESURRECTION_SICKNESS,i)) { Aur->SetAuraDuration(delta*1000); - Aur->UpdateAuraDuration(); + Aur->SendAuraUpdate(false); } } } @@ -4289,7 +4355,7 @@ uint32 Player::GetShieldBlockValue() const { BaseModGroup modGroup = SHIELD_BLOCK_VALUE; - float value = GetTotalBaseModValue(modGroup) + GetStat(STAT_STRENGTH)/20 - 1; + float value = GetTotalBaseModValue(modGroup) + GetStat(STAT_STRENGTH) * 0.5f - 10; value = (value < 0) ? 0 : value; @@ -4478,7 +4544,18 @@ float Player::OCTRegenMPPerSpirit() void Player::ApplyRatingMod(CombatRating cr, int32 value, bool apply) { - ApplyModUInt32Value(PLAYER_FIELD_COMBAT_RATING_1 + cr, value, apply); + m_baseRatingValue[cr]+=(apply ? value : -value); + + int32 amount = uint32(m_baseRatingValue[cr]); + // Apply bonus from SPELL_AURA_MOD_RATING_FROM_STAT + // stat used stored in miscValueB for this aura + AuraList const& modRatingFromStat = GetAurasByType(SPELL_AURA_MOD_RATING_FROM_STAT); + for(AuraList::const_iterator i = modRatingFromStat.begin();i != modRatingFromStat.end(); ++i) + if ((*i)->GetMiscValue() & (1<GetMiscBValue())) * (*i)->GetModifier()->m_amount / 100.0f; + if (amount < 0) + amount = 0; + SetUInt32Value(PLAYER_FIELD_COMBAT_RATING_1 + cr, uint32(amount)); float RatingCoeffecient = GetRatingCoefficient(cr); float RatingChange = 0.0f; @@ -4501,16 +4578,13 @@ void Player::ApplyRatingMod(CombatRating cr, int32 value, bool apply) UpdateBlockPercentage(); break; case CR_HIT_MELEE: - RatingChange = value / RatingCoeffecient; - m_modMeleeHitChance += apply ? RatingChange : -RatingChange; + UpdateMeleeHitChances(); break; case CR_HIT_RANGED: - RatingChange = value / RatingCoeffecient; - m_modRangedHitChance += apply ? RatingChange : -RatingChange; + UpdateRangedHitChances(); break; case CR_HIT_SPELL: - RatingChange = value / RatingCoeffecient; - m_modSpellHitChance += apply ? RatingChange : -RatingChange; + UpdateSpellHitChances(); break; case CR_CRIT_MELEE: if(affectStats) @@ -4608,6 +4682,7 @@ bool Player::UpdateSkill(uint32 skill_id, uint32 step) new_value = max; SetUInt32Value(PLAYER_SKILL_VALUE_INDEX(i),MAKE_SKILL_VALUE(new_value,max)); + GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_REACH_SKILL_LEVEL); return true; } @@ -4670,6 +4745,7 @@ bool Player::UpdateGatherSkill(uint32 SkillId, uint32 SkillValue, uint32 RedLeve case SKILL_HERBALISM: case SKILL_LOCKPICKING: case SKILL_JEWELCRAFTING: + case SKILL_INSCRIPTION: return UpdateSkillPro(SkillId, SkillGainChance(SkillValue, RedLevel+100, RedLevel+50, RedLevel+25)*Multiplicator,gathering_skill_gain); case SKILL_SKINNING: if( sWorld.getConfig(CONFIG_SKILL_CHANCE_SKINNING_STEPS)==0) @@ -4732,6 +4808,7 @@ bool Player::UpdateSkillPro(uint16 SkillId, int32 Chance, uint32 step) new_value = MaxValue; SetUInt32Value(PLAYER_SKILL_VALUE_INDEX(i),MAKE_SKILL_VALUE(new_value,MaxValue)); + GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_REACH_SKILL_LEVEL); sLog.outDebug("Player::UpdateSkillPro Chance=%3.1f%% taken", Chance/10.0); return true; } @@ -4919,7 +4996,10 @@ void Player::SetSkill(uint32 id, uint16 currVal, uint16 maxVal) if(iReputationListID; @@ -5708,7 +5792,8 @@ bool Player::ModifyOneFactionReputation(FactionEntry const* factionEntry, int32 } } } - + GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_GAIN_REPUTATION); + GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_GAIN_EXALTED_REPUTATION); SendFactionState(&(itr->second)); return true; @@ -5774,6 +5859,8 @@ bool Player::SetOneFactionReputation(FactionEntry const* factionEntry, int32 sta SetFactionAtWar(&itr->second,true); SendFactionState(&(itr->second)); + GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_GAIN_REPUTATION); + GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_GAIN_EXALTED_REPUTATION); return true; } return false; @@ -6424,19 +6511,43 @@ void Player::_ApplyItemMods(Item *item, uint8 slot,bool apply) sLog.outDebug("_ApplyItemMods complete."); } -void Player::_ApplyItemBonuses(ItemPrototype const *proto,uint8 slot,bool apply) +void Player::_ApplyItemBonuses(ItemPrototype const *proto, uint8 slot, bool apply) { if(slot >= INVENTORY_SLOT_BAG_END || !proto) return; for (int i = 0; i < 10; i++) { - float val = float (proto->ItemStat[i].ItemStatValue); + uint32 statType = 0; + int32 val = 0; - if(val==0) + if(proto->ScalingStatDistribution) + { + if(ScalingStatDistributionEntry const *ssd = sScalingStatDistributionStore.LookupEntry(proto->ScalingStatDistribution)) + { + statType = ssd->StatMod[i]; + + if(uint32 modifier = ssd->Modifier[i]) + { + uint32 level = ((getLevel() > ssd->MaxLevel) ? ssd->MaxLevel : getLevel()); + if(ScalingStatValuesEntry const *ssv = sScalingStatValuesStore.LookupEntry(level)) + { + int multiplier = ssv->Multiplier[proto->GetScalingStatValuesColumn()]; + val = (multiplier * modifier) / 10000; + } + } + } + } + else + { + statType = proto->ItemStat[i].ItemStatType; + val = float(proto->ItemStat[i].ItemStatValue); + } + + if(val == 0) continue; - switch (proto->ItemStat[i].ItemStatType) + switch (statType) { case ITEM_MOD_MANA: HandleStatModifier(UNIT_MOD_MANA, BASE_VALUE, float(val), apply); @@ -6554,6 +6665,9 @@ void Player::_ApplyItemBonuses(ItemPrototype const *proto,uint8 slot,bool apply) case ITEM_MOD_EXPERTISE_RATING: ApplyRatingMod(CR_EXPERTISE, int32(val), apply); break; + case ITEM_MOD_ARMOR_PENETRATION_RATING: + ApplyRatingMod(CR_ARMOR_PENETRATION, int32(val), apply); + break; } } @@ -7159,6 +7273,17 @@ void Player::SendLoot(uint64 guid, LootType loot_type) loot->FillLoot(item->GetEntry(), LootTemplates_Prospecting, this); } } + else if(loot_type == LOOT_MILLING) + { + loot = &item->loot; + + if(!item->m_lootGenerated) + { + item->m_lootGenerated = true; + loot->clear(); + loot->FillLoot(item->GetEntry(), LootTemplates_Milling, this); + } + } else { loot = &item->loot; @@ -7352,8 +7477,8 @@ void Player::SendLoot(uint64 guid, LootType loot_type) conditional_list = itr->second; } - // LOOT_PICKPOCKETING, LOOT_PROSPECTING, LOOT_DISENCHANTING and LOOT_INSIGNIA unsupported by client, sending LOOT_SKINNING instead - if(loot_type == LOOT_PICKPOCKETING || loot_type == LOOT_DISENCHANTING || loot_type == LOOT_PROSPECTING || loot_type == LOOT_INSIGNIA) + // LOOT_PICKPOCKETING, LOOT_PROSPECTING, LOOT_DISENCHANTING, LOOT_INSIGNIA and LOOT_MILLING unsupported by client, sending LOOT_SKINNING instead + if(loot_type == LOOT_PICKPOCKETING || loot_type == LOOT_DISENCHANTING || loot_type == LOOT_PROSPECTING || loot_type == LOOT_INSIGNIA || loot_type == LOOT_MILLING) loot_type = LOOT_SKINNING; if(loot_type == LOOT_FISHINGHOLE) @@ -7732,19 +7857,34 @@ void Player::SendInitWorldStates() data << uint32(0xa5f) << uint32(0x0); // 35 break; case 3698: // Nagrand Arena - data << uint32(0xa0f) << uint32(0x0); // 7 - data << uint32(0xa10) << uint32(0x0); // 8 - data << uint32(0xa11) << uint32(0x0); // 9 + if (bg && bg->GetTypeID() == BATTLEGROUND_NA) + bg->FillInitialWorldStates(data); + else + { + data << uint32(0xa0f) << uint32(0x0); // 7 + data << uint32(0xa10) << uint32(0x0); // 8 + data << uint32(0xa11) << uint32(0x0); // 9 show + } break; case 3702: // Blade's Edge Arena - data << uint32(0x9f0) << uint32(0x0); // 7 - data << uint32(0x9f1) << uint32(0x0); // 8 - data << uint32(0x9f3) << uint32(0x0); // 9 + if (bg && bg->GetTypeID() == BATTLEGROUND_BE) + bg->FillInitialWorldStates(data); + else + { + data << uint32(0x9f0) << uint32(0x0); // 7 gold + data << uint32(0x9f1) << uint32(0x0); // 8 green + data << uint32(0x9f3) << uint32(0x0); // 9 show + } break; case 3968: // Ruins of Lordaeron - data << uint32(0xbb8) << uint32(0x0); // 7 - data << uint32(0xbb9) << uint32(0x0); // 8 - data << uint32(0xbba) << uint32(0x0); // 9 + if (bg && bg->GetTypeID() == BATTLEGROUND_RL) + bg->FillInitialWorldStates(data); + else + { + data << uint32(0xbb8) << uint32(0x0); // 7 gold + data << uint32(0xbb9) << uint32(0x0); // 8 green + data << uint32(0xbba) << uint32(0x0); // 9 show + } break; case 3703: // Shattrath City break; @@ -7913,7 +8053,8 @@ uint8 Player::FindEquipSlot( ItemPrototype const* proto, uint32 slot, bool swap // (this will be replace mainhand weapon at auto equip instead unwonted "you don't known dual wielding" ... if(CanDualWield()) slots[1] = EQUIPMENT_SLOT_OFFHAND; - };break; + break; + }; case INVTYPE_SHIELD: slots[0] = EQUIPMENT_SLOT_OFFHAND; break; @@ -7922,6 +8063,8 @@ uint8 Player::FindEquipSlot( ItemPrototype const* proto, uint32 slot, bool swap break; case INVTYPE_2HWEAPON: slots[0] = EQUIPMENT_SLOT_MAINHAND; + if (CanDualWield() && CanTitanGrip()) + slots[1] = EQUIPMENT_SLOT_OFFHAND; break; case INVTYPE_TABARD: slots[0] = EQUIPMENT_SLOT_TABARD; @@ -7967,6 +8110,10 @@ uint8 Player::FindEquipSlot( ItemPrototype const* proto, uint32 slot, bool swap if (pClass == CLASS_WARLOCK) slots[0] = EQUIPMENT_SLOT_RANGED; break; + case ITEM_SUBCLASS_ARMOR_SIGIL: + if (pClass == CLASS_DEATH_KNIGHT) + slots[0] = EQUIPMENT_SLOT_RANGED; + break; } break; } @@ -7992,14 +8139,8 @@ uint8 Player::FindEquipSlot( ItemPrototype const* proto, uint32 slot, bool swap { if ( slots[i] != NULL_SLOT && !GetItemByPos( INVENTORY_SLOT_BAG_0, slots[i] ) ) { - // in case 2hand equipped weapon offhand slot empty but not free - if(slots[i]==EQUIPMENT_SLOT_OFFHAND) - { - Item* mainItem = GetItemByPos( INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_MAINHAND ); - if(!mainItem || mainItem->GetProto()->InventoryType != INVTYPE_2HWEAPON) - return slots[i]; - } - else + // in case 2hand equipped weapon (without titan grip) offhand slot empty but not free + if(slots[i]!=EQUIPMENT_SLOT_OFFHAND || !IsTwoHandUsed()) return slots[i]; } } @@ -8049,7 +8190,7 @@ uint8 Player::CanUnequipItems( uint32 item, uint32 count ) const return EQUIP_ERR_OK; } } - for(int i = KEYRING_SLOT_START; i < KEYRING_SLOT_END; i++) + for(int i = KEYRING_SLOT_START; i < QUESTBAG_SLOT_END; i++) { pItem = GetItemByPos( INVENTORY_SLOT_BAG_0, i ); if( pItem && pItem->GetEntry() == item ) @@ -8091,7 +8232,7 @@ uint32 Player::GetItemCount( uint32 item, bool inBankAlso, Item* skipItem ) cons if( pItem && pItem != skipItem && pItem->GetEntry() == item ) count += pItem->GetCount(); } - for(int i = KEYRING_SLOT_START; i < KEYRING_SLOT_END; i++) + for(int i = KEYRING_SLOT_START; i < QUESTBAG_SLOT_END; i++) { Item *pItem = GetItemByPos( INVENTORY_SLOT_BAG_0, i ); if( pItem && pItem != skipItem && pItem->GetEntry() == item ) @@ -8151,7 +8292,7 @@ Item* Player::GetItemByGuid( uint64 guid ) const if( pItem && pItem->GetGUID() == guid ) return pItem; } - for(int i = KEYRING_SLOT_START; i < KEYRING_SLOT_END; i++) + for(int i = KEYRING_SLOT_START; i < QUESTBAG_SLOT_END; i++) { Item *pItem = GetItemByPos( INVENTORY_SLOT_BAG_0, i ); if( pItem && pItem->GetGUID() == guid ) @@ -8197,7 +8338,7 @@ Item* Player::GetItemByPos( uint16 pos ) const Item* Player::GetItemByPos( uint8 bag, uint8 slot ) const { - if( bag == INVENTORY_SLOT_BAG_0 && ( slot < BANK_SLOT_BAG_END || slot >= KEYRING_SLOT_START && slot < KEYRING_SLOT_END ) ) + if( bag == INVENTORY_SLOT_BAG_0 && ( slot < BANK_SLOT_BAG_END || slot >= KEYRING_SLOT_START && slot < QUESTBAG_SLOT_END ) ) return m_items[slot]; else if(bag >= INVENTORY_SLOT_BAG_START && bag < INVENTORY_SLOT_BAG_END || bag >= BANK_SLOT_BAG_START && bag < BANK_SLOT_BAG_END ) @@ -8275,7 +8416,7 @@ bool Player::IsInventoryPos( uint8 bag, uint8 slot ) return true; if( bag >= INVENTORY_SLOT_BAG_START && bag < INVENTORY_SLOT_BAG_END ) return true; - if( bag == INVENTORY_SLOT_BAG_0 && ( slot >= KEYRING_SLOT_START && slot < KEYRING_SLOT_END ) ) + if( bag == INVENTORY_SLOT_BAG_0 && ( slot >= KEYRING_SLOT_START && slot < QUESTBAG_SLOT_END ) ) return true; return false; } @@ -8396,7 +8537,7 @@ bool Player::HasItemCount( uint32 item, uint32 count, bool inBankAlso ) const return true; } } - for(int i = KEYRING_SLOT_START; i < KEYRING_SLOT_END; i++) + for(int i = KEYRING_SLOT_START; i < QUESTBAG_SLOT_END; i++) { Item *pItem = GetItemByPos( INVENTORY_SLOT_BAG_0, i ); if( pItem && pItem->GetEntry() == item ) @@ -8518,7 +8659,7 @@ bool Player::HasItemTotemCategory( uint32 TotemCategory ) const if( pItem && IsTotemCategoryCompatiableWith(pItem->GetProto()->TotemCategory,TotemCategory )) return true; } - for(uint8 i = KEYRING_SLOT_START; i < KEYRING_SLOT_END; ++i) + for(uint8 i = KEYRING_SLOT_START; i < QUESTBAG_SLOT_END; ++i) { pItem = GetItemByPos( INVENTORY_SLOT_BAG_0, i ); if( pItem && IsTotemCategoryCompatiableWith(pItem->GetProto()->TotemCategory,TotemCategory )) @@ -8558,6 +8699,18 @@ uint8 Player::_CanStoreItem_InSpecificSlot( uint8 bag, uint8 slot, ItemPosCountV if(slot >= KEYRING_SLOT_START && slot < KEYRING_SLOT_START+GetMaxKeyringSize() && !(pProto->BagFamily & BAG_FAMILY_MASK_KEYS)) return EQUIP_ERR_ITEM_DOESNT_GO_INTO_BAG; + // vanitypet case + if(slot >= VANITYPET_SLOT_START && slot < VANITYPET_SLOT_END && !(pProto->BagFamily & BAG_FAMILY_MASK_VANITY_PETS)) + 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)) + return EQUIP_ERR_ITEM_DOESNT_GO_INTO_BAG; + + // guestbag case + if(slot >= QUESTBAG_SLOT_START && slot < QUESTBAG_SLOT_END && !(pProto->BagFamily & BAG_FAMILY_MASK_QUEST_ITEMS)) + return EQUIP_ERR_ITEM_DOESNT_GO_INTO_BAG; + // prevent cheating if(slot >= BUYBACK_SLOT_START && slot < BUYBACK_SLOT_END || slot >= PLAYER_SLOT_END) return EQUIP_ERR_ITEM_DOESNT_GO_INTO_BAG; @@ -8802,7 +8955,7 @@ uint8 Player::_CanStoreItem( uint8 bag, uint8 slot, ItemPosCountVec &dest, uint3 { if( bag == INVENTORY_SLOT_BAG_0 ) // inventory { - res = _CanStoreItem_InInventorySlots(KEYRING_SLOT_START,KEYRING_SLOT_END,dest,pProto,count,true,pItem,bag,slot); + res = _CanStoreItem_InInventorySlots(KEYRING_SLOT_START,QUESTBAG_SLOT_END,dest,pProto,count,true,pItem,bag,slot); if(res!=EQUIP_ERR_OK) { if(no_space_count) @@ -8889,6 +9042,66 @@ uint8 Player::_CanStoreItem( uint8 bag, uint8 slot, ItemPosCountVec &dest, uint3 return EQUIP_ERR_CANT_CARRY_MORE_OF_THIS; } } + else if(pProto->BagFamily & BAG_FAMILY_MASK_VANITY_PETS) + { + res = _CanStoreItem_InInventorySlots(VANITYPET_SLOT_START,VANITYPET_SLOT_END,dest,pProto,count,false,pItem,bag,slot); + if(res!=EQUIP_ERR_OK) + { + if(no_space_count) + *no_space_count = count + no_similar_count; + return res; + } + + if(count==0) + { + if(no_similar_count==0) + return EQUIP_ERR_OK; + + if(no_space_count) + *no_space_count = count + no_similar_count; + return EQUIP_ERR_CANT_CARRY_MORE_OF_THIS; + } + } + else if(pProto->BagFamily & BAG_FAMILY_MASK_CURRENCY_TOKENS) + { + res = _CanStoreItem_InInventorySlots(CURRENCYTOKEN_SLOT_START,CURRENCYTOKEN_SLOT_END,dest,pProto,count,false,pItem,bag,slot); + if(res!=EQUIP_ERR_OK) + { + if(no_space_count) + *no_space_count = count + no_similar_count; + return res; + } + + if(count==0) + { + if(no_similar_count==0) + return EQUIP_ERR_OK; + + if(no_space_count) + *no_space_count = count + no_similar_count; + return EQUIP_ERR_CANT_CARRY_MORE_OF_THIS; + } + } + else if(pProto->BagFamily & BAG_FAMILY_MASK_QUEST_ITEMS) + { + res = _CanStoreItem_InInventorySlots(QUESTBAG_SLOT_START,QUESTBAG_SLOT_END,dest,pProto,count,false,pItem,bag,slot); + if(res!=EQUIP_ERR_OK) + { + if(no_space_count) + *no_space_count = count + no_similar_count; + return res; + } + + if(count==0) + { + if(no_similar_count==0) + return EQUIP_ERR_OK; + + if(no_space_count) + *no_space_count = count + no_similar_count; + return EQUIP_ERR_CANT_CARRY_MORE_OF_THIS; + } + } res = _CanStoreItem_InInventorySlots(INVENTORY_SLOT_ITEM_START,INVENTORY_SLOT_ITEM_END,dest,pProto,count,false,pItem,bag,slot); if(res!=EQUIP_ERR_OK) @@ -8938,7 +9151,7 @@ uint8 Player::_CanStoreItem( uint8 bag, uint8 slot, ItemPosCountVec &dest, uint3 // search stack for merge to if( pProto->Stackable > 1 ) { - res = _CanStoreItem_InInventorySlots(KEYRING_SLOT_START,KEYRING_SLOT_END,dest,pProto,count,true,pItem,bag,slot); + res = _CanStoreItem_InInventorySlots(KEYRING_SLOT_START,QUESTBAG_SLOT_END,dest,pProto,count,true,pItem,bag,slot); if(res!=EQUIP_ERR_OK) { if(no_space_count) @@ -9036,6 +9249,66 @@ uint8 Player::_CanStoreItem( uint8 bag, uint8 slot, ItemPosCountVec &dest, uint3 return EQUIP_ERR_CANT_CARRY_MORE_OF_THIS; } } + else if(pProto->BagFamily & BAG_FAMILY_MASK_VANITY_PETS) + { + res = _CanStoreItem_InInventorySlots(VANITYPET_SLOT_START,VANITYPET_SLOT_END,dest,pProto,count,false,pItem,bag,slot); + if(res!=EQUIP_ERR_OK) + { + if(no_space_count) + *no_space_count = count + no_similar_count; + return res; + } + + if(count==0) + { + if(no_similar_count==0) + return EQUIP_ERR_OK; + + if(no_space_count) + *no_space_count = count + no_similar_count; + return EQUIP_ERR_CANT_CARRY_MORE_OF_THIS; + } + } + else if(pProto->BagFamily & BAG_FAMILY_MASK_CURRENCY_TOKENS) + { + res = _CanStoreItem_InInventorySlots(CURRENCYTOKEN_SLOT_START,CURRENCYTOKEN_SLOT_END,dest,pProto,count,false,pItem,bag,slot); + if(res!=EQUIP_ERR_OK) + { + if(no_space_count) + *no_space_count = count + no_similar_count; + return res; + } + + if(count==0) + { + if(no_similar_count==0) + return EQUIP_ERR_OK; + + if(no_space_count) + *no_space_count = count + no_similar_count; + return EQUIP_ERR_CANT_CARRY_MORE_OF_THIS; + } + } + else if(pProto->BagFamily & BAG_FAMILY_MASK_QUEST_ITEMS) + { + res = _CanStoreItem_InInventorySlots(QUESTBAG_SLOT_START,QUESTBAG_SLOT_END,dest,pProto,count,false,pItem,bag,slot); + if(res!=EQUIP_ERR_OK) + { + if(no_space_count) + *no_space_count = count + no_similar_count; + return res; + } + + if(count==0) + { + if(no_similar_count==0) + return EQUIP_ERR_OK; + + if(no_space_count) + *no_space_count = count + no_similar_count; + return EQUIP_ERR_CANT_CARRY_MORE_OF_THIS; + } + } for(int i = INVENTORY_SLOT_BAG_START; i < INVENTORY_SLOT_BAG_END; i++) { @@ -9106,10 +9379,16 @@ uint8 Player::CanStoreItems( Item **pItems,int count) const int inv_slot_items[INVENTORY_SLOT_ITEM_END-INVENTORY_SLOT_ITEM_START]; int inv_bags[INVENTORY_SLOT_BAG_END-INVENTORY_SLOT_BAG_START][MAX_BAG_SIZE]; int inv_keys[KEYRING_SLOT_END-KEYRING_SLOT_START]; + int inv_pets[VANITYPET_SLOT_END-VANITYPET_SLOT_START]; + int inv_tokens[CURRENCYTOKEN_SLOT_END-CURRENCYTOKEN_SLOT_START]; + int inv_quests[QUESTBAG_SLOT_END-QUESTBAG_SLOT_START]; memset(inv_slot_items,0,sizeof(int)*(INVENTORY_SLOT_ITEM_END-INVENTORY_SLOT_ITEM_START)); memset(inv_bags,0,sizeof(int)*(INVENTORY_SLOT_BAG_END-INVENTORY_SLOT_BAG_START)*MAX_BAG_SIZE); memset(inv_keys,0,sizeof(int)*(KEYRING_SLOT_END-KEYRING_SLOT_START)); + memset(inv_pets,0,sizeof(int)*(VANITYPET_SLOT_END-VANITYPET_SLOT_START)); + memset(inv_tokens,0,sizeof(int)*(CURRENCYTOKEN_SLOT_END-CURRENCYTOKEN_SLOT_START)); + memset(inv_quests,0,sizeof(int)*(QUESTBAG_SLOT_END-QUESTBAG_SLOT_START)); for(int i = INVENTORY_SLOT_ITEM_START; i < INVENTORY_SLOT_ITEM_END; i++) { @@ -9131,6 +9410,36 @@ uint8 Player::CanStoreItems( Item **pItems,int count) const } } + for(int i = VANITYPET_SLOT_START; i < VANITYPET_SLOT_END; i++) + { + pItem2 = GetItemByPos( INVENTORY_SLOT_BAG_0, i ); + + if (pItem2 && !pItem2->IsInTrade()) + { + inv_pets[i-VANITYPET_SLOT_START] = pItem2->GetCount(); + } + } + + for(int i = CURRENCYTOKEN_SLOT_START; i < CURRENCYTOKEN_SLOT_END; i++) + { + pItem2 = GetItemByPos( INVENTORY_SLOT_BAG_0, i ); + + if (pItem2 && !pItem2->IsInTrade()) + { + inv_tokens[i-CURRENCYTOKEN_SLOT_START] = pItem2->GetCount(); + } + } + + for(int i = QUESTBAG_SLOT_START; i < QUESTBAG_SLOT_END; i++) + { + pItem2 = GetItemByPos( INVENTORY_SLOT_BAG_0, i ); + + if (pItem2 && !pItem2->IsInTrade()) + { + inv_quests[i-QUESTBAG_SLOT_START] = pItem2->GetCount(); + } + } + for(int i = INVENTORY_SLOT_BAG_START; i < INVENTORY_SLOT_BAG_END; i++) { if(Bag* pBag = (Bag*)GetItemByPos( INVENTORY_SLOT_BAG_0, i )) @@ -9190,6 +9499,42 @@ uint8 Player::CanStoreItems( Item **pItems,int count) const } if (b_found) continue; + for(int t = VANITYPET_SLOT_START; t < VANITYPET_SLOT_END; t++) + { + pItem2 = GetItemByPos( INVENTORY_SLOT_BAG_0, t ); + if( pItem2 && pItem2->GetEntry() == pItem->GetEntry() && inv_pets[t-VANITYPET_SLOT_START] + pItem->GetCount() <= pProto->Stackable ) + { + inv_pets[t-VANITYPET_SLOT_START] += pItem->GetCount(); + b_found = true; + break; + } + } + if (b_found) continue; + + for(int t = CURRENCYTOKEN_SLOT_START; t < CURRENCYTOKEN_SLOT_END; t++) + { + pItem2 = GetItemByPos( INVENTORY_SLOT_BAG_0, t ); + if( pItem2 && pItem2->GetEntry() == pItem->GetEntry() && inv_tokens[t-CURRENCYTOKEN_SLOT_START] + pItem->GetCount() <= pProto->Stackable ) + { + inv_tokens[t-CURRENCYTOKEN_SLOT_START] += pItem->GetCount(); + b_found = true; + break; + } + } + if (b_found) continue; + + for(int t = QUESTBAG_SLOT_START; t < QUESTBAG_SLOT_END; t++) + { + pItem2 = GetItemByPos( INVENTORY_SLOT_BAG_0, t ); + if( pItem2 && pItem2->GetEntry() == pItem->GetEntry() && inv_quests[t-QUESTBAG_SLOT_START] + pItem->GetCount() <= pProto->Stackable ) + { + inv_quests[t-QUESTBAG_SLOT_START] += pItem->GetCount(); + b_found = true; + break; + } + } + if (b_found) continue; + for(int t = INVENTORY_SLOT_ITEM_START; t < INVENTORY_SLOT_ITEM_END; t++) { pItem2 = GetItemByPos( INVENTORY_SLOT_BAG_0, t ); @@ -9242,6 +9587,51 @@ uint8 Player::CanStoreItems( Item **pItems,int count) const if (b_found) continue; + if(pProto->BagFamily & BAG_FAMILY_MASK_VANITY_PETS) + { + for(uint32 t = VANITYPET_SLOT_START; t < VANITYPET_SLOT_END; ++t) + { + if( inv_pets[t-VANITYPET_SLOT_START] == 0 ) + { + inv_pets[t-VANITYPET_SLOT_START] = 1; + b_found = true; + break; + } + } + } + + if (b_found) continue; + + if(pProto->BagFamily & BAG_FAMILY_MASK_CURRENCY_TOKENS) + { + for(uint32 t = CURRENCYTOKEN_SLOT_START; t < CURRENCYTOKEN_SLOT_END; ++t) + { + if( inv_tokens[t-CURRENCYTOKEN_SLOT_START] == 0 ) + { + inv_tokens[t-CURRENCYTOKEN_SLOT_START] = 1; + b_found = true; + break; + } + } + } + + if (b_found) continue; + + if(pProto->BagFamily & BAG_FAMILY_MASK_QUEST_ITEMS) + { + for(uint32 t = QUESTBAG_SLOT_START; t < QUESTBAG_SLOT_END; ++t) + { + if( inv_quests[t-QUESTBAG_SLOT_START] == 0 ) + { + inv_quests[t-QUESTBAG_SLOT_START] = 1; + b_found = true; + break; + } + } + } + + if (b_found) continue; + for(int t = INVENTORY_SLOT_BAG_START; !b_found && t < INVENTORY_SLOT_BAG_END; t++) { pBag = (Bag*)GetItemByPos( INVENTORY_SLOT_BAG_0, t ); @@ -9308,10 +9698,10 @@ uint8 Player::CanStoreItems( Item **pItems,int count) const } ////////////////////////////////////////////////////////////////////////// -uint8 Player::CanEquipNewItem( uint8 slot, uint16 &dest, uint32 item, uint32 count, bool swap ) const +uint8 Player::CanEquipNewItem( uint8 slot, uint16 &dest, uint32 item, bool swap ) const { dest = 0; - Item *pItem = Item::CreateItem( item, count, this ); + Item *pItem = Item::CreateItem( item, 1, this ); if( pItem ) { uint8 result = CanEquipItem(slot, dest, pItem, swap ); @@ -9427,33 +9817,42 @@ uint8 Player::CanEquipItem( uint8 slot, uint16 &dest, Item *pItem, bool swap, bo if(eslot == EQUIPMENT_SLOT_OFFHAND) { - if( type == INVTYPE_WEAPON || type == INVTYPE_WEAPONOFFHAND ) + if (type == INVTYPE_WEAPON || type == INVTYPE_WEAPONOFFHAND) { if(!CanDualWield()) return EQUIP_ERR_CANT_DUAL_WIELD; } - - Item *mainItem = GetItemByPos( INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_MAINHAND ); - if(mainItem) + else if (type == INVTYPE_2HWEAPON) { - if(mainItem->GetProto()->InventoryType == INVTYPE_2HWEAPON) - return EQUIP_ERR_CANT_EQUIP_WITH_TWOHANDED; + if(!CanDualWield() || !CanTitanGrip()) + return EQUIP_ERR_CANT_DUAL_WIELD; } + + if(IsTwoHandUsed()) + return EQUIP_ERR_CANT_EQUIP_WITH_TWOHANDED; } // equip two-hand weapon case (with possible unequip 2 items) if( type == INVTYPE_2HWEAPON ) { - if(eslot != EQUIPMENT_SLOT_MAINHAND) + if (eslot == EQUIPMENT_SLOT_OFFHAND) + { + if (!CanTitanGrip()) + return EQUIP_ERR_ITEM_CANT_BE_EQUIPPED; + } + else if (eslot != EQUIPMENT_SLOT_MAINHAND) return EQUIP_ERR_ITEM_CANT_BE_EQUIPPED; - // offhand item must can be stored in inventory for offhand item and it also must be unequipped - Item *offItem = GetItemByPos( INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_OFFHAND ); - ItemPosCountVec off_dest; - if( offItem && (!not_loading || - CanUnequipItem(uint16(INVENTORY_SLOT_BAG_0) << 8 | EQUIPMENT_SLOT_OFFHAND,false) != EQUIP_ERR_OK || - CanStoreItem( NULL_BAG, NULL_SLOT, off_dest, offItem, false ) != EQUIP_ERR_OK ) ) - return swap ? EQUIP_ERR_ITEMS_CANT_BE_SWAPPED : EQUIP_ERR_INVENTORY_FULL; + if (!CanTitanGrip()) + { + // offhand item must can be stored in inventory for offhand item and it also must be unequipped + Item *offItem = GetItemByPos( INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_OFFHAND ); + ItemPosCountVec off_dest; + if( offItem && (!not_loading || + CanUnequipItem(uint16(INVENTORY_SLOT_BAG_0) << 8 | EQUIPMENT_SLOT_OFFHAND,false) != EQUIP_ERR_OK || + CanStoreItem( NULL_BAG, NULL_SLOT, off_dest, offItem, false ) != EQUIP_ERR_OK ) ) + return swap ? EQUIP_ERR_ITEMS_CANT_BE_SWAPPED : EQUIP_ERR_INVENTORY_FULL; + } } dest = ((INVENTORY_SLOT_BAG_0 << 8) | eslot); return EQUIP_ERR_OK; @@ -9975,12 +10374,12 @@ Item* Player::_StoreItem( uint16 pos, Item *pItem, uint32 count, bool clone, boo } } -Item* Player::EquipNewItem( uint16 pos, uint32 item, uint32 count, bool update ) +Item* Player::EquipNewItem( uint16 pos, uint32 item, bool update ) { - Item *pItem = Item::CreateItem( item, count, this ); + Item *pItem = Item::CreateItem( item, 1, this ); if( pItem ) { - ItemAddedQuestCheck( item, count ); + ItemAddedQuestCheck( item, 1 ); Item * retItem = EquipItem( pos, pItem, update ); return retItem; @@ -10373,7 +10772,7 @@ void Player::DestroyItemCount( uint32 item, uint32 count, bool update, bool uneq } } } - for(int i = KEYRING_SLOT_START; i < KEYRING_SLOT_END; i++) + for(int i = KEYRING_SLOT_START; i < QUESTBAG_SLOT_END; i++) { pItem = GetItemByPos( INVENTORY_SLOT_BAG_0, i ); if( pItem && pItem->GetEntry() == item ) @@ -10476,7 +10875,7 @@ void Player::DestroyZoneLimitedItem( bool update, uint32 new_zone ) if( pItem && pItem->IsLimitedToAnotherMapOrZone(GetMapId(),new_zone) ) DestroyItem( INVENTORY_SLOT_BAG_0, i, update); } - for(int i = KEYRING_SLOT_START; i < KEYRING_SLOT_END; i++) + for(int i = KEYRING_SLOT_START; i < QUESTBAG_SLOT_END; i++) { Item* pItem = GetItemByPos( INVENTORY_SLOT_BAG_0, i ); if( pItem && pItem->IsLimitedToAnotherMapOrZone(GetMapId(),new_zone) ) @@ -11272,9 +11671,9 @@ void Player::ApplyEnchantment(Item *item,EnchantmentSlot slot,bool apply, bool a { if(apply) { - int32 basepoints = int32(enchant_amount); + int32 basepoints = 0; // Random Property Exist - try found basepoints for spell (basepoints depends from item suffix factor) - if (item->GetItemRandomPropertyId() !=0 && !enchant_amount) + if (item->GetItemRandomPropertyId()) { ItemRandomSuffixEntry const *item_rand = sItemRandomSuffixStore.LookupEntry(abs(item->GetItemRandomPropertyId())); if (item_rand) @@ -11473,6 +11872,10 @@ void Player::ApplyEnchantment(Item *item,EnchantmentSlot slot,bool apply, bool a ((Player*)this)->ApplyRatingMod(CR_EXPERTISE, enchant_amount, apply); sLog.outDebug("+ %u EXPERTISE", enchant_amount); break; + case ITEM_MOD_ARMOR_PENETRATION_RATING: + ((Player*)this)->ApplyRatingMod(CR_ARMOR_PENETRATION, enchant_amount, apply); + sLog.outDebug("+ %u ARMOR PENETRATION", enchant_amount); + break; default: break; } @@ -12195,7 +12598,10 @@ void Player::RewardQuest( Quest const *pQuest, uint32 reward, Object* questGiver } if(pQuest->IsDaily()) + { SetDailyQuestStatus(quest_id); + GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_DAILY_QUEST, 1); + } if ( !pQuest->IsRepeatable() ) SetQuestStatus(quest_id, QUEST_STATUS_COMPLETE); @@ -12208,6 +12614,8 @@ void Player::RewardQuest( Quest const *pQuest, uint32 reward, Object* questGiver SendQuestReward( pQuest, XP, questGiver ); if (q_status.uState != QUEST_NEW) q_status.uState = QUEST_CHANGED; + GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_QUEST_COUNT); + GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_QUEST); } void Player::FailQuest( uint32 quest_id ) @@ -12833,6 +13241,7 @@ void Player::ItemAddedQuestCheck( uint32 entry, uint32 count ) } } UpdateForQuestsGO(); + GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_OWN_ITEM, entry); } void Player::ItemRemovedQuestCheck( uint32 entry, uint32 count ) @@ -12879,6 +13288,7 @@ void Player::ItemRemovedQuestCheck( uint32 entry, uint32 count ) void Player::KilledMonster( uint32 entry, uint64 guid ) { uint32 addkillcount = 1; + GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_KILL_CREATURE, entry, addkillcount); for( int i = 0; i < MAX_QUEST_LOG_SIZE; i++ ) { uint32 questid = GetQuestSlotQuestId(i); @@ -13155,13 +13565,12 @@ void Player::SendQuestReward( Quest const *pQuest, uint32 XP, Object * questGive { uint32 questid = pQuest->GetQuestId(); sLog.outDebug( "WORLD: Sent SMSG_QUESTGIVER_QUEST_COMPLETE quest = %u", questid ); - WorldPacket data( SMSG_QUESTGIVER_QUEST_COMPLETE, (4+4+4+4+4+4+pQuest->GetRewItemsCount()*8) ); - data << questid; - data << uint32(0x03); + WorldPacket data( SMSG_QUESTGIVER_QUEST_COMPLETE, (4+4+4+4+4) ); + data << uint32(questid); if ( getLevel() < sWorld.getConfig(CONFIG_MAX_PLAYER_LEVEL) ) { - data << XP; + data << uint32(XP); data << uint32(pQuest->GetRewOrReqMoney()); } else @@ -13169,16 +13578,9 @@ void Player::SendQuestReward( Quest const *pQuest, uint32 XP, Object * questGive data << uint32(0); data << uint32(pQuest->GetRewOrReqMoney() + int32(pQuest->GetRewMoneyMaxLevel() * sWorld.getRate(RATE_DROP_MONEY))); } - data << uint32(0); // new 2.3.0, HonorPoints? - data << uint32( pQuest->GetRewItemsCount() ); // max is 5 - for (uint32 i = 0; i < pQuest->GetRewItemsCount(); ++i) - { - if ( pQuest->RewItemId[i] > 0 ) - data << pQuest->RewItemId[i] << pQuest->RewItemCount[i]; - else - data << uint32(0) << uint32(0); - } + data << uint32(10*MaNGOS::Honor::hk_honor_at_level(getLevel(), pQuest->GetRewHonorableKills())); + data << uint32(pQuest->GetBonusTalents()); // bonus talents GetSession()->SendPacket( &data ); if (pQuest->GetQuestCompleteScript() != 0) @@ -13189,8 +13591,9 @@ void Player::SendQuestFailed( uint32 quest_id ) { if( quest_id ) { - WorldPacket data( SMSG_QUESTGIVER_QUEST_FAILED, 4 ); + WorldPacket data( SMSG_QUESTGIVER_QUEST_FAILED, 4+4 ); data << quest_id; + data << uint32(0); // failed reason (4 for inventory is full) GetSession()->SendPacket( &data ); sLog.outDebug("WORLD: Sent SMSG_QUESTGIVER_QUEST_FAILED"); } @@ -13229,10 +13632,10 @@ void Player::SendPushToPartyResponse( Player *pPlayer, uint32 msg ) void Player::SendQuestUpdateAddItem( Quest const* pQuest, uint32 item_idx, uint32 count ) { - WorldPacket data( SMSG_QUESTUPDATE_ADD_ITEM, (4+4) ); + WorldPacket data( SMSG_QUESTUPDATE_ADD_ITEM, 0 ); sLog.outDebug( "WORLD: Sent SMSG_QUESTUPDATE_ADD_ITEM" ); - data << pQuest->ReqItemId[item_idx]; - data << count; + //data << pQuest->ReqItemId[item_idx]; + //data << count; GetSession()->SendPacket( &data ); } @@ -13278,7 +13681,7 @@ bool Player::MinimalLoadFromDB( QueryResult *result, uint32 guid ) if(!LoadValues( fields[1].GetString())) { - sLog.outError("ERROR: Player #%d have broken data in `data` field. Can't be loaded.",GUID_LOPART(guid)); + sLog.outError("ERROR: Player #%d have broken data in `data` field. Can't be loaded for character list.",GUID_LOPART(guid)); if(delete_result) delete result; return false; } @@ -13329,6 +13732,41 @@ void Player::_LoadDeclinedNames(QueryResult* result) delete result; } +void Player::_LoadArenaTeamInfo(QueryResult *result) +{ + // arenateamid, played_week, played_season, personal_rating + memset((void*)&m_uint32Values[PLAYER_FIELD_ARENA_TEAM_INFO_1_1], 0, sizeof(uint32)*18); + if (!result) + return; + + do + { + Field *fields = result->Fetch(); + + uint32 arenateamid = fields[0].GetUInt32(); + uint32 played_week = fields[1].GetUInt32(); + uint32 played_season = fields[2].GetUInt32(); + uint32 personal_rating = fields[3].GetUInt32(); + + ArenaTeam* aTeam = objmgr.GetArenaTeamById(arenateamid); + if(!aTeam) + { + sLog.outError("Player::_LoadArenaTeamInfo: couldn't load arenateam %u, week %u, season %u, rating %u", arenateamid, played_week, played_season, personal_rating); + continue; + } + uint8 arenaSlot = aTeam->GetSlot(); + + m_uint32Values[PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + arenaSlot * 6] = arenateamid; // TeamID + m_uint32Values[PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + arenaSlot * 6 + 1] = ((aTeam->GetCaptain() == GetGUID()) ? (uint32)0 : (uint32)1); // Captain 0, member 1 + m_uint32Values[PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + arenaSlot * 6 + 2] = played_week; // Played Week + m_uint32Values[PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + arenaSlot * 6 + 3] = played_season; // Played Season + m_uint32Values[PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + arenaSlot * 6 + 4] = 0; // Unk + m_uint32Values[PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + arenaSlot * 6 + 5] = personal_rating; // Personal Rating + + }while (result->NextRow()); + delete result; +} + bool Player::LoadPositionFromDB(uint32& mapid, float& x,float& y,float& z,float& o, bool& in_flight, uint64 guid) { QueryResult *result = CharacterDatabase.PQuery("SELECT position_x,position_y,position_z,orientation,map,taxi_path FROM characters WHERE guid = '%u'",GUID_LOPART(guid)); @@ -13400,8 +13838,8 @@ float Player::GetFloatValueFromDB(uint16 index, uint64 guid) bool Player::LoadFromDB( uint32 guid, SqlQueryHolder *holder ) { - //// 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 [28] [29] 30 31 32 - //QueryResult *result = CharacterDatabase.PQuery("SELECT guid, account, data, name, race, class, position_x, position_y, position_z, map, orientation, taximask, cinematic, totaltime, leveltime, rest_bonus, logout_time, is_logout_resting, resettalents_cost, resettalents_time, trans_x, trans_y, trans_z, trans_o, transguid, extra_flags, stable_slots, at_login, zone, online, death_expire_time, taxi_path, dungeon_difficulty FROM characters WHERE guid = '%u'", guid); + //// 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 [28] [29] 30 31 32 33 + //QueryResult *result = CharacterDatabase.PQuery("SELECT guid, account, data, name, race, class, position_x, position_y, position_z, map, orientation, taximask, cinematic, totaltime, leveltime, rest_bonus, logout_time, is_logout_resting, resettalents_cost, resettalents_time, trans_x, trans_y, trans_z, trans_o, transguid, extra_flags, stable_slots, at_login, zone, online, death_expire_time, taxi_path, dungeon_difficulty, arena_pending_points FROM characters WHERE guid = '%u'", guid); QueryResult *result = holder->GetResult(PLAYER_LOGIN_QUERY_LOADFROM); if(!result) @@ -13485,11 +13923,20 @@ bool Player::LoadFromDB( uint32 guid, SqlQueryHolder *holder ) uint32 transGUID = fields[24].GetUInt32(); Relocate(fields[6].GetFloat(),fields[7].GetFloat(),fields[8].GetFloat(),fields[10].GetFloat()); + SetFallInformation(0, fields[8].GetFloat()); SetMapId(fields[9].GetUInt32()); SetDifficulty(fields[32].GetUInt32()); // may be changed in _LoadGroup _LoadGroup(holder->GetResult(PLAYER_LOGIN_QUERY_LOADGROUP)); + _LoadArenaTeamInfo(holder->GetResult(PLAYER_LOGIN_QUERY_LOADARENAINFO)); + + uint32 arena_currency = GetUInt32Value(PLAYER_FIELD_ARENA_CURRENCY) + fields[33].GetUInt32(); + if (arena_currency > sWorld.getConfig(CONFIG_MAX_ARENA_POINTS)) + arena_currency = sWorld.getConfig(CONFIG_MAX_ARENA_POINTS); + + SetUInt32Value(PLAYER_FIELD_ARENA_CURRENCY, arena_currency); + // check arena teams integrity for(uint32 arena_slot = 0; arena_slot < MAX_ARENA_SLOT; ++arena_slot) { @@ -13639,10 +14086,10 @@ bool Player::LoadFromDB( uint32 guid, SqlQueryHolder *holder ) uint32 extraflags = fields[25].GetUInt32(); m_stableSlots = fields[26].GetUInt32(); - if(m_stableSlots > 2) + if(m_stableSlots > 4) { - sLog.outError("Player can have not more 2 stable slots, but have in DB %u",uint32(m_stableSlots)); - m_stableSlots = 2; + sLog.outError("Player can have not more 4 stable slots, but have in DB %u",uint32(m_stableSlots)); + m_stableSlots = 4; } m_atLoginFlags = fields[27].GetUInt32(); @@ -13711,6 +14158,8 @@ bool Player::LoadFromDB( uint32 guid, SqlQueryHolder *holder ) // reset stats before loading any modifiers InitStatsForLevel(); InitTaxiNodesForLevel(); + InitGlyphsForLevel(); + InitRunes(); // apply original stats mods before spell loading or item equipment that call before equip _RemoveStatsMods() @@ -13867,6 +14316,8 @@ bool Player::LoadFromDB( uint32 guid, SqlQueryHolder *holder ) _LoadDeclinedNames(holder->GetResult(PLAYER_LOGIN_QUERY_LOADDECLINEDNAMES)); + m_achievementMgr.LoadFromDB(holder->GetResult(PLAYER_LOGIN_QUERY_LOADACHIEVEMENTS), holder->GetResult(PLAYER_LOGIN_QUERY_LOADCRITERIAPROGRESS)); + m_achievementMgr.CheckAllAchievementCriteria(); return true; } @@ -13920,10 +14371,6 @@ void Player::_LoadAuras(QueryResult *result, uint32 timediff) for (int i = 0; i < TOTAL_AURAS; i++) m_modAuras[i].clear(); - // all aura related fields - for(int i = UNIT_FIELD_AURA; i <= UNIT_FIELD_AURASTATE; ++i) - SetUInt32Value(i, 0); - //QueryResult *result = CharacterDatabase.PQuery("SELECT caster_guid,spell,effect_index,stackcount,amount,maxduration,remaintime,remaincharges FROM character_aura WHERE guid = '%u'",GetGUIDLow()); if(result) @@ -14812,8 +15259,10 @@ void Player::SaveToDB() // first save/honor gain after midnight will also update the player's honor fields UpdateHonorFields(); - // Must saved before enter into BattleGround - if(InBattleGround()) + // players aren't saved on battleground maps + uint32 mapid = IsBeingTeleported() ? GetTeleportDest().mapid : GetMapId(); + const MapEntry * me = sMapStore.LookupEntry(mapid); + if(!me || me->IsBattleGroundOrArena()) return; int is_save_resting = HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_RESTING) ? 1 : 0; @@ -14833,7 +15282,7 @@ void Player::SaveToDB() SetByteValue(UNIT_FIELD_BYTES_1, 0, 0); // stand state SetByteValue(UNIT_FIELD_BYTES_2, 3, 0); // shapeshift SetByteValue(UNIT_FIELD_BYTES_1, 3, 0); // stand flags? - RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_ROTATE); + RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_STUNNED); SetDisplayId(GetNativeDisplayId()); bool inworld = IsInWorld(); @@ -14851,7 +15300,7 @@ void Player::SaveToDB() "taximask, online, cinematic, " "totaltime, leveltime, rest_bonus, logout_time, is_logout_resting, resettalents_cost, resettalents_time, " "trans_x, trans_y, trans_z, trans_o, transguid, extra_flags, stable_slots, at_login, zone, " - "death_expire_time, taxi_path) VALUES (" + "death_expire_time, taxi_path, arena_pending_points) VALUES (" << GetGUIDLow() << ", " << GetSession()->GetAccountId() << ", '" << sql_name << "', " @@ -14950,7 +15399,7 @@ void Player::SaveToDB() ss << ", '"; ss << m_taxi.SaveTaxiDestinationsToString(); - ss << "' )"; + ss << "', '0' )"; CharacterDatabase.Execute( ss.str().c_str() ); @@ -14979,6 +15428,7 @@ void Player::SaveToDB() // save pet (hunter pet level and experience and all type pets health/mana). if(Pet* pet = GetPet()) pet->SavePetToDB(PET_SAVE_AS_CURRENT); + m_achievementMgr.SaveToDB(); } // fast save function for item/money cheating preventing - save only inventory and money state @@ -15439,6 +15889,42 @@ void Player::SetFloatValueInDB(uint16 index, float value, uint64 guid) Player::SetUInt32ValueInDB(index, temp, guid); } +void Player::Customize(uint64 guid, uint8 gender, uint8 skin, uint8 face, uint8 hairStyle, uint8 hairColor, uint8 facialHair) +{ + Tokens tokens; + if(!LoadValuesArrayFromDB(tokens, guid)) + return; + + uint32 unit_bytes0 = GetUInt32ValueFromArray(tokens, UNIT_FIELD_BYTES_0); + uint8 race = unit_bytes0 & 0xFF; + uint8 class_ = (unit_bytes0 >> 8) & 0xFF; + + PlayerInfo const* info = objmgr.GetPlayerInfo(race, class_); + if(!info) + return; + + unit_bytes0 &= ~(0xFF << 16); + unit_bytes0 |= (gender << 16); + SetUInt32ValueInArray(tokens, UNIT_FIELD_BYTES_0, unit_bytes0); + + SetUInt32ValueInArray(tokens, UNIT_FIELD_DISPLAYID, gender ? info->displayId_f : info->displayId_m); + SetUInt32ValueInArray(tokens, UNIT_FIELD_NATIVEDISPLAYID, gender ? info->displayId_f : info->displayId_m); + + SetUInt32ValueInArray(tokens, PLAYER_BYTES, (skin | (face << 8) | (hairStyle << 16) | (hairColor << 24))); + + uint32 player_bytes2 = GetUInt32ValueFromArray(tokens, PLAYER_BYTES_2); + player_bytes2 &= ~0xFF; + player_bytes2 |= facialHair; + SetUInt32ValueInArray(tokens, PLAYER_BYTES_2, player_bytes2); + + uint32 player_bytes3 = GetUInt32ValueFromArray(tokens, PLAYER_BYTES_3); + player_bytes3 &= ~0xFF; + player_bytes3 |= gender; + SetUInt32ValueInArray(tokens, PLAYER_BYTES_3, player_bytes3); + + SaveValuesArrayInDB(tokens, guid); +} + void Player::SendAttackSwingNotStanding() { WorldPacket data(SMSG_ATTACKSWING_NOTSTANDING, 0); @@ -15471,7 +15957,8 @@ void Player::SendAttackSwingBadFacingAttack() void Player::SendAutoRepeatCancel() { - WorldPacket data(SMSG_CANCEL_AUTO_REPEAT, 0); + WorldPacket data(SMSG_CANCEL_AUTO_REPEAT, GetPackGUID().size()); + data.append(GetPackGUID()); // may be it's target guid GetSession()->SendPacket( &data ); } @@ -15696,6 +16183,7 @@ void Player::RemovePet(Pet* pet, PetSaveMode mode, bool returnreagent) { WorldPacket data(SMSG_PET_SPELLS, 8); data << uint64(0); + data << uint32(0); GetSession()->SendPacket(&data); if(GetGroup()) @@ -15752,7 +16240,7 @@ void Player::Uncharm() charm->RemoveSpellsCausingAura(SPELL_AURA_MOD_POSSESS); } -void Player::BuildPlayerChat(WorldPacket *data, uint8 msgtype, std::string text, uint32 language) const +void Player::BuildPlayerChat(WorldPacket *data, uint8 msgtype, const std::string& text, uint32 language) const { *data << (uint8)msgtype; *data << (uint32)language; @@ -15764,28 +16252,28 @@ void Player::BuildPlayerChat(WorldPacket *data, uint8 msgtype, std::string text, *data << (uint8)chatTag(); } -void Player::Say(const std::string text, const uint32 language) +void Player::Say(const std::string& text, const uint32 language) { WorldPacket data(SMSG_MESSAGECHAT, 200); BuildPlayerChat(&data, CHAT_MSG_SAY, text, language); SendMessageToSetInRange(&data,sWorld.getConfig(CONFIG_LISTEN_RANGE_SAY),true); } -void Player::Yell(const std::string text, const uint32 language) +void Player::Yell(const std::string& text, const uint32 language) { WorldPacket data(SMSG_MESSAGECHAT, 200); BuildPlayerChat(&data, CHAT_MSG_YELL, text, language); SendMessageToSetInRange(&data,sWorld.getConfig(CONFIG_LISTEN_RANGE_YELL),true); } -void Player::TextEmote(const std::string text) +void Player::TextEmote(const std::string& text) { WorldPacket data(SMSG_MESSAGECHAT, 200); BuildPlayerChat(&data, CHAT_MSG_EMOTE, text, LANG_UNIVERSAL); SendMessageToSetInRange(&data,sWorld.getConfig(CONFIG_LISTEN_RANGE_TEXTEMOTE),true, !sWorld.getConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_CHAT) ); } -void Player::Whisper(std::string text, uint32 language,uint64 receiver) +void Player::Whisper(const std::string& text, uint32 language,uint64 receiver) { if (language != LANG_ADDON) // if not addon data language = LANG_UNIVERSAL; // whispers should always be readable @@ -15828,65 +16316,79 @@ void Player::PetSpellInitialize() { Pet* pet = GetPet(); - if(pet) + if(!pet) + return; + + sLog.outDebug("Pet Spells Groups"); + + CharmInfo *charmInfo = pet->GetCharmInfo(); + + WorldPacket data(SMSG_PET_SPELLS, 8+4+4+4+10*4); + data << uint64(pet->GetGUID()); + data << uint32(pet->GetCreatureInfo()->family); // creature family (required for pet talents) + data << uint32(0); + data << uint8(charmInfo->GetReactState()) << uint8(charmInfo->GetCommandState()) << uint16(0); + + // action bar loop + for(uint32 i = 0; i < 10; i++) { - uint8 addlist = 0; - - sLog.outDebug("Pet Spells Groups"); - - CreatureInfo const *cinfo = pet->GetCreatureInfo(); - - if(pet->isControlled() && (pet->getPetType() == HUNTER_PET || cinfo && cinfo->type == CREATURE_TYPE_DEMON && getClass() == CLASS_WARLOCK)) - { - for(PetSpellMap::iterator itr = pet->m_spells.begin();itr != pet->m_spells.end();++itr) - { - if(itr->second->state == PETSPELL_REMOVED) - continue; - ++addlist; - } - } - - // first line + actionbar + spellcount + spells + last adds - WorldPacket data(SMSG_PET_SPELLS, 16+40+1+4*addlist+25); - - CharmInfo *charmInfo = pet->GetCharmInfo(); - - //16 - data << (uint64)pet->GetGUID() << uint32(0x00000000) << uint8(charmInfo->GetReactState()) << uint8(charmInfo->GetCommandState()) << uint16(0); - - for(uint32 i = 0; i < 10; i++) //40 - { - data << uint16(charmInfo->GetActionBarEntry(i)->SpellOrAction) << uint16(charmInfo->GetActionBarEntry(i)->Type); - } - - data << uint8(addlist); //1 - - if(addlist && pet->isControlled()) - { - for (PetSpellMap::iterator itr = pet->m_spells.begin(); itr != pet->m_spells.end(); ++itr) - { - if(itr->second->state == PETSPELL_REMOVED) - continue; - - data << uint16(itr->first); - data << uint16(itr->second->active); // pet spell active state isn't boolean - } - } - - //data << uint8(0x01) << uint32(0x6010) << uint32(0x01) << uint32(0x05) << uint16(0x00); //15 - uint8 count = 3; //1+8+8+8=25 - - // if count = 0, then end of packet... - data << count; - // uint32 value is spell id... - // uint64 value is constant 0, unknown... - data << uint32(0x6010) << uint64(0); // if count = 1, 2 or 3 - //data << uint32(0x5fd1) << uint64(0); // if count = 2 - data << uint32(0x8e8c) << uint64(0); // if count = 3 - data << uint32(0x8e8b) << uint64(0); // if count = 3 - - GetSession()->SendPacket(&data); + data << uint32(charmInfo->GetActionBarEntry(i)->Raw); } + + size_t spellsCountPos = data.wpos(); + + // spells count + uint8 addlist = 0; + data << uint8(addlist); // placeholder + + if(pet->isControlled() && ((pet->getPetType() == HUNTER_PET) || ((pet->GetCreatureInfo()->type == CREATURE_TYPE_DEMON) && (getClass() == CLASS_WARLOCK)))) + { + // spells loop + for (PetSpellMap::iterator itr = pet->m_spells.begin(); itr != pet->m_spells.end(); ++itr) + { + if(itr->second->state == PETSPELL_REMOVED) + continue; + + data << uint16(itr->first); + data << uint16(itr->second->active); // pet spell active state isn't boolean + ++addlist; + } + } + + data.put(spellsCountPos, addlist); + + uint8 cooldownsCount = pet->m_CreatureSpellCooldowns.size() + pet->m_CreatureCategoryCooldowns.size(); + data << uint8(cooldownsCount); + + time_t curTime = time(NULL); + + for(CreatureSpellCooldowns::const_iterator itr = pet->m_CreatureSpellCooldowns.begin(); itr != pet->m_CreatureSpellCooldowns.end(); ++itr) + { + time_t cooldown = 0; + + if(itr->second > curTime) + cooldown = (itr->second - curTime) * 1000; + + data << uint16(itr->first); // spellid + data << uint16(0); // spell category? + data << uint32(itr->second); // cooldown + data << uint32(0); // category cooldown + } + + for(CreatureSpellCooldowns::const_iterator itr = pet->m_CreatureCategoryCooldowns.begin(); itr != pet->m_CreatureCategoryCooldowns.end(); ++itr) + { + time_t cooldown = 0; + + if(itr->second > curTime) + cooldown = (itr->second - curTime) * 1000; + + data << uint16(itr->first); // spellid + data << uint16(0); // spell category? + data << uint32(0); // cooldown + data << uint32(itr->second); // category cooldown + } + + GetSession()->SendPacket(&data); } void Player::PossessSpellInitialize() @@ -15908,7 +16410,10 @@ void Player::PossessSpellInitialize() WorldPacket data(SMSG_PET_SPELLS, 16+40+1+4*addlist+25);// first line + actionbar + spellcount + spells + last adds //16 - data << (uint64)charm->GetGUID() << uint32(0x00000000) << uint8(0) << uint8(0) << uint16(0); + data << uint64(charm->GetGUID()); + data << uint32(0x00000000); + data << uint32(0); + data << uint8(0) << uint8(0) << uint16(0); for(uint32 i = 0; i < 10; i++) //40 { @@ -15917,11 +16422,8 @@ void Player::PossessSpellInitialize() data << uint8(addlist); //1 - uint8 count = 3; - data << count; - data << uint32(0x6010) << uint64(0); // if count = 1, 2 or 3 - data << uint32(0x8e8c) << uint64(0); // if count = 3 - data << uint32(0x8e8b) << uint64(0); // if count = 3 + uint8 count = 0; + data << uint8(count); // cooldowns count GetSession()->SendPacket(&data); } @@ -15958,13 +16460,13 @@ void Player::CharmSpellInitialize() WorldPacket data(SMSG_PET_SPELLS, 16+40+1+4*addlist+25);// first line + actionbar + spellcount + spells + last adds - data << (uint64)charm->GetGUID() << uint32(0x00000000); - + data << uint64(charm->GetGUID()); + data << uint32(0x00000000); + data << uint32(0); if(charm->GetTypeId() != TYPEID_PLAYER) data << uint8(charmInfo->GetReactState()) << uint8(charmInfo->GetCommandState()); else data << uint8(0) << uint8(0); - data << uint16(0); for(uint32 i = 0; i < 10; i++) //40 @@ -15987,51 +16489,12 @@ void Player::CharmSpellInitialize() } } - uint8 count = 3; - data << count; - data << uint32(0x6010) << uint64(0); // if count = 1, 2 or 3 - data << uint32(0x8e8c) << uint64(0); // if count = 3 - data << uint32(0x8e8b) << uint64(0); // if count = 3 + uint8 count = 0; + data << uint8(count); // cooldowns count GetSession()->SendPacket(&data); } -int32 Player::GetTotalFlatMods(uint32 spellId, SpellModOp op) -{ - SpellEntry const *spellInfo = sSpellStore.LookupEntry(spellId); - if (!spellInfo) return 0; - int32 total = 0; - for (SpellModList::iterator itr = m_spellMods[op].begin(); itr != m_spellMods[op].end(); ++itr) - { - SpellModifier *mod = *itr; - - if(!IsAffectedBySpellmod(spellInfo,mod)) - continue; - - if (mod->type == SPELLMOD_FLAT) - total += mod->value; - } - return total; -} - -int32 Player::GetTotalPctMods(uint32 spellId, SpellModOp op) -{ - SpellEntry const *spellInfo = sSpellStore.LookupEntry(spellId); - if (!spellInfo) return 0; - int32 total = 0; - for (SpellModList::iterator itr = m_spellMods[op].begin(); itr != m_spellMods[op].end(); ++itr) - { - SpellModifier *mod = *itr; - - if(!IsAffectedBySpellmod(spellInfo,mod)) - continue; - - if (mod->type == SPELLMOD_PCT) - total += mod->value; - } - return total; -} - bool Player::IsAffectedBySpellmod(SpellEntry const *spellInfo, SpellModifier *mod, Spell const* spell) { if (!mod || !spellInfo) @@ -16049,22 +16512,25 @@ bool Player::IsAffectedBySpellmod(SpellEntry const *spellInfo, SpellModifier *mo return false; } - return spellmgr.IsAffectedBySpell(spellInfo,mod->spellId,mod->effectId,mod->mask); + return spellmgr.IsAffectedByMod(spellInfo, mod); } void Player::AddSpellMod(SpellModifier* mod, bool apply) { uint16 Opcode= (mod->type == SPELLMOD_FLAT) ? SMSG_SET_FLAT_SPELL_MODIFIER : SMSG_SET_PCT_SPELL_MODIFIER; - for(int eff=0;eff<64;++eff) + for(int eff=0;eff<96;++eff) { - uint64 _mask = uint64(1) << eff; - if ( mod->mask & _mask) + uint64 _mask = 0; + uint64 _mask2= 0; + if (eff<64) _mask = uint64(1) << (eff- 0); + else _mask2= uint64(1) << (eff-64); + if ( mod->mask & _mask || mod->mask2 & _mask2) { int32 val = 0; for (SpellModList::iterator itr = m_spellMods[mod->op].begin(); itr != m_spellMods[mod->op].end(); ++itr) { - if ((*itr)->type == mod->type && (*itr)->mask & _mask) + if ((*itr)->type == mod->type && ((*itr)->mask & _mask || (*itr)->mask2 & _mask2)) val += (*itr)->value; } val += apply ? mod->value : -(mod->value); @@ -16230,7 +16696,7 @@ void Player::HandleStealthedUnitsDetection() // target aura duration for caster show only if target exist at caster client // send data at target visibility change (adding to client) if((*i)!=this && (*i)->isType(TYPEMASK_UNIT)) - SendAuraDurationsForTarget(*i); + SendAurasForTarget(*i); i = stealthedUnits.erase(i); continue; @@ -16636,8 +17102,14 @@ bool Player::BuyItemFromVendor(uint64 vendorguid, uint32 item, uint8 count, uint } else if( IsEquipmentPos( bag, slot ) ) { + if(pProto->BuyCount * count != 1) + { + SendEquipError( EQUIP_ERR_ITEM_CANT_BE_EQUIPPED, NULL, NULL ); + return false; + } + uint16 dest; - uint8 msg = CanEquipNewItem( slot, dest, item, pProto->BuyCount * count, false ); + uint8 msg = CanEquipNewItem( slot, dest, item, false ); if( msg != EQUIP_ERR_OK ) { SendEquipError( msg, NULL, NULL ); @@ -16659,7 +17131,7 @@ bool Player::BuyItemFromVendor(uint64 vendorguid, uint32 item, uint8 count, uint } } - if(Item *it = EquipNewItem( dest, item, pProto->BuyCount * count, true )) + if(Item *it = EquipNewItem( dest, item, true )) { uint32 new_count = pCreature->UpdateVendorItemCurrentCount(crItem,pProto->BuyCount * count); @@ -17107,7 +17579,7 @@ void Player::UpdateVisibilityOf(WorldObject* target) // target aura duration for caster show only if target exist at caster client // send data at target visibility change (adding to client) if(target!=this && target->isType(TYPEMASK_UNIT)) - SendAuraDurationsForTarget((Unit*)target); + SendAurasForTarget((Unit*)target); if(target->GetTypeId()==TYPEID_UNIT && ((Creature*)target)->isAlive()) ((Creature*)target)->SendMonsterMoveWithSpeedToCurrentDestination(this); @@ -17246,7 +17718,7 @@ void Player::SetGroup(Group *group, int8 subgroup) void Player::SendInitialPacketsBeforeAddToMap() { - WorldPacket data(SMSG_SET_REST_START, 4); + WorldPacket data(SMSG_SET_REST_START_OBSOLETE, 4); data << uint32(0); // unknown, may be rest state time or experience GetSession()->SendPacket(&data); @@ -17274,6 +17746,7 @@ void Player::SendInitialPacketsBeforeAddToMap() SendInitialActionButtons(); SendInitialReputations(); + m_achievementMgr.SendAllAchievementData(); UpdateZone(GetZoneId()); SendInitWorldStates(); @@ -17284,13 +17757,23 @@ void Player::SendInitialPacketsBeforeAddToMap() data << (float)0.01666667f; // game speed GetSession()->SendPacket( &data ); + data.Initialize(SMSG_TIME_SYNC_REQ, 4); // new 2.0.x, enable movement + data << uint32(0x00000000); // on blizz it increments periodically + GetSession()->SendPacket(&data); + // set fly flag if in fly form or taxi flight to prevent visually drop at ground in showup moment if(HasAuraType(SPELL_AURA_MOD_INCREASE_FLIGHT_SPEED) || isInFlight()) AddUnitMovementFlag(MOVEMENTFLAG_FLYING2); + + m_mover = this; } void Player::SendInitialPacketsAfterAddToMap() { + WorldPacket data(SMSG_TIME_SYNC_REQ, 4); // new 2.0.x, enable movement + data << uint32(0x00000000); // on blizz it increments periodically + GetSession()->SendPacket(&data); + CastSpell(this, 836, true); // LOGINEFFECT // set some aura effects that send packet to player client after add player to map @@ -17321,6 +17804,7 @@ void Player::SendInitialPacketsAfterAddToMap() SendMessageToSet(&data,true); } + SendAurasForTarget(this); SendEnchantmentDurations(); // must be after add to map SendItemDurations(); // must be after add to map } @@ -17338,11 +17822,19 @@ void Player::SendUpdateToOutOfRangeGroupMembers() pet->ResetAuraUpdateMask(); } -void Player::SendTransferAborted(uint32 mapid, uint16 reason) +void Player::SendTransferAborted(uint32 mapid, uint8 reason, uint8 arg) { WorldPacket data(SMSG_TRANSFER_ABORTED, 4+2); data << uint32(mapid); - data << uint16(reason); // transfer abort reason + data << uint8(reason); // transfer abort reason + switch(reason) + { + case TRANSFER_ABORT_INSUF_EXPAN_LVL: + case TRANSFER_ABORT_DIFFICULTY: + case TRANSFER_ABORT_UNIQUE_MESSAGE: + data << uint8(arg); + break; + } GetSession()->SendPacket(&data); } @@ -17552,16 +18044,51 @@ void Player::learnSkillRewardedSpells() } } -void Player::SendAuraDurationsForTarget(Unit* target) +void Player::SendAurasForTarget(Unit *target) { - for(Unit::AuraMap::const_iterator itr = target->GetAuras().begin(); itr != target->GetAuras().end(); ++itr) - { - Aura* aura = itr->second; - if(aura->GetAuraSlot() >= MAX_AURAS || aura->IsPassive() || aura->GetCasterGUID()!=GetGUID()) - continue; + if(target->GetVisibleAuras()->empty()) // speedup things + return; - aura->SendAuraDurationForCaster(this); + WorldPacket data(SMSG_AURA_UPDATE_ALL); + data.append(target->GetPackGUID()); + + Unit::VisibleAuraMap const *visibleAuras = target->GetVisibleAuras(); + for(Unit::VisibleAuraMap::const_iterator itr = visibleAuras->begin(); itr != visibleAuras->end(); ++itr) + { + for(uint32 j = 0; j < 3; ++j) + { + if(Aura *aura = target->GetAura(itr->second, j)) + { + data << uint8(aura->GetAuraSlot()); + data << uint32(aura->GetId()); + + if(aura->GetId()) + { + uint8 auraFlags = aura->GetAuraFlags(); + // flags + data << uint8(auraFlags); + // level + data << uint8(aura->GetAuraLevel()); + // charges + data << uint8(aura->m_procCharges >= 0 ? aura->m_procCharges : 0 ); + + if(!(auraFlags & AFLAG_NOT_CASTER)) + { + data << uint8(0); // packed GUID of someone (caster?) + } + + if(auraFlags & AFLAG_DURATION) // include aura duration + { + data << uint32(aura->GetAuraMaxDuration()); + data << uint32(aura->GetAuraDuration()); + } + } + break; + } + } } + + GetSession()->SendPacket(&data); } void Player::SetDailyQuestStatus( uint32 quest_id ) @@ -17607,7 +18134,8 @@ bool Player::InArena() const bool Player::GetBGAccessByLevel(uint32 bgTypeId) const { - BattleGround *bg = sBattleGroundMgr.GetBattleGround(bgTypeId); + // get a template bg instead of running one + BattleGround *bg = sBattleGroundMgr.GetBattleGroundTemplate(bgTypeId); if(!bg) return false; @@ -17622,15 +18150,15 @@ uint32 Player::GetMinLevelForBattleGroundQueueId(uint32 queue_id) if(queue_id < 1) return 0; - if(queue_id >=6) - queue_id = 6; + if(queue_id >=7) + queue_id = 7; return 10*(queue_id+1); } uint32 Player::GetMaxLevelForBattleGroundQueueId(uint32 queue_id) { - if(queue_id >=6) + if(queue_id >=7) return 255; // hardcoded max level return 10*(queue_id+2)-1; @@ -17641,10 +18169,15 @@ uint32 Player::GetBattleGroundQueueIdFromLevel() const uint32 level = getLevel(); if(level <= 19) return 0; - else if (level > 69) - return 6; + else if (level > 79) + return 7; else return level/10 - 1; // 20..29 -> 1, 30-39 -> 2, ... + /* + assert(bgTypeId < MAX_BATTLEGROUND_TYPES); + BattleGround *bg = sBattleGroundMgr.GetBattleGroundTemplate(bgTypeId); + assert(bg); + return (getLevel() - bg->GetMinLevel()) / 10;*/ } float Player::GetReputationPriceDiscount( Creature const* pCreature ) const @@ -17783,9 +18316,8 @@ void Player::AutoUnequipOffhandIfNeed() if(!offItem) return; - Item *mainItem = GetItemByPos( INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_MAINHAND ); - - if(!mainItem || mainItem->GetProto()->InventoryType != INVTYPE_2HWEAPON) + // need unequip for 2h-weapon without TitanGrip + if (!IsTwoHandUsed()) return; ItemPosCountVec off_dest; @@ -17846,6 +18378,23 @@ bool Player::HasItemFitToSpellReqirements(SpellEntry const* spellInfo, Item cons return false; } +bool Player::CanNoReagentCast(SpellEntry const* spellInfo) const +{ + // don't take reagents for spells with SPELL_ATTR_EX5_NO_REAGENT_WHILE_PREP + if (spellInfo->AttributesEx5 & SPELL_ATTR_EX5_NO_REAGENT_WHILE_PREP && + HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PREPARATION)) + return true; + + // Check no reagent use mask + uint64 noReagentMask_0_1 = GetUInt64Value(PLAYER_NO_REAGENT_COST_1); + uint32 noReagentMask_2 = GetUInt64Value(PLAYER_NO_REAGENT_COST_1+2); + if (spellInfo->SpellFamilyFlags & noReagentMask_0_1 || + spellInfo->SpellFamilyFlags2 & noReagentMask_2) + return true; + + return false; +} + void Player::RemoveItemDependentAurasAndCasts( Item * pItem ) { AuraMap& auras = GetAuras(); @@ -17891,7 +18440,7 @@ uint32 Player::GetResurrectionSpellId() for(AuraList::const_iterator itr = dummyAuras.begin(); itr != dummyAuras.end(); ++itr) { // Soulstone Resurrection // prio: 3 (max, non death persistent) - if( prio < 2 && (*itr)->GetSpellProto()->SpellVisual == 99 && (*itr)->GetSpellProto()->SpellIconID == 92 ) + if( prio < 2 && (*itr)->GetSpellProto()->SpellVisual[0] == 99 && (*itr)->GetSpellProto()->SpellIconID == 92 ) { switch((*itr)->GetId()) { @@ -18049,6 +18598,9 @@ uint32 Player::GetBaseWeaponSkillValue (WeaponAttackType attType) const void Player::ResurectUsingRequestData() { + /// Teleport before resurrecting, otherwise the player might get attacked from creatures near his corpse + TeleportTo(m_resurrectMap, m_resurrectX, m_resurrectY, m_resurrectZ, GetOrientation()); + ResurrectPlayer(0.0f,false); if(GetMaxHealth() > m_resurrectHealth) @@ -18066,8 +18618,6 @@ void Player::ResurectUsingRequestData() SetPower(POWER_ENERGY, GetMaxPower(POWER_ENERGY) ); SpawnCorpseBones(); - - TeleportTo(m_resurrectMap, m_resurrectX, m_resurrectY, m_resurrectZ, GetOrientation()); } void Player::SetClientControl(Unit* target, uint8 allowMove) @@ -18081,8 +18631,8 @@ void Player::SetClientControl(Unit* target, uint8 allowMove) void Player::UpdateZoneDependentAuras( uint32 newZone ) { // remove new continent flight forms - if( !isGameMaster() && - GetVirtualMapForMapAndZone(GetMapId(),newZone) != 530) + uint32 v_map = GetVirtualMapForMapAndZone(GetMapId(), newZone); + if( !isGameMaster() && v_map != 530 && v_map != 571) { RemoveSpellsCausingAura(SPELL_AURA_MOD_INCREASE_FLIGHT_SPEED); RemoveSpellsCausingAura(SPELL_AURA_FLY); @@ -18308,6 +18858,152 @@ bool Player::isAllowUseBattleGroundObject() ); } +uint32 Player::GetBarberShopCost(uint8 newhairstyle, uint8 newhaircolor, uint8 newfacialhair) +{ + uint32 level = getLevel(); + + if(level > GT_MAX_LEVEL) + level = GT_MAX_LEVEL; // max level in this dbc + + uint8 hairstyle = GetByteValue(PLAYER_BYTES, 2); + uint8 haircolor = GetByteValue(PLAYER_BYTES, 3); + uint8 facialhair = GetByteValue(PLAYER_BYTES_2, 0); + + if((hairstyle == newhairstyle) && (haircolor == newhaircolor) && (facialhair == newfacialhair)) + return 0; + + GtBarberShopCostBaseEntry const *bsc = sGtBarberShopCostBaseStore.LookupEntry(level - 1); + + if(!bsc) // shouldn't happen + return 0xFFFFFFFF; + + float cost = 0; + + if(hairstyle != newhairstyle) + cost += bsc->cost; // full price + + if((haircolor != newhaircolor) && (hairstyle == newhairstyle)) + cost += bsc->cost * 0.5f; // +1/2 of price + + if(facialhair != newfacialhair) + cost += bsc->cost * 0.75f; // +3/4 of price + + return uint32(cost); +} + +void Player::InitGlyphsForLevel() +{ + uint32 level = getLevel(); + uint32 value = 0; + + // 0x3F = 0x01 | 0x02 | 0x04 | 0x08 | 0x10 | 0x20 for 80 level + if(level >= 15) + value |= (0x01 | 0x02); + if(level >= 30) + value |= 0x04; + if(level >= 50) + value |= 0x08; + if(level >= 70) + value |= 0x10; + if(level >= 80) + value |= 0x20; + + SetUInt32Value(PLAYER_GLYPHS_ENABLED, value); +} + +void Player::EnterVehicle(Vehicle *vehicle) +{ + VehicleEntry const *ve = sVehicleStore.LookupEntry(vehicle->GetVehicleId()); + if(!ve) + return; + + VehicleSeatEntry const *veSeat = sVehicleSeatStore.LookupEntry(ve->m_seatID[0]); + if(!veSeat) + return; + + vehicle->SetCharmerGUID(GetGUID()); + vehicle->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_SPELLCLICK); + vehicle->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_UNKNOWN5); + vehicle->setFaction(getFaction()); + + SetCharm(vehicle); // charm + SetFarSight(vehicle->GetGUID()); // set view + + SetClientControl(vehicle, 1); // redirect controls to vehicle + + WorldPacket data(SMSG_ON_CANCEL_EXPECTED_RIDE_VEHICLE_AURA, 0); + GetSession()->SendPacket(&data); + + data.Initialize(MSG_MOVE_TELEPORT_ACK, 30); + data.append(GetPackGUID()); + data << uint32(0); // counter? + data << uint32(MOVEMENTFLAG_ONTRANSPORT); // transport + data << uint16(0); // special flags + data << uint32(getMSTime()); // time + data << vehicle->GetPositionX(); // x + data << vehicle->GetPositionY(); // y + data << vehicle->GetPositionZ(); // z + data << vehicle->GetOrientation(); // o + // transport part, TODO: load/calculate seat offsets + data << uint64(vehicle->GetGUID()); // transport guid + data << float(veSeat->m_attachmentOffsetX); // transport offsetX + data << float(veSeat->m_attachmentOffsetY); // transport offsetY + data << float(veSeat->m_attachmentOffsetZ); // transport offsetZ + data << float(0); // transport orientation + data << uint32(getMSTime()); // transport time + data << uint8(0); // seat + // end of transport part + data << uint32(0); // fall time + GetSession()->SendPacket(&data); + + data.Initialize(SMSG_PET_SPELLS, 8+4+4+4+4*10+1+1); + data << uint64(vehicle->GetGUID()); + data << uint32(0x00000000); + data << uint32(0x00000000); + data << uint32(0x00000101); + + for(uint32 i = 0; i < 10; ++i) + data << uint16(0) << uint8(0) << uint8(i+8); + + data << uint8(0); + data << uint8(0); + GetSession()->SendPacket(&data); +} + +void Player::ExitVehicle(Vehicle *vehicle) +{ + vehicle->SetCharmerGUID(0); + vehicle->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_SPELLCLICK); + vehicle->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_UNKNOWN5); + vehicle->setFaction((GetTeam() == ALLIANCE) ? vehicle->GetCreatureInfo()->faction_A : vehicle->GetCreatureInfo()->faction_H); + + SetCharm(NULL); + SetFarSight(NULL); + + SetClientControl(vehicle, 0); + + WorldPacket data(MSG_MOVE_TELEPORT_ACK, 30); + data.append(GetPackGUID()); + data << uint32(0); // counter? + data << uint32(MOVEMENTFLAG_FLY_UNK1); // fly unk + data << uint16(0x40); // special flags + data << uint32(getMSTime()); // time + data << vehicle->GetPositionX(); // x + data << vehicle->GetPositionY(); // y + data << vehicle->GetPositionZ(); // z + data << vehicle->GetOrientation(); // o + data << uint32(0); // fall time + GetSession()->SendPacket(&data); + + data.Initialize(SMSG_PET_SPELLS, 8+4); + data << uint64(0); + data << uint32(0); + GetSession()->SendPacket(&data); + + // only for flyable vehicles? + CastSpell(this, 45472, true); // Parachute +} + bool Player::HasTitle(uint32 bitIndex) { if (bitIndex > 128) @@ -18324,3 +19020,52 @@ void Player::SetTitle(CharTitlesEntry const* title) uint32 flag = 1 << (title->bit_index%32); SetFlag(PLAYER__FIELD_KNOWN_TITLES+fieldIndexOffset, flag); } + +void Player::ConvertRune(uint8 index, uint8 newType) +{ + SetCurrentRune(index, newType); + + WorldPacket data(SMSG_CONVERT_RUNE, 2); + data << uint8(index); + data << uint8(newType); + GetSession()->SendPacket(&data); +} + +void Player::ResyncRunes(uint8 count) +{ + WorldPacket data(SMSG_RESYNC_RUNES, count * 2); + for(uint32 i = 0; i < count; ++i) + { + data << uint8(GetCurrentRune(i)); // rune type + data << uint8(255 - (GetRuneCooldown(i) * 51)); // passed cooldown time (0-255) + } + GetSession()->SendPacket(&data); +} + +void Player::AddRunePower(uint8 index) +{ + WorldPacket data(SMSG_ADD_RUNE_POWER, 4); + data << uint32(1 << index); // mask (0x00-0x3F probably) + GetSession()->SendPacket(&data); +} + +void Player::InitRunes() +{ + if(getClass() != CLASS_DEATH_KNIGHT) + return; + + m_runes = new Runes; + + m_runes->runeState = 0; + + for(uint32 i = 0; i < MAX_RUNES; ++i) + { + SetBaseRune(i, i / 2); // init base types + SetCurrentRune(i, i / 2); // init current types + SetRuneCooldown(i, 0); // reset cooldowns + m_runes->SetRuneState(i); + } + + for(uint32 i = 0; i < NUM_RUNE_TYPES; ++i) + SetFloatValue(PLAYER_RUNE_REGEN_1 + i, 0.1f); +} diff --git a/src/game/Player.h b/src/game/Player.h index bc7e3d39c..0f15be30c 100644 --- a/src/game/Player.h +++ b/src/game/Player.h @@ -33,6 +33,7 @@ #include "Pet.h" #include "MapReference.h" #include "Util.h" // for Tokens typedef +#include "AchievementMgr.h" #include #include @@ -46,6 +47,8 @@ class PlayerMenu; class Transport; class UpdateMask; class PlayerSocial; +class AchievementMgr; +class Vehicle; typedef std::deque PlayerMails; @@ -77,15 +80,17 @@ struct PlayerSpell #define SPELL_WITHOUT_SLOT_ID uint16(-1) +// Spell modifier (used for modify other spells) struct SpellModifier { + SpellModifier() : charges(0), lastAffected(NULL) {} SpellModOp op : 8; SpellModType type : 8; int16 charges : 16; int32 value; uint64 mask; + uint64 mask2; uint32 spellId; - uint32 effectId; Spell const* lastAffected; }; @@ -221,6 +226,39 @@ struct Areas float y2; }; +#define MAX_RUNES 6 +#define RUNE_COOLDOWN 5 // 5*2=10 sec + +enum RuneType +{ + RUNE_BLOOD = 0, + RUNE_UNHOLY = 1, + RUNE_FROST = 2, + RUNE_DEATH = 3, + NUM_RUNE_TYPES = 4 +}; + +struct RuneInfo +{ + uint8 BaseRune; + uint8 CurrentRune; + uint8 Cooldown; +}; + +struct Runes +{ + RuneInfo runes[MAX_RUNES]; + uint8 runeState; // mask of available runes + + void SetRuneState(uint8 index, bool set = true) + { + if(set) + runeState |= (1 << index); // usable + else + runeState &= ~(1 << index); // on cooldown + } +}; + enum FactionFlags { FACTION_FLAG_VISIBLE = 0x01, // makes visible in client (set or can be set at interaction with target of this faction) @@ -389,7 +427,7 @@ enum PlayerFlags PLAYER_FLAGS_UNK3 = 0x00008000, // strange visual effect (2.0.1), looks like PLAYER_FLAGS_GHOST flag PLAYER_FLAGS_SANCTUARY = 0x00010000, // player entered sanctuary PLAYER_FLAGS_UNK4 = 0x00020000, // taxi benchmark mode (on/off) (2.0.1) - PLAYER_UNK = 0x00040000, // 2.0.8... + PLAYER_FLAGS_PVP_TIMER = 0x00040000, // 3.0.2, pvp timer active (after you disable pvp manually) }; // used for PLAYER__FIELD_KNOWN_TITLES field (uint64), (1< QuestStatusMap; @@ -541,7 +581,7 @@ enum PlayerSlots // first slot for item stored (in any way in player m_items data) PLAYER_SLOT_START = 0, // last+1 slot for item stored (in any way in player m_items data) - PLAYER_SLOT_END = 118, + PLAYER_SLOT_END = 200, PLAYER_SLOTS_COUNT = (PLAYER_SLOT_END - PLAYER_SLOT_START) }; @@ -669,6 +709,24 @@ enum KeyRingSlots KEYRING_SLOT_END = 118 }; +enum VanityPetSlots +{ + VANITYPET_SLOT_START = 118, + VANITYPET_SLOT_END = 136 +}; + +enum CurrencyTokenSlots +{ + CURRENCYTOKEN_SLOT_START = 136, + CURRENCYTOKEN_SLOT_END = 168 +}; + +enum QuestBagSlots +{ + QUESTBAG_SLOT_START = 168, + QUESTBAG_SLOT_END = 200 +}; + struct ItemPosCount { ItemPosCount(uint16 _pos, uint8 _count) : pos(_pos), count(_count) {} @@ -687,14 +745,15 @@ enum TradeSlots enum TransferAbortReason { - TRANSFER_ABORT_MAX_PLAYERS = 0x0001, // Transfer Aborted: instance is full - TRANSFER_ABORT_NOT_FOUND = 0x0002, // Transfer Aborted: instance not found - TRANSFER_ABORT_TOO_MANY_INSTANCES = 0x0003, // You have entered too many instances recently. - TRANSFER_ABORT_ZONE_IN_COMBAT = 0x0005, // Unable to zone in while an encounter is in progress. - TRANSFER_ABORT_INSUF_EXPAN_LVL1 = 0x0106, // You must have TBC expansion installed to access this area. - TRANSFER_ABORT_DIFFICULTY1 = 0x0007, // Normal difficulty mode is not available for %s. - TRANSFER_ABORT_DIFFICULTY2 = 0x0107, // Heroic difficulty mode is not available for %s. - TRANSFER_ABORT_DIFFICULTY3 = 0x0207 // Epic difficulty mode is not available for %s. + TRANSFER_ABORT_ERROR = 0x00, + TRANSFER_ABORT_MAX_PLAYERS = 0x01, // Transfer Aborted: instance is full + TRANSFER_ABORT_NOT_FOUND = 0x02, // Transfer Aborted: instance not found + TRANSFER_ABORT_TOO_MANY_INSTANCES = 0x03, // You have entered too many instances recently. + TRANSFER_ABORT_ZONE_IN_COMBAT = 0x05, // Unable to zone in while an encounter is in progress. + TRANSFER_ABORT_INSUF_EXPAN_LVL = 0x06, // You must have expansion installed to access this area. + TRANSFER_ABORT_DIFFICULTY = 0x07, // difficulty mode is not available for %s. + TRANSFER_ABORT_UNIQUE_MESSAGE = 0x08, // Until you've escaped TLK's grasp, you cannot leave this place! + TRANSFER_ABORT_TOO_MANY_REALM_INSTANCES = 0x09 // Additional instances cannot be launched, please try again later. }; enum InstanceResetWarningType @@ -708,15 +767,16 @@ enum InstanceResetWarningType struct MovementInfo { // common - //uint32 flags; - uint8 unk1; + uint32 flags; + uint16 unk1; uint32 time; float x, y, z, o; // transport uint64 t_guid; float t_x, t_y, t_z, t_o; uint32 t_time; - // swimming and unk + int8 t_seat; + // swimming and unknown float s_pitch; // last fall time uint32 fallTime; @@ -727,17 +787,17 @@ struct MovementInfo MovementInfo() { - //flags = + flags = 0; time = t_time = fallTime = 0; unk1 = 0; x = y = z = o = t_x = t_y = t_z = t_o = s_pitch = j_unk = j_sinAngle = j_cosAngle = j_xyspeed = u_unk1 = 0.0f; t_guid = 0; } - /*void SetMovementFlags(uint32 _flags) + void SetMovementFlags(uint32 _flags) { flags = _flags; - }*/ + } }; // flags that use in movement check for example at spell casting @@ -809,9 +869,12 @@ enum PlayerLoginQueryIndex PLAYER_LOGIN_QUERY_LOADSPELLCOOLDOWNS = 15, PLAYER_LOGIN_QUERY_LOADDECLINEDNAMES = 16, PLAYER_LOGIN_QUERY_LOADGUILD = 17, + PLAYER_LOGIN_QUERY_LOADARENAINFO = 18, + PLAYER_LOGIN_QUERY_LOADACHIEVEMENTS = 19, + PLAYER_LOGIN_QUERY_LOADCRITERIAPROGRESS = 20, + MAX_PLAYER_LOGIN_QUERY = 21 }; -#define MAX_PLAYER_LOGIN_QUERY 18 // Player summoning auto-decline time (in secs) #define MAX_PLAYER_SUMMON_DELAY (2*MINUTE) @@ -833,7 +896,7 @@ class MANGOS_DLL_SPEC PlayerTaxi PlayerTaxi(); ~PlayerTaxi() {} // Nodes - void InitTaxiNodesForLevel(uint32 race, uint32 level); + void InitTaxiNodesForLevel(uint32 race, uint32 chrClass, uint32 level); void LoadTaxiMask(const char* data); void SaveTaxiMask(const char* data); @@ -859,7 +922,7 @@ class MANGOS_DLL_SPEC PlayerTaxi void AppendTaximaskTo(ByteBuffer& data,bool all); // Destinations - bool LoadTaxiDestinationsFromString(std::string values); + bool LoadTaxiDestinationsFromString(const std::string& values); std::string SaveTaxiDestinationsToString(); void ClearTaxiDestinations() { m_TaxiDestinations.clear(); } @@ -912,7 +975,7 @@ class MANGOS_DLL_SPEC Player : public Unit } void SummonIfPossible(bool agree); - bool Create( uint32 guidlow, std::string name, uint8 race, uint8 class_, uint8 gender, uint8 skin, uint8 face, uint8 hairStyle, uint8 hairColor, uint8 facialHair, uint8 outfitId ); + bool Create( uint32 guidlow, const std::string& name, uint8 race, uint8 class_, uint8 gender, uint8 skin, uint8 face, uint8 hairStyle, uint8 hairColor, uint8 facialHair, uint8 outfitId ); void Update( uint32 time ); @@ -925,7 +988,7 @@ class MANGOS_DLL_SPEC Player : public Unit void SendInitialPacketsBeforeAddToMap(); void SendInitialPacketsAfterAddToMap(); - void SendTransferAborted(uint32 mapid, uint16 reason); + void SendTransferAborted(uint32 mapid, uint8 reason, uint8 arg = 0); void SendInstanceResetWarning(uint32 mapid, uint32 time); bool CanInteractWithNPCs(bool alive = true) const; @@ -938,10 +1001,12 @@ class MANGOS_DLL_SPEC Player : public Unit std::string afkMsg; std::string dndMsg; + uint32 GetBarberShopCost(uint8 newhairstyle, uint8 newhaircolor, uint8 newfacialhair); + PlayerSocial *GetSocial() { return m_social; } PlayerTaxi m_taxi; - void InitTaxiNodesForLevel() { m_taxi.InitTaxiNodesForLevel(getRace(),getLevel()); } + void InitTaxiNodesForLevel() { m_taxi.InitTaxiNodesForLevel(getRace(), getClass(), getLevel()); } bool ActivateTaxiPathTo(std::vector const& nodes, uint32 mount_id = 0 , Creature* npc = NULL); // mount_id can be used in scripting calls bool isAcceptTickets() const { return GetSession()->GetSecurity() >= SEC_GAMEMASTER && (m_ExtraFlags & PLAYER_EXTRA_GM_ACCEPT_TICKETS); } @@ -1004,11 +1069,11 @@ class MANGOS_DLL_SPEC Player : public Unit GuardianPetList const& GetGuardians() const { return m_guardianPets; } void Uncharm(); - void Say(std::string text, const uint32 language); - void Yell(std::string text, const uint32 language); - void TextEmote(std::string text); - void Whisper(std::string text, const uint32 language,uint64 receiver); - void BuildPlayerChat(WorldPacket *data, uint8 msgtype, std::string text, uint32 language) const; + void Say(const std::string& text, const uint32 language); + void Yell(const std::string& text, const uint32 language); + void TextEmote(const std::string& text); + void Whisper(const std::string& text, const uint32 language,uint64 receiver); + void BuildPlayerChat(WorldPacket *data, uint8 msgtype, const std::string& text, uint32 language) const; /*********************************************************/ /*** STORAGE SYSTEM ***/ @@ -1037,6 +1102,7 @@ class MANGOS_DLL_SPEC Player : public Unit bool HasBankBagSlot( uint8 slot ) const; bool HasItemCount( uint32 item, uint32 count, bool inBankAlso = false ) const; bool HasItemFitToSpellReqirements(SpellEntry const* spellInfo, Item const* ignoreItem = NULL); + bool CanNoReagentCast(SpellEntry const* spellInfo) const; Item* GetItemOrItemWithGemEquipped( uint32 item ) const; uint8 CanTakeMoreSimilarItems(Item* pItem) const { return _CanTakeMoreSimilarItems(pItem->GetEntry(),pItem->GetCount(),pItem); } uint8 CanTakeMoreSimilarItems(uint32 entry, uint32 count) const { return _CanTakeMoreSimilarItems(entry,count,NULL); } @@ -1053,7 +1119,7 @@ class MANGOS_DLL_SPEC Player : public Unit } uint8 CanStoreItems( Item **pItem,int count) const; - uint8 CanEquipNewItem( uint8 slot, uint16 &dest, uint32 item, uint32 count, bool swap ) const; + uint8 CanEquipNewItem( uint8 slot, uint16 &dest, uint32 item, bool swap ) const; uint8 CanEquipItem( uint8 slot, uint16 &dest, Item *pItem, bool swap, bool not_loading = true ) const; uint8 CanUnequipItems( uint32 item, uint32 count ) const; uint8 CanUnequipItem( uint16 src, bool swap ) const; @@ -1064,10 +1130,10 @@ class MANGOS_DLL_SPEC Player : public Unit uint8 CanUseAmmo( uint32 item ) const; Item* StoreNewItem( ItemPosCountVec const& pos, uint32 item, bool update,int32 randomPropertyId = 0 ); Item* StoreItem( ItemPosCountVec const& pos, Item *pItem, bool update ); - Item* EquipNewItem( uint16 pos, uint32 item, uint32 count, bool update ); + Item* EquipNewItem( uint16 pos, uint32 item, bool update ); Item* EquipItem( uint16 pos, Item *pItem, bool update ); void AutoUnequipOffhandIfNeed(); - bool StoreNewItemInBestSlot(uint32 item_id, uint32 item_count); + bool StoreNewItemInBestSlots(uint32 item_id, uint32 item_count); uint8 _CanTakeMoreSimilarItems(uint32 entry, uint32 count, Item* pItem, uint32* no_space_count = NULL) const; uint8 _CanStoreItem( uint8 bag, uint8 slot, ItemPosCountVec& dest, uint32 entry, uint32 count, Item *pItem = NULL, bool swap = false, uint32* no_space_count = NULL ) const; @@ -1115,6 +1181,11 @@ class MANGOS_DLL_SPEC Player : public Unit // disarm applied only to mainhand weapon return !IsInFeralForm() && (!mainhand || !HasFlag(UNIT_FIELD_FLAGS,UNIT_FLAG_DISARMED) ); } + bool IsTwoHandUsed() const + { + Item* mainItem = GetItemByPos(INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_MAINHAND); + return mainItem && mainItem->GetProto()->InventoryType == INVTYPE_2HWEAPON && !CanTitanGrip(); + } void SendNewItem( Item *item, uint32 count, bool received, bool created, bool broadcast = false ); bool BuyItemFromVendor(uint64 vendorguid, uint32 item, uint8 count, uint64 bagguid, uint8 slot); @@ -1270,6 +1341,7 @@ class MANGOS_DLL_SPEC Player : public Unit static void SetFloatValueInArray(Tokens& data,uint16 index, float value); static void SetUInt32ValueInDB(uint16 index, uint32 value, uint64 guid); static void SetFloatValueInDB(uint16 index, float value, uint64 guid); + static void Customize(uint64 guid, uint8 gender, uint8 skin, uint8 face, uint8 hairStyle, uint8 hairColor, uint8 facialHair); static void SavePositionInDB(uint32 mapid, float x,float y,float z,float o,uint32 zone,uint64 guid); bool m_mailsLoaded; @@ -1408,6 +1480,12 @@ class MANGOS_DLL_SPEC Player : public Unit uint32 resetTalentsCost() const; void InitTalentForLevel(); + void InitGlyphsForLevel(); + void SetGlyphSlot(uint8 slot, uint32 slottype) { SetUInt32Value(PLAYER_FIELD_GLYPH_SLOTS_1 + slot, slottype); } + uint32 GetGlyphSlot(uint8 slot) { return GetUInt32Value(PLAYER_FIELD_GLYPH_SLOTS_1 + slot); } + void SetGlyph(uint8 slot, uint32 glyph) { SetUInt32Value(PLAYER_FIELD_GLYPHS_1 + slot, glyph); } + uint32 GetGlyph(uint8 slot) { return GetUInt32Value(PLAYER_FIELD_GLYPHS_1 + slot); } + uint32 GetFreePrimaryProffesionPoints() const { return GetUInt32Value(PLAYER_CHARACTER_POINTS2); } void SetFreePrimaryProffesions(uint16 profs) { SetUInt32Value(PLAYER_CHARACTER_POINTS2,profs); } void InitPrimaryProffesions(); @@ -1416,8 +1494,6 @@ class MANGOS_DLL_SPEC Player : public Unit PlayerSpellMap & GetSpellMap() { return m_spells; } void AddSpellMod(SpellModifier* mod, bool apply); - int32 GetTotalFlatMods(uint32 spellId, SpellModOp op); - int32 GetTotalPctMods(uint32 spellId, SpellModOp op); bool IsAffectedBySpellmod(SpellEntry const *spellInfo, SpellModifier *mod, Spell const* spell = NULL); template T ApplySpellMod(uint32 spellId, SpellModOp op, T &basevalue, Spell const* spell = NULL); void RemoveSpellMods(Spell const* spell); @@ -1517,7 +1593,6 @@ class MANGOS_DLL_SPEC Player : public Unit void SetInArenaTeam(uint32 ArenaTeamId, uint8 slot) { SetUInt32Value(PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + (slot * 6), ArenaTeamId); - SaveDataFieldToDB(); // needed? } uint32 GetArenaTeamId(uint8 slot) { return GetUInt32Value(PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + (slot * 6)); } static uint32 GetArenaTeamIdFromDB(uint64 guid, uint8 slot); @@ -1575,6 +1650,10 @@ class MANGOS_DLL_SPEC Player : public Unit void UpdateAllCritPercentages(); void UpdateParryPercentage(); void UpdateDodgePercentage(); + void UpdateMeleeHitChances(); + void UpdateRangedHitChances(); + void UpdateSpellHitChances(); + void UpdateAllSpellCritChances(); void UpdateSpellCritChance(uint32 school); void UpdateExpertise(WeaponAttackType attType); @@ -1748,6 +1827,8 @@ class MANGOS_DLL_SPEC Player : public Unit void SetCanBlock(bool value); bool CanDualWield() const { return m_canDualWield; } void SetCanDualWield(bool value) { m_canDualWield = value; } + bool CanTitanGrip() const { return m_canTitanGrip ; } + void SetCanTitanGrip(bool value) { m_canTitanGrip = value; } void SetRegularAttackTime(); void SetBaseModValue(BaseModGroup modGroup, BaseModType modType, float value) { m_auraBaseMod[modGroup][modType] = value; } @@ -1781,7 +1862,7 @@ class MANGOS_DLL_SPEC Player : public Unit void SendUpdateWorldState(uint32 Field, uint32 Value); void SendDirectMessage(WorldPacket *data); - void SendAuraDurationsForTarget(Unit* target); + void SendAurasForTarget(Unit *target); PlayerMenu* PlayerTalkClass; std::vector ItemSetEff; @@ -1804,24 +1885,32 @@ class MANGOS_DLL_SPEC Player : public Unit static uint32 GetMaxLevelForBattleGroundQueueId(uint32 queue_id); uint32 GetBattleGroundQueueIdFromLevel() const; - uint32 GetBattleGroundQueueId(uint32 index) const { return m_bgBattleGroundQueueID[index].bgType; } - uint32 GetBattleGroundQueueIndex(uint32 bgType) const + bool InBattleGroundQueue() const { for (int i=0; i < PLAYER_MAX_BATTLEGROUND_QUEUES; i++) - if (m_bgBattleGroundQueueID[i].bgType == bgType) + if (m_bgBattleGroundQueueID[i].bgQueueType != 0) + return true; + return false; + } + + uint32 GetBattleGroundQueueId(uint32 index) const { return m_bgBattleGroundQueueID[index].bgQueueType; } + uint32 GetBattleGroundQueueIndex(uint32 bgQueueType) const + { + for (int i=0; i < PLAYER_MAX_BATTLEGROUND_QUEUES; i++) + if (m_bgBattleGroundQueueID[i].bgQueueType == bgQueueType) return i; return PLAYER_MAX_BATTLEGROUND_QUEUES; } - bool IsInvitedForBattleGroundType(uint32 bgType) const + bool IsInvitedForBattleGroundQueueType(uint32 bgQueueType) const { for (int i=0; i < PLAYER_MAX_BATTLEGROUND_QUEUES; i++) - if (m_bgBattleGroundQueueID[i].bgType == bgType) - return m_bgBattleGroundQueueID[i].invited; + if (m_bgBattleGroundQueueID[i].bgQueueType == bgQueueType) + return m_bgBattleGroundQueueID[i].invitedToInstance != 0; return PLAYER_MAX_BATTLEGROUND_QUEUES; } - bool InBattleGroundQueueForBattleGroundType(uint32 bgType) const + bool InBattleGroundQueueForBattleGroundQueueType(uint32 bgQueueType) const { - return GetBattleGroundQueueIndex(bgType) < PLAYER_MAX_BATTLEGROUND_QUEUES; + return GetBattleGroundQueueIndex(bgQueueType) < PLAYER_MAX_BATTLEGROUND_QUEUES; } void SetBattleGroundId(uint32 val) { m_bgBattleGroundID = val; } @@ -1829,34 +1918,47 @@ class MANGOS_DLL_SPEC Player : public Unit { for (int i=0; i < PLAYER_MAX_BATTLEGROUND_QUEUES; i++) { - if (m_bgBattleGroundQueueID[i].bgType == 0 || m_bgBattleGroundQueueID[i].bgType == val) + if (m_bgBattleGroundQueueID[i].bgQueueType == 0 || m_bgBattleGroundQueueID[i].bgQueueType == val) { - m_bgBattleGroundQueueID[i].bgType = val; - m_bgBattleGroundQueueID[i].invited = false; + m_bgBattleGroundQueueID[i].bgQueueType = val; + m_bgBattleGroundQueueID[i].invitedToInstance = 0; return i; } } return PLAYER_MAX_BATTLEGROUND_QUEUES; } + bool HasFreeBattleGroundQueueId() + { + for (int i=0; i < PLAYER_MAX_BATTLEGROUND_QUEUES; i++) + if (m_bgBattleGroundQueueID[i].bgQueueType == 0) + return true; + return false; + } void RemoveBattleGroundQueueId(uint32 val) { for (int i=0; i < PLAYER_MAX_BATTLEGROUND_QUEUES; i++) { - if (m_bgBattleGroundQueueID[i].bgType == val) + if (m_bgBattleGroundQueueID[i].bgQueueType == val) { - m_bgBattleGroundQueueID[i].bgType = 0; - m_bgBattleGroundQueueID[i].invited = false; + m_bgBattleGroundQueueID[i].bgQueueType = 0; + m_bgBattleGroundQueueID[i].invitedToInstance = 0; return; } } } - void SetInviteForBattleGroundType(uint32 bgType) + void SetInviteForBattleGroundQueueType(uint32 bgQueueType, uint32 instanceId) { for (int i=0; i < PLAYER_MAX_BATTLEGROUND_QUEUES; i++) - if (m_bgBattleGroundQueueID[i].bgType == bgType) - m_bgBattleGroundQueueID[i].invited = true; + if (m_bgBattleGroundQueueID[i].bgQueueType == bgQueueType) + m_bgBattleGroundQueueID[i].invitedToInstance = instanceId; + } + bool IsInvitedForBattleGroundInstance(uint32 instanceId) const + { + for (int i=0; i < PLAYER_MAX_BATTLEGROUND_QUEUES; i++) + if (m_bgBattleGroundQueueID[i].invitedToInstance == instanceId) + return true; + return false; } - uint32 GetBattleGroundEntryPointMap() const { return m_bgEntryPointMap; } float GetBattleGroundEntryPointX() const { return m_bgEntryPointX; } float GetBattleGroundEntryPointY() const { return m_bgEntryPointY; } @@ -1912,6 +2014,7 @@ class MANGOS_DLL_SPEC Player : public Unit MovementInfo m_movementInfo; uint32 m_lastFallTime; float m_lastFallZ; + Unit *m_mover; void SetFallInformation(uint32 time, float z) { m_lastFallTime = time; @@ -1927,6 +2030,9 @@ class MANGOS_DLL_SPEC Player : public Unit void SetClientControl(Unit* target, uint8 allowMove); + void EnterVehicle(Vehicle *vehicle); + void ExitVehicle(Vehicle *vehicle); + uint64 GetFarSight() const { return GetUInt64Value(PLAYER_FARSIGHT); } void SetFarSight(uint64 guid) { SetUInt64Value(PLAYER_FARSIGHT, guid); } @@ -1939,6 +2045,7 @@ class MANGOS_DLL_SPEC Player : public Unit float GetTransOffsetZ() const { return m_movementInfo.t_z; } float GetTransOffsetO() const { return m_movementInfo.t_o; } uint32 GetTransTime() const { return m_movementInfo.t_time; } + int8 GetTransSeat() const { return m_movementInfo.t_seat; } uint32 GetSaveTimer() const { return m_nextSave; } void SetSaveTimer(uint32 timer) { m_nextSave = timer; } @@ -2036,6 +2143,18 @@ class MANGOS_DLL_SPEC Player : public Unit WorldLocation& GetTeleportDest() { return m_teleport_dest; } DeclinedName const* GetDeclinedNames() const { return m_declinedname; } + uint8 GetRunesState() const { return m_runes->runeState; } + uint8 GetBaseRune(uint8 index) const { return m_runes->runes[index].BaseRune; } + uint8 GetCurrentRune(uint8 index) const { return m_runes->runes[index].CurrentRune; } + uint8 GetRuneCooldown(uint8 index) const { return m_runes->runes[index].Cooldown; } + void SetBaseRune(uint8 index, uint8 baseRune) { m_runes->runes[index].BaseRune = baseRune; } + void SetCurrentRune(uint8 index, uint8 currentRune) { m_runes->runes[index].CurrentRune = currentRune; } + void SetRuneCooldown(uint8 index, uint8 cooldown) { m_runes->runes[index].Cooldown = cooldown; m_runes->SetRuneState(index, (cooldown == 0) ? true : false); } + void ConvertRune(uint8 index, uint8 newType); + void ResyncRunes(uint8 count); + void AddRunePower(uint8 index); + void InitRunes(); + AchievementMgr& GetAchievementMgr() { return m_achievementMgr; } bool HasTitle(uint32 bitIndex); bool HasTitle(CharTitlesEntry const* title) { return HasTitle(title->bit_index); } void SetTitle(CharTitlesEntry const* title); @@ -2053,8 +2172,8 @@ class MANGOS_DLL_SPEC Player : public Unit */ struct BgBattleGroundQueueID_Rec { - uint32 bgType; - bool invited; + uint32 bgQueueType; + uint32 invitedToInstance; }; BgBattleGroundQueueID_Rec m_bgBattleGroundQueueID[PLAYER_MAX_BATTLEGROUND_QUEUES]; uint32 m_bgEntryPointMap; @@ -2099,6 +2218,7 @@ class MANGOS_DLL_SPEC Player : public Unit void _LoadFriendList(QueryResult *result); bool _LoadHomeBind(QueryResult *result); void _LoadDeclinedNames(QueryResult *result); + void _LoadArenaTeamInfo(QueryResult *result); /*********************************************************/ /*** SAVE SYSTEM ***/ @@ -2171,6 +2291,7 @@ class MANGOS_DLL_SPEC Player : public Unit ActionButtonList m_actionButtons; float m_auraBaseMod[BASEMOD_END][MOD_END]; + int16 m_baseRatingValue[MAX_COMBAT_RATING]; SpellModList m_spellMods[MAX_SPELLMOD]; int32 m_SpellModRemoveCount; @@ -2204,7 +2325,6 @@ class MANGOS_DLL_SPEC Player : public Unit bool m_DailyQuestChanged; time_t m_lastDailyQuestTime; - uint32 m_regenTimer; uint32 m_breathTimer; uint32 m_drunkTimer; uint16 m_drunk; @@ -2224,8 +2344,10 @@ class MANGOS_DLL_SPEC Player : public Unit bool m_canParry; bool m_canBlock; bool m_canDualWield; + bool m_canTitanGrip; uint8 m_swingErrorMsg; float m_ammoDPS; + ////////////////////Rest System///////////////////// int time_inn_enter; uint32 inn_pos_mapid; @@ -2270,6 +2392,8 @@ class MANGOS_DLL_SPEC Player : public Unit WorldLocation m_teleport_dest; DeclinedName *m_declinedname; + Runes *m_runes; + AchievementMgr m_achievementMgr; private: // internal common parts for CanStore/StoreItem functions uint8 _CanStoreItem_InSpecificSlot( uint8 bag, uint8 slot, ItemPosCountVec& dest, ItemPrototype const *pProto, uint32& count, bool swap, Item *pSrcItem ) const; diff --git a/src/game/PlayerDump.cpp b/src/game/PlayerDump.cpp index b7e66c968..b533cab6c 100644 --- a/src/game/PlayerDump.cpp +++ b/src/game/PlayerDump.cpp @@ -337,7 +337,7 @@ std::string PlayerDumpWriter::GetDump(uint32 guid) return dump; } -DumpReturn PlayerDumpWriter::WriteDump(std::string file, uint32 guid) +DumpReturn PlayerDumpWriter::WriteDump(const std::string& file, uint32 guid) { FILE *fout = fopen(file.c_str(), "w"); if (!fout) @@ -353,7 +353,7 @@ DumpReturn PlayerDumpWriter::WriteDump(std::string file, uint32 guid) // Reading - High-level functions #define ROLLBACK(DR) {CharacterDatabase.RollbackTransaction(); fclose(fin); return (DR);} -DumpReturn PlayerDumpReader::LoadDump(std::string file, uint32 account, std::string name, uint32 guid) +DumpReturn PlayerDumpReader::LoadDump(const std::string& file, uint32 account, std::string name, uint32 guid) { // check character count { diff --git a/src/game/PlayerDump.h b/src/game/PlayerDump.h index 2e83102f9..5991b7445 100644 --- a/src/game/PlayerDump.h +++ b/src/game/PlayerDump.h @@ -92,7 +92,7 @@ class PlayerDumpWriter : public PlayerDump PlayerDumpWriter() {} std::string GetDump(uint32 guid); - DumpReturn WriteDump(std::string file, uint32 guid); + DumpReturn WriteDump(const std::string& file, uint32 guid); private: typedef std::set GUIDs; @@ -111,7 +111,7 @@ class PlayerDumpReader : public PlayerDump public: PlayerDumpReader() {} - DumpReturn LoadDump(std::string file, uint32 account, std::string name, uint32 guid); + DumpReturn LoadDump(const std::string& file, uint32 account, std::string name, uint32 guid); }; #endif diff --git a/src/game/QueryHandler.cpp b/src/game/QueryHandler.cpp index f71cb761b..08f4a4db7 100644 --- a/src/game/QueryHandler.cpp +++ b/src/game/QueryHandler.cpp @@ -31,6 +31,7 @@ #include "NPCHandler.h" #include "ObjectAccessor.h" #include "Pet.h" +#include "MapManager.h" void WorldSession::SendNameQueryOpcode(Player *p) { @@ -183,7 +184,6 @@ void WorldSession::HandleCreatureQueryOpcode( WorldPacket & recv_data ) data << (uint32)ci->type; data << (uint32)ci->family; // family wdbFeild9 data << (uint32)ci->rank; // rank wdbFeild10 - data << (uint32)0; // unknown wdbFeild11 data << (uint32)ci->PetSpellDataId; // Id from CreatureSpellData.dbc wdbField12 data << (uint32)ci->DisplayID_A; // modelid_male1 data << (uint32)ci->DisplayID_H; // modelid_female1 ? @@ -275,20 +275,43 @@ void WorldSession::HandleCorpseQueryOpcode(WorldPacket & /*recv_data*/) Corpse *corpse = GetPlayer()->GetCorpse(); - uint8 found = 1; if(!corpse) - found = 0; - - WorldPacket data(MSG_CORPSE_QUERY, (1+found*(5*4))); - data << uint8(found); - if(found) { - data << corpse->GetMapId(); - data << corpse->GetPositionX(); - data << corpse->GetPositionY(); - data << corpse->GetPositionZ(); - data << _player->GetMapId(); + WorldPacket data(MSG_CORPSE_QUERY, 1); + data << uint8(0); // corpse not found + SendPacket(&data); + return; } + + int32 mapid = corpse->GetMapId(); + float x = corpse->GetPositionX(); + float y = corpse->GetPositionY(); + float z = corpse->GetPositionZ(); + int32 corpsemapid = _player->GetMapId(); + + if(Map *map = corpse->GetMap()) + { + if(map->IsDungeon()) + { + if(!map->GetEntrancePos(mapid, x, y)) + return; + + Map *entrance_map = MapManager::Instance().GetMap(mapid, _player); + if(!entrance_map) + return; + + z = entrance_map->GetHeight(x, y, MAX_HEIGHT); + corpsemapid = corpse->GetMapId(); + } + } + + WorldPacket data(MSG_CORPSE_QUERY, 1+(5*4)); + data << uint8(1); // corpse found + data << int32(mapid); + data << float(x); + data << float(y); + data << float(z); + data << int32(corpsemapid); SendPacket(&data); } diff --git a/src/game/QuestDef.cpp b/src/game/QuestDef.cpp index 06a7ed2b4..1e2cd6021 100644 --- a/src/game/QuestDef.cpp +++ b/src/game/QuestDef.cpp @@ -42,88 +42,90 @@ Quest::Quest(Field * questRecord) QuestFlags = questRecord[17].GetUInt16(); uint32 SpecialFlags = questRecord[18].GetUInt16(); CharTitleId = questRecord[19].GetUInt32(); - PrevQuestId = questRecord[20].GetInt32(); - NextQuestId = questRecord[21].GetInt32(); - ExclusiveGroup = questRecord[22].GetInt32(); - NextQuestInChain = questRecord[23].GetUInt32(); - SrcItemId = questRecord[24].GetUInt32(); - SrcItemCount = questRecord[25].GetUInt32(); - SrcSpell = questRecord[26].GetUInt32(); - Title = questRecord[27].GetCppString(); - Details = questRecord[28].GetCppString(); - Objectives = questRecord[29].GetCppString(); - OfferRewardText = questRecord[30].GetCppString(); - RequestItemsText = questRecord[31].GetCppString(); - EndText = questRecord[32].GetCppString(); + PlayersSlain = questRecord[20].GetUInt32(); + BonusTalents = questRecord[21].GetUInt32(); + PrevQuestId = questRecord[22].GetInt32(); + NextQuestId = questRecord[23].GetInt32(); + ExclusiveGroup = questRecord[24].GetInt32(); + NextQuestInChain = questRecord[25].GetUInt32(); + SrcItemId = questRecord[26].GetUInt32(); + SrcItemCount = questRecord[27].GetUInt32(); + SrcSpell = questRecord[28].GetUInt32(); + Title = questRecord[29].GetCppString(); + Details = questRecord[30].GetCppString(); + Objectives = questRecord[31].GetCppString(); + OfferRewardText = questRecord[32].GetCppString(); + RequestItemsText = questRecord[33].GetCppString(); + EndText = questRecord[34].GetCppString(); for (int i = 0; i < QUEST_OBJECTIVES_COUNT; ++i) - ObjectiveText[i] = questRecord[33+i].GetCppString(); + ObjectiveText[i] = questRecord[35+i].GetCppString(); for (int i = 0; i < QUEST_OBJECTIVES_COUNT; ++i) - ReqItemId[i] = questRecord[37+i].GetUInt32(); + ReqItemId[i] = questRecord[39+i].GetUInt32(); for (int i = 0; i < QUEST_OBJECTIVES_COUNT; ++i) - ReqItemCount[i] = questRecord[41+i].GetUInt32(); + ReqItemCount[i] = questRecord[43+i].GetUInt32(); for (int i = 0; i < QUEST_SOURCE_ITEM_IDS_COUNT; ++i) - ReqSourceId[i] = questRecord[45+i].GetUInt32(); + ReqSourceId[i] = questRecord[47+i].GetUInt32(); for (int i = 0; i < QUEST_SOURCE_ITEM_IDS_COUNT; ++i) - ReqSourceCount[i] = questRecord[49+i].GetUInt32(); + ReqSourceCount[i] = questRecord[51+i].GetUInt32(); for (int i = 0; i < QUEST_SOURCE_ITEM_IDS_COUNT; ++i) - ReqSourceRef[i] = questRecord[53+i].GetUInt32(); + ReqSourceRef[i] = questRecord[55+i].GetUInt32(); for (int i = 0; i < QUEST_OBJECTIVES_COUNT; ++i) - ReqCreatureOrGOId[i] = questRecord[57+i].GetInt32(); + ReqCreatureOrGOId[i] = questRecord[59+i].GetInt32(); for (int i = 0; i < QUEST_OBJECTIVES_COUNT; ++i) - ReqCreatureOrGOCount[i] = questRecord[61+i].GetUInt32(); + ReqCreatureOrGOCount[i] = questRecord[63+i].GetUInt32(); for (int i = 0; i < QUEST_OBJECTIVES_COUNT; ++i) - ReqSpell[i] = questRecord[65+i].GetUInt32(); + ReqSpell[i] = questRecord[67+i].GetUInt32(); for (int i = 0; i < QUEST_REWARD_CHOICES_COUNT; ++i) - RewChoiceItemId[i] = questRecord[69+i].GetUInt32(); + RewChoiceItemId[i] = questRecord[71+i].GetUInt32(); for (int i = 0; i < QUEST_REWARD_CHOICES_COUNT; ++i) - RewChoiceItemCount[i] = questRecord[75+i].GetUInt32(); + RewChoiceItemCount[i] = questRecord[77+i].GetUInt32(); for (int i = 0; i < QUEST_REWARDS_COUNT; ++i) - RewItemId[i] = questRecord[81+i].GetUInt32(); + RewItemId[i] = questRecord[83+i].GetUInt32(); for (int i = 0; i < QUEST_REWARDS_COUNT; ++i) - RewItemCount[i] = questRecord[85+i].GetUInt32(); + RewItemCount[i] = questRecord[87+i].GetUInt32(); for (int i = 0; i < QUEST_REPUTATIONS_COUNT; ++i) - RewRepFaction[i] = questRecord[89+i].GetUInt32(); + RewRepFaction[i] = questRecord[91+i].GetUInt32(); for (int i = 0; i < QUEST_REPUTATIONS_COUNT; ++i) - RewRepValue[i] = questRecord[94+i].GetInt32(); + RewRepValue[i] = questRecord[96+i].GetInt32(); - RewHonorableKills = questRecord[99].GetUInt32(); - RewOrReqMoney = questRecord[100].GetInt32(); - RewMoneyMaxLevel = questRecord[101].GetUInt32(); - RewSpell = questRecord[102].GetUInt32(); - RewSpellCast = questRecord[103].GetUInt32(); - RewMailTemplateId = questRecord[104].GetUInt32(); - RewMailDelaySecs = questRecord[105].GetUInt32(); - PointMapId = questRecord[106].GetUInt32(); - PointX = questRecord[107].GetFloat(); - PointY = questRecord[108].GetFloat(); - PointOpt = questRecord[109].GetUInt32(); + RewHonorableKills = questRecord[101].GetUInt32(); + RewOrReqMoney = questRecord[102].GetInt32(); + RewMoneyMaxLevel = questRecord[103].GetUInt32(); + RewSpell = questRecord[104].GetUInt32(); + RewSpellCast = questRecord[105].GetUInt32(); + RewMailTemplateId = questRecord[106].GetUInt32(); + RewMailDelaySecs = questRecord[107].GetUInt32(); + PointMapId = questRecord[108].GetUInt32(); + PointX = questRecord[109].GetFloat(); + PointY = questRecord[110].GetFloat(); + PointOpt = questRecord[111].GetUInt32(); for (int i = 0; i < QUEST_EMOTE_COUNT; ++i) - DetailsEmote[i] = questRecord[110+i].GetUInt32(); + DetailsEmote[i] = questRecord[112+i].GetUInt32(); - IncompleteEmote = questRecord[114].GetUInt32(); - CompleteEmote = questRecord[115].GetUInt32(); + IncompleteEmote = questRecord[116].GetUInt32(); + CompleteEmote = questRecord[117].GetUInt32(); for (int i = 0; i < QUEST_EMOTE_COUNT; ++i) - OfferRewardEmote[i] = questRecord[116+i].GetInt32(); + OfferRewardEmote[i] = questRecord[118+i].GetInt32(); - QuestStartScript = questRecord[120].GetUInt32(); - QuestCompleteScript = questRecord[121].GetUInt32(); + QuestStartScript = questRecord[122].GetUInt32(); + QuestCompleteScript = questRecord[123].GetUInt32(); QuestFlags |= SpecialFlags << 16; diff --git a/src/game/QuestDef.h b/src/game/QuestDef.h index 316209393..8c173fdb7 100644 --- a/src/game/QuestDef.h +++ b/src/game/QuestDef.h @@ -42,30 +42,33 @@ class ObjectMgr; enum QuestFailedReasons { INVALIDREASON_DONT_HAVE_REQ = 0, - INVALIDREASON_QUEST_FAILED_LOW_LEVEL = 1, //You are not high enough level for that quest. - INVALIDREASON_QUEST_FAILED_WRONG_RACE = 6, //That quest is not available to your race. - INVALIDREASON_QUEST_ALREADY_DONE = 7, //You have completed that quest. - INVALIDREASON_QUEST_ONLY_ONE_TIMED = 12, //You can only be on one timed quest at a time. - INVALIDREASON_QUEST_ALREADY_ON = 13, //You are already on that quest - INVALIDREASON_QUEST_FAILED_EXPANSION = 16, //This quest requires an expansion enabled account. - INVALIDREASON_QUEST_ALREADY_ON2 = 18, //You are already on that quest - INVALIDREASON_QUEST_FAILED_MISSING_ITEMS = 21, //You don't have the required items with you. Check storage. - INVALIDREASON_QUEST_FAILED_NOT_ENOUGH_MONEY = 23, //You don't have enough money for that quest. - INVALIDREASON_DAILY_QUESTS_REMAINING = 26, //You have already completed 10 daily quests today - INVALIDREASON_QUEST_FAILED_CAIS = 27, //You cannot complete quests once you have reached tired time + INVALIDREASON_QUEST_FAILED_LOW_LEVEL = 1, // You are not high enough level for that quest. + INVALIDREASON_QUEST_FAILED_WRONG_RACE = 6, // That quest is not available to your race. + INVALIDREASON_QUEST_ALREADY_DONE = 7, // You have completed that quest. + INVALIDREASON_QUEST_ONLY_ONE_TIMED = 12, // You can only be on one timed quest at a time. + INVALIDREASON_QUEST_ALREADY_ON = 13, // You are already on that quest. + INVALIDREASON_QUEST_FAILED_EXPANSION = 16, // This quest requires an expansion enabled account. + INVALIDREASON_QUEST_ALREADY_ON2 = 18, // You are already on that quest. + INVALIDREASON_QUEST_FAILED_MISSING_ITEMS = 21, // You don't have the required items with you. Check storage. + INVALIDREASON_QUEST_FAILED_NOT_ENOUGH_MONEY = 23, // You don't have enough money for that quest. + INVALIDREASON_DAILY_QUESTS_REMAINING = 26, // You have already completed 25 daily quests today. + INVALIDREASON_QUEST_FAILED_CAIS = 27, // You cannot complete quests once you have reached tired time. + INVALIDREASON_DAILY_QUEST_COMPLETED_TODAY = 29 // You have completed that daily quest today. }; enum QuestShareMessages { - QUEST_PARTY_MSG_SHARING_QUEST = 0, - QUEST_PARTY_MSG_CANT_TAKE_QUEST = 1, - QUEST_PARTY_MSG_ACCEPT_QUEST = 2, - QUEST_PARTY_MSG_REFUSE_QUEST = 3, - QUEST_PARTY_MSG_TOO_FAR = 4, - QUEST_PARTY_MSG_BUSY = 5, - QUEST_PARTY_MSG_LOG_FULL = 6, - QUEST_PARTY_MSG_HAVE_QUEST = 7, - QUEST_PARTY_MSG_FINISH_QUEST = 8, + QUEST_PARTY_MSG_SHARING_QUEST = 0, + QUEST_PARTY_MSG_CANT_TAKE_QUEST = 1, + QUEST_PARTY_MSG_ACCEPT_QUEST = 2, + QUEST_PARTY_MSG_DECLINE_QUEST = 3, + QUEST_PARTY_MSG_BUSY = 4, + QUEST_PARTY_MSG_LOG_FULL = 5, + QUEST_PARTY_MSG_HAVE_QUEST = 6, + QUEST_PARTY_MSG_FINISH_QUEST = 7, + QUEST_PARTY_MSG_CANT_BE_SHARED_TODAY = 8, + QUEST_PARTY_MSG_SHARING_TIMER_EXPIRED = 9, + QUEST_PARTY_MSG_NOT_IN_PARTY = 10 }; enum __QuestTradeSkill @@ -188,6 +191,8 @@ class Quest int32 GetExclusiveGroup() const { return ExclusiveGroup; } uint32 GetNextQuestInChain() const { return NextQuestInChain; } uint32 GetCharTitleId() const { return CharTitleId; } + uint32 GetPlayersSlain() const { return PlayersSlain; } + uint32 GetBonusTalents() const { return BonusTalents; } uint32 GetSrcItemId() const { return SrcItemId; } uint32 GetSrcItemCount() const { return SrcItemCount; } uint32 GetSrcSpell() const { return SrcSpell; } @@ -275,6 +280,8 @@ class Quest uint32 LimitTime; uint32 QuestFlags; uint32 CharTitleId; + uint32 PlayersSlain; + uint32 BonusTalents; int32 PrevQuestId; int32 NextQuestId; int32 ExclusiveGroup; diff --git a/src/game/QuestHandler.cpp b/src/game/QuestHandler.cpp index 5b68829ab..bbb3fa764 100644 --- a/src/game/QuestHandler.cpp +++ b/src/game/QuestHandler.cpp @@ -441,12 +441,6 @@ void WorldSession::HandleQuestPushToParty(WorldPacket& recvPacket) _player->SendPushToPartyResponse(pPlayer, QUEST_PARTY_MSG_SHARING_QUEST); - if( _player->GetDistance( pPlayer ) > 10 ) - { - _player->SendPushToPartyResponse( pPlayer, QUEST_PARTY_MSG_TOO_FAR ); - continue; - } - if( !pPlayer->SatisfyQuestStatus( pQuest, false ) ) { _player->SendPushToPartyResponse( pPlayer, QUEST_PARTY_MSG_HAVE_QUEST ); diff --git a/src/game/SharedDefines.h b/src/game/SharedDefines.h index 8ae1cf27b..882311934 100644 --- a/src/game/SharedDefines.h +++ b/src/game/SharedDefines.h @@ -40,16 +40,24 @@ enum Races RACE_TAUREN = 6, RACE_GNOME = 7, RACE_TROLL = 8, - RACE_GOBLIN = 9, + //RACE_GOBLIN = 9, RACE_BLOODELF = 10, RACE_DRAENEI = 11, - RACE_FEL_ORC = 12, - RACE_NAGA = 13, - RACE_BROKEN = 14, - RACE_SKELETON = 15, - MAX_RACES = 16 + //RACE_FEL_ORC = 12, + //RACE_NAGA = 13, + //RACE_BROKEN = 14, + //RACE_SKELETON = 15, + //RACE_VRYKUL = 16, + //RACE_TUSKARR = 17, + //RACE_FOREST_TROLL = 18, + //RACE_TAUNKA = 19, + //RACE_NORTHREND_SKELETON = 20, + //RACE_ICE_TROLL = 21 }; +// max+1 for player race +#define MAX_RACES 12 + #define RACEMASK_ALL_PLAYABLE \ ((1<<(RACE_HUMAN-1)) |(1<<(RACE_ORC-1)) |(1<<(RACE_DWARF-1)) | \ (1<<(RACE_NIGHTELF-1))|(1<<(RACE_UNDEAD_PLAYER-1))|(1<<(RACE_TAUREN-1)) | \ @@ -70,13 +78,16 @@ enum Classes CLASS_WARLOCK = 9, // CLASS_UNK2 = 10,unused CLASS_DRUID = 11, - MAX_CLASSES = 12 }; +// max+1 for player class +#define MAX_CLASSES 12 + #define CLASSMASK_ALL_PLAYABLE \ ((1<<(CLASS_WARRIOR-1))|(1<<(CLASS_PALADIN-1))|(1<<(CLASS_HUNTER-1))| \ (1<<(CLASS_ROGUE-1)) |(1<<(CLASS_PRIEST-1)) |(1<<(CLASS_SHAMAN-1))| \ - (1<<(CLASS_MAGE-1)) |(1<<(CLASS_WARLOCK-1))|(1<<(CLASS_DRUID-1)) ) + (1<<(CLASS_MAGE-1)) |(1<<(CLASS_WARLOCK-1))|(1<<(CLASS_DRUID-1)) | \ + (1<<(CLASS_DEATH_KNIGHT-1)) ) #define CLASSMASK_WAND_USERS ((1<<(CLASS_PRIEST-1))|(1<<(CLASS_MAGE-1))|(1<<(CLASS_WARLOCK-1))) @@ -122,11 +133,12 @@ enum Powers POWER_FOCUS = 2, POWER_ENERGY = 3, POWER_HAPPINESS = 4, - POWER_RUNES = 5, + POWER_RUNE = 5, + POWER_RUNIC_POWER = 6, POWER_HEALTH = 0xFFFFFFFE // (-2 as signed value) }; -#define MAX_POWERS 5 // not count POWER_RUNES for now +#define MAX_POWERS 7 enum SpellSchools { @@ -187,10 +199,11 @@ enum ItemQualities ITEM_QUALITY_RARE = 3, //BLUE ITEM_QUALITY_EPIC = 4, //PURPLE ITEM_QUALITY_LEGENDARY = 5, //ORANGE - ITEM_QUALITY_ARTIFACT = 6 //LIGHT YELLOW + ITEM_QUALITY_ARTIFACT = 6, //LIGHT YELLOW + ITEM_QUALITY_HEIRLOOM = 7 }; -#define MAX_ITEM_QUALITY 7 +#define MAX_ITEM_QUALITY 8 // *********************************** // Spell Attributes definitions @@ -199,7 +212,7 @@ enum ItemQualities #define SPELL_ATTR_UNK0 0x00000001 // 0 #define SPELL_ATTR_RANGED 0x00000002 // 1 All ranged abilites have this flag #define SPELL_ATTR_ON_NEXT_SWING_1 0x00000004 // 2 on next swing -#define SPELL_ATTR_UNK3 0x00000008 // 3 not set in 2.4.2 +#define SPELL_ATTR_UNK3 0x00000008 // 3 not set in 3.0.3 #define SPELL_ATTR_UNK4 0x00000010 // 4 #define SPELL_ATTR_UNK5 0x00000020 // 5 trade spells? #define SPELL_ATTR_PASSIVE 0x00000040 // 6 Passive spell @@ -254,7 +267,7 @@ enum ItemQualities #define SPELL_ATTR_EX_REQ_COMBO_POINTS2 0x00400000 // 22 Req combo points on target #define SPELL_ATTR_EX_UNK23 0x00800000 // 23 #define SPELL_ATTR_EX_UNK24 0x01000000 // 24 Req fishing pole?? -#define SPELL_ATTR_EX_UNK25 0x02000000 // 25 not set in 2.4.2 +#define SPELL_ATTR_EX_UNK25 0x02000000 // 25 #define SPELL_ATTR_EX_UNK26 0x04000000 // 26 #define SPELL_ATTR_EX_UNK27 0x08000000 // 27 #define SPELL_ATTR_EX_UNK28 0x10000000 // 28 @@ -270,14 +283,14 @@ enum ItemQualities #define SPELL_ATTR_EX2_UNK5 0x00000020 // 5 #define SPELL_ATTR_EX2_UNK6 0x00000040 // 6 #define SPELL_ATTR_EX2_UNK7 0x00000080 // 7 -#define SPELL_ATTR_EX2_UNK8 0x00000100 // 8 not set in 2.4.2 +#define SPELL_ATTR_EX2_UNK8 0x00000100 // 8 not set in 3.0.3 #define SPELL_ATTR_EX2_UNK9 0x00000200 // 9 #define SPELL_ATTR_EX2_UNK10 0x00000400 // 10 #define SPELL_ATTR_EX2_HEALTH_FUNNEL 0x00000800 // 11 #define SPELL_ATTR_EX2_UNK12 0x00001000 // 12 #define SPELL_ATTR_EX2_UNK13 0x00002000 // 13 #define SPELL_ATTR_EX2_UNK14 0x00004000 // 14 -#define SPELL_ATTR_EX2_UNK15 0x00008000 // 15 not set in 2.4.2 +#define SPELL_ATTR_EX2_UNK15 0x00008000 // 15 not set in 3.0.3 #define SPELL_ATTR_EX2_UNK16 0x00010000 // 16 #define SPELL_ATTR_EX2_UNK17 0x00020000 // 17 Hunters Shot and Stings only have this flag #define SPELL_ATTR_EX2_UNK18 0x00040000 // 18 Only Revive pet - possible req dead pet @@ -395,37 +408,37 @@ enum ItemQualities #define SPELL_ATTR_EX5_UNK31 0x80000000 // 31 Forces all nearby enemies to focus attacks caster #define SPELL_ATTR_EX6_UNK0 0x00000001 // 0 Only Move spell have this flag -#define SPELL_ATTR_EX6_UNK1 0x00000002 // 1 not set in 2.4.2 +#define SPELL_ATTR_EX6_UNK1 0x00000002 // 1 not set in 3.0.3 #define SPELL_ATTR_EX6_UNK2 0x00000004 // 2 #define SPELL_ATTR_EX6_UNK3 0x00000008 // 3 -#define SPELL_ATTR_EX6_UNK4 0x00000010 // 4 not set in 2.4.2 +#define SPELL_ATTR_EX6_UNK4 0x00000010 // 4 #define SPELL_ATTR_EX6_UNK5 0x00000020 // 5 #define SPELL_ATTR_EX6_UNK6 0x00000040 // 6 #define SPELL_ATTR_EX6_UNK7 0x00000080 // 7 #define SPELL_ATTR_EX6_UNK8 0x00000100 // 8 -#define SPELL_ATTR_EX6_UNK9 0x00000200 // 9 not set in 2.4.2 +#define SPELL_ATTR_EX6_UNK9 0x00000200 // 9 #define SPELL_ATTR_EX6_UNK10 0x00000400 // 10 #define SPELL_ATTR_EX6_UNK11 0x00000800 // 11 -#define SPELL_ATTR_EX6_UNK12 0x00001000 // 12 not set in 2.4.2 -#define SPELL_ATTR_EX6_UNK13 0x00002000 // 13 not set in 2.4.2 -#define SPELL_ATTR_EX6_UNK14 0x00004000 // 14 not set in 2.4.2 -#define SPELL_ATTR_EX6_UNK15 0x00008000 // 15 not set in 2.4.2 -#define SPELL_ATTR_EX6_UNK16 0x00010000 // 16 not set in 2.4.2 -#define SPELL_ATTR_EX6_UNK17 0x00020000 // 17 not set in 2.4.2 -#define SPELL_ATTR_EX6_UNK18 0x00040000 // 18 not set in 2.4.2 -#define SPELL_ATTR_EX6_UNK19 0x00080000 // 19 not set in 2.4.2 -#define SPELL_ATTR_EX6_UNK20 0x00100000 // 20 not set in 2.4.2 -#define SPELL_ATTR_EX6_UNK21 0x00200000 // 21 not set in 2.4.2 -#define SPELL_ATTR_EX6_UNK22 0x00400000 // 22 not set in 2.4.2 -#define SPELL_ATTR_EX6_UNK23 0x00800000 // 23 not set in 2.4.2 -#define SPELL_ATTR_EX6_UNK24 0x01000000 // 24 not set in 2.4.2 -#define SPELL_ATTR_EX6_UNK25 0x02000000 // 25 not set in 2.4.2 -#define SPELL_ATTR_EX6_UNK26 0x04000000 // 26 not set in 2.4.2 -#define SPELL_ATTR_EX6_UNK27 0x08000000 // 27 not set in 2.4.2 -#define SPELL_ATTR_EX6_UNK28 0x10000000 // 28 not set in 2.4.2 -#define SPELL_ATTR_EX6_UNK29 0x20000000 // 29 not set in 2.4.2 -#define SPELL_ATTR_EX6_UNK30 0x40000000 // 30 not set in 2.4.2 -#define SPELL_ATTR_EX6_UNK31 0x80000000 // 31 not set in 2.4.2 +#define SPELL_ATTR_EX6_UNK12 0x00001000 // 12 +#define SPELL_ATTR_EX6_UNK13 0x00002000 // 13 +#define SPELL_ATTR_EX6_UNK14 0x00004000 // 14 +#define SPELL_ATTR_EX6_UNK15 0x00008000 // 15 not set in 3.0.3 +#define SPELL_ATTR_EX6_UNK16 0x00010000 // 16 +#define SPELL_ATTR_EX6_UNK17 0x00020000 // 17 +#define SPELL_ATTR_EX6_UNK18 0x00040000 // 18 +#define SPELL_ATTR_EX6_UNK19 0x00080000 // 19 +#define SPELL_ATTR_EX6_UNK20 0x00100000 // 20 +#define SPELL_ATTR_EX6_UNK21 0x00200000 // 21 +#define SPELL_ATTR_EX6_UNK22 0x00400000 // 22 +#define SPELL_ATTR_EX6_UNK23 0x00800000 // 23 not set in 3.0.3 +#define SPELL_ATTR_EX6_UNK24 0x01000000 // 24 not set in 3.0.3 +#define SPELL_ATTR_EX6_UNK25 0x02000000 // 25 not set in 3.0.3 +#define SPELL_ATTR_EX6_UNK26 0x04000000 // 26 not set in 3.0.3 +#define SPELL_ATTR_EX6_UNK27 0x08000000 // 27 not set in 3.0.3 +#define SPELL_ATTR_EX6_UNK28 0x10000000 // 28 not set in 3.0.3 +#define SPELL_ATTR_EX6_UNK29 0x20000000 // 29 not set in 3.0.3 +#define SPELL_ATTR_EX6_UNK30 0x40000000 // 30 not set in 3.0.3 +#define SPELL_ATTR_EX6_UNK31 0x80000000 // 31 not set in 3.0.3 enum SheathTypes { @@ -548,7 +561,7 @@ enum SpellEffects SPELL_EFFECT_SUMMON_GUARDIAN = 42, SPELL_EFFECT_TELEPORT_UNITS_FACE_CASTER= 43, SPELL_EFFECT_SKILL_STEP = 44, - SPELL_EFFECT_UNDEFINED_45 = 45, + SPELL_EFFECT_ADD_HONOR = 45, SPELL_EFFECT_SPAWN = 46, SPELL_EFFECT_TRADE_SKILL = 47, SPELL_EFFECT_STEALTH = 48, @@ -568,16 +581,16 @@ enum SpellEffects SPELL_EFFECT_POWER_BURN = 62, SPELL_EFFECT_THREAT = 63, SPELL_EFFECT_TRIGGER_SPELL = 64, - SPELL_EFFECT_HEALTH_FUNNEL = 65, - SPELL_EFFECT_POWER_FUNNEL = 66, + SPELL_EFFECT_APPLY_AREA_AURA_RAID = 65, + SPELL_EFFECT_CREATE_MANA_GEM = 66, SPELL_EFFECT_HEAL_MAX_HEALTH = 67, SPELL_EFFECT_INTERRUPT_CAST = 68, SPELL_EFFECT_DISTRACT = 69, SPELL_EFFECT_PULL = 70, SPELL_EFFECT_PICKPOCKET = 71, SPELL_EFFECT_ADD_FARSIGHT = 72, - SPELL_EFFECT_SUMMON_POSSESSED = 73, - SPELL_EFFECT_SUMMON_TOTEM = 74, + SPELL_EFFECT_UNTRAIN_TALENTS = 73, + SPELL_EFFECT_APPLY_GLYPH = 74, SPELL_EFFECT_HEAL_MECHANICAL = 75, SPELL_EFFECT_SUMMON_OBJECT_WILD = 76, SPELL_EFFECT_SCRIPT_EFFECT = 77, @@ -590,10 +603,10 @@ enum SpellEffects SPELL_EFFECT_STUCK = 84, SPELL_EFFECT_SUMMON_PLAYER = 85, SPELL_EFFECT_ACTIVATE_OBJECT = 86, - SPELL_EFFECT_SUMMON_TOTEM_SLOT1 = 87, - SPELL_EFFECT_SUMMON_TOTEM_SLOT2 = 88, - SPELL_EFFECT_SUMMON_TOTEM_SLOT3 = 89, - SPELL_EFFECT_SUMMON_TOTEM_SLOT4 = 90, + SPELL_EFFECT_WMO_DAMAGE = 87, + SPELL_EFFECT_WMO_REPAIR = 88, + SPELL_EFFECT_WMO_CHANGE = 89, + SPELL_EFFECT_KILL_CREDIT = 90, SPELL_EFFECT_THREAT_ALL = 91, SPELL_EFFECT_ENCHANT_HELD_ITEM = 92, SPELL_EFFECT_SUMMON_PHANTASM = 93, @@ -637,19 +650,19 @@ enum SpellEffects SPELL_EFFECT_131 = 131, SPELL_EFFECT_132 = 132, SPELL_EFFECT_UNLEARN_SPECIALIZATION = 133, - SPELL_EFFECT_KILL_CREDIT = 134, + SPELL_EFFECT_KILL_CREDIT2 = 134, SPELL_EFFECT_135 = 135, SPELL_EFFECT_HEAL_PCT = 136, SPELL_EFFECT_ENERGIZE_PCT = 137, SPELL_EFFECT_138 = 138, - SPELL_EFFECT_139 = 139, + SPELL_EFFECT_CLEAR_QUEST = 139, SPELL_EFFECT_FORCE_CAST = 140, SPELL_EFFECT_141 = 141, SPELL_EFFECT_TRIGGER_SPELL_WITH_VALUE = 142, SPELL_EFFECT_APPLY_AREA_AURA_OWNER = 143, SPELL_EFFECT_144 = 144, SPELL_EFFECT_145 = 145, - SPELL_EFFECT_146 = 146, + SPELL_EFFECT_ACTIVATE_RUNE = 146, SPELL_EFFECT_QUEST_FAIL = 147, SPELL_EFFECT_148 = 148, SPELL_EFFECT_149 = 149, @@ -657,7 +670,13 @@ enum SpellEffects SPELL_EFFECT_TRIGGER_SPELL_2 = 151, SPELL_EFFECT_152 = 152, SPELL_EFFECT_153 = 153, - TOTAL_SPELL_EFFECTS = 154 + SPELL_EFFECT_154 = 154, + SPELL_EFFECT_TITAN_GRIP = 155, + SPELL_EFFECT_ADD_SOCKET = 156, + SPELL_EFFECT_157 = 157, + SPELL_EFFECT_MILLING = 158, + SPELL_EFFECT_ALLOW_RENAME_PET = 159, + TOTAL_SPELL_EFFECTS = 160 }; // Spell aura states @@ -685,7 +704,8 @@ enum AuraState AURA_STATE_DEADLY_POISON = 16, // T | AURA_STATE_FORBEARANCE = 17, // c t| AURA_STATE_WEAKENED_SOUL = 18, // t| - AURA_STATE_HYPOTHERMIA = 19 // c | + AURA_STATE_HYPOTHERMIA = 19, // c | + AURA_STATE_HEALTH_ABOVE_75_PERCENT = 23, // C | not implemented yet }; // Spell mechanics @@ -693,11 +713,11 @@ enum Mechanics { MECHANIC_NONE = 0, MECHANIC_CHARM = 1, - MECHANIC_CONFUSED = 2, + MECHANIC_DISORIENTED = 2, MECHANIC_DISARM = 3, MECHANIC_DISTRACT = 4, MECHANIC_FEAR = 5, - MECHANIC_FUMBLE = 6, + MECHANIC_GRIP = 6, MECHANIC_ROOT = 7, MECHANIC_PACIFY = 8, //0 spells use this mechanic MECHANIC_SILENCE = 9, @@ -713,7 +733,7 @@ enum Mechanics MECHANIC_SHIELD = 19, MECHANIC_SHACKLE = 20, MECHANIC_MOUNT = 21, - MECHANIC_PERSUADE = 22, //0 spells use this mechanic + MECHANIC_INFECTED = 22, MECHANIC_TURN = 23, MECHANIC_HORROR = 24, MECHANIC_INVULNERABILITY = 25, @@ -721,12 +741,13 @@ enum Mechanics MECHANIC_DAZE = 27, MECHANIC_DISCOVERY = 28, MECHANIC_IMMUNE_SHIELD = 29, // Divine (Blessing) Shield/Protection and Ice Block - MECHANIC_SAPPED = 30 + MECHANIC_SAPPED = 30, + MECHANIC_ENRAGED = 31 }; // Used for spell 42292 Immune Movement Impairment and Loss of Control (0x49967da6) #define IMMUNE_TO_MOVEMENT_IMPAIRMENT_AND_LOSS_CONTROL_MASK ( \ - (1<DependsOnSpell && !player->HasSpell(talentInfo->DependsOnSpell) ) - return; - // Find out how many points we have in this field uint32 spentPoints = 0; diff --git a/src/game/SocialMgr.h b/src/game/SocialMgr.h index 8c873d8a0..0a7f822a7 100644 --- a/src/game/SocialMgr.h +++ b/src/game/SocialMgr.h @@ -63,7 +63,7 @@ struct FriendInfo Note = ""; } - FriendInfo(uint32 flags, std::string note) + FriendInfo(uint32 flags, const std::string& note) { Status = FRIEND_STATUS_OFFLINE; Flags = flags; diff --git a/src/game/Spell.cpp b/src/game/Spell.cpp index 916ea9a64..5b24781ad 100644 --- a/src/game/Spell.cpp +++ b/src/game/Spell.cpp @@ -219,7 +219,7 @@ void SpellCastTargets::write ( WorldPacket * data ) { *data << uint32(m_targetMask); - if( m_targetMask & ( TARGET_FLAG_UNIT | TARGET_FLAG_PVP_CORPSE | TARGET_FLAG_OBJECT | TARGET_FLAG_CORPSE | TARGET_FLAG_UNK2 ) ) + if( m_targetMask & ( TARGET_FLAG_UNIT | TARGET_FLAG_PVP_CORPSE | TARGET_FLAG_OBJECT | TARGET_FLAG_OBJECT_UNK | TARGET_FLAG_CORPSE | TARGET_FLAG_UNK2 ) ) { if(m_targetMask & TARGET_FLAG_UNIT) { @@ -339,6 +339,7 @@ Spell::Spell( Unit* Caster, SpellEntry const *info, bool triggered, uint64 origi gameObjTarget = NULL; focusObject = NULL; m_cast_count = 0; + m_glyphIndex = 0; m_triggeredByAuraSpell = NULL; //Auto Shot & Shoot @@ -347,6 +348,7 @@ Spell::Spell( Unit* Caster, SpellEntry const *info, bool triggered, uint64 origi else m_autoRepeat = false; + m_runesState = 0; m_powerCost = 0; // setup to correct value in Spell::prepare, don't must be used before. m_casttime = 0; // setup to correct value in Spell::prepare, don't must be used before. m_timer = 0; // will set to castime in prepare @@ -535,7 +537,6 @@ void Spell::FillTargetMap() case SPELL_EFFECT_LEARN_SPELL: case SPELL_EFFECT_SKILL_STEP: case SPELL_EFFECT_PROFICIENCY: - case SPELL_EFFECT_SUMMON_POSSESSED: case SPELL_EFFECT_SUMMON_OBJECT_WILD: case SPELL_EFFECT_SELF_RESURRECT: case SPELL_EFFECT_REPUTATION: @@ -578,6 +579,7 @@ void Spell::FillTargetMap() case SPELL_EFFECT_SUMMON_GUARDIAN: case SPELL_EFFECT_TRANS_DOOR: case SPELL_EFFECT_ADD_FARSIGHT: + case SPELL_EFFECT_APPLY_GLYPH: case SPELL_EFFECT_STUCK: case SPELL_EFFECT_DESTROY_ALL_TOTEMS: case SPELL_EFFECT_SUMMON_DEMON: @@ -593,6 +595,7 @@ void Spell::FillTargetMap() case SPELL_EFFECT_DISENCHANT: case SPELL_EFFECT_FEED_PET: case SPELL_EFFECT_PROSPECTING: + case SPELL_EFFECT_MILLING: if(m_targets.getItemTarget()) AddItemTarget(m_targets.getItemTarget(), i); break; @@ -1142,6 +1145,17 @@ void Spell::DoSpellHitOnUnit(Unit *unit, const uint32 effectMask) return; } + if (unit->GetTypeId() == TYPEID_PLAYER) + { + ((Player*)unit)->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_BE_SPELL_TARGET, m_spellInfo->Id); + ((Player*)unit)->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_BE_SPELL_TARGET2, m_spellInfo->Id); + } + + if(m_caster->GetTypeId() == TYPEID_PLAYER) + { + ((Player*)m_caster)->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_CAST_SPELL2, m_spellInfo->Id, 0, unit); + } + if( m_caster != unit ) { if( !m_caster->IsFriendlyTo(unit) ) @@ -1354,7 +1368,15 @@ void Spell::SetTargetMap(uint32 i,uint32 cur,std::list &TagUnitMap) if(Player* modOwner = m_originalCaster->GetSpellModOwner()) modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_JUMP_TARGETS, EffectChainTarget, this); + // Get spell max affected targets uint32 unMaxTargets = m_spellInfo->MaxAffectedTargets; + Unit::AuraList const& mod = m_caster->GetAurasByType(SPELL_AURA_MOD_MAX_AFFECTED_TARGETS); + for(Unit::AuraList::const_iterator m = mod.begin(); m != mod.end(); ++m) + { + if (!(*m)->isAffectedOnSpell(m_spellInfo)) + continue; + unMaxTargets+=(*m)->GetModifier()->m_amount; + } switch(cur) { case TARGET_TOTEM_EARTH: @@ -1734,7 +1756,7 @@ void Spell::SetTargetMap(uint32 i,uint32 cur,std::list &TagUnitMap) cell.data.Part.reserved = ALL_DISTRICT; cell.SetNoCreate(); - bool inFront = m_spellInfo->SpellVisual != 3879; + bool inFront = m_spellInfo->SpellVisual[0] != 3879; MaNGOS::SpellNotifierCreatureAndPlayer notifier(*this, TagUnitMap, radius, inFront ? PUSH_IN_FRONT : PUSH_IN_BACK,SPELL_TARGETS_AOE_DAMAGE); TypeContainerVisitor world_object_notifier(notifier); @@ -2267,6 +2289,14 @@ void Spell::cast(bool skipCheck) // set to real guid to be sent later to the client m_targets.updateTradeSlotItem(); + if (m_caster->GetTypeId() == TYPEID_PLAYER) + { + if (m_CastItem) + ((Player*)m_caster)->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_USE_ITEM, m_CastItem->GetEntry()); + + ((Player*)m_caster)->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_CAST_SPELL, m_spellInfo->Id); + } + // CAST SPELL SendSpellCooldown(); @@ -2675,7 +2705,7 @@ void Spell::finish(bool ok) { SpellEntry const *auraSpellInfo = (*i)->GetSpellProto(); uint32 auraSpellIdx = (*i)->GetEffIndex(); - if (IsAffectedBy(auraSpellInfo, auraSpellIdx)) + if (IsAffectedByAura((*i))) { for(std::list::iterator ihit= m_UniqueTargetInfo.begin();ihit != m_UniqueTargetInfo.end();++ihit) if( ihit->effectMask & (1<Id); data << uint8(result); // problem - data << uint8(m_cast_count); // single cast or multi 2.3 (0/1) switch (result) { case SPELL_FAILED_REQUIRES_SPELL_FOCUS: @@ -2790,18 +2820,11 @@ void Spell::SendCastResult(uint8 result) case SPELL_FAILED_EQUIPPED_ITEM_CLASS: data << uint32(m_spellInfo->EquippedItemClass); data << uint32(m_spellInfo->EquippedItemSubClassMask); - data << uint32(m_spellInfo->EquippedItemInventoryTypeMask); + //data << uint32(m_spellInfo->EquippedItemInventoryTypeMask); break; } ((Player*)m_caster)->GetSession()->SendPacket(&data); } - else - { - WorldPacket data(SMSG_CLEAR_EXTRA_AURA_INFO, (8+4)); - data.append(m_caster->GetPackGUID()); - data << uint32(m_spellInfo->Id); - ((Player*)m_caster)->GetSession()->SendPacket(&data); - } } void Spell::SendSpellStart() @@ -2815,6 +2838,9 @@ void Spell::SendSpellStart() if(IsRangedSpell()) castFlags |= CAST_FLAG_AMMO; + if(m_spellInfo->runeCostID) + castFlags |= CAST_FLAG_UNKNOWN10; + Unit *target = m_targets.getUnitTarget() ? m_targets.getUnitTarget() : m_caster; WorldPacket data(SMSG_SPELL_START, (8+8+4+4+2)); @@ -2824,14 +2850,32 @@ void Spell::SendSpellStart() data.append(m_caster->GetPackGUID()); data.append(m_caster->GetPackGUID()); - data << uint32(m_spellInfo->Id); - data << uint8(m_cast_count); // single cast or multi 2.3 (0/1) - data << uint16(castFlags); - data << uint32(m_timer); + data << uint8(m_cast_count); // pending spell cast? + data << uint32(m_spellInfo->Id); // spellId + data << uint32(castFlags); // cast flags + data << uint32(m_timer); // delay? m_targets.write(&data); - if( castFlags & CAST_FLAG_AMMO ) + if ( castFlags & CAST_FLAG_UNKNOWN6 ) // predicted power? + data << uint32(0); + + if ( castFlags & CAST_FLAG_UNKNOWN7 ) // rune cooldowns list + { + uint8 v1 = 0;//m_runesState; + uint8 v2 = 0;//((Player*)m_caster)->GetRunesState(); + data << uint8(v1); // runes state before + data << uint8(v2); // runes state after + for(uint8 i = 0; i < MAX_RUNES; ++i) + { + uint8 m = (1 << i); + if(m & v1) // usable before... + if(!(m & v2)) // ...but on cooldown now... + data << uint8(0); // some unknown byte (time?) + } + } + + if ( castFlags & CAST_FLAG_AMMO ) WriteAmmoToPacket(&data); m_caster->SendMessageToSet(&data, true); @@ -2851,6 +2895,13 @@ void Spell::SendSpellGo() if(IsRangedSpell()) castFlags |= CAST_FLAG_AMMO; // arrows/bullets visual + if((m_caster->GetTypeId() == TYPEID_PLAYER) && (m_caster->getClass() == CLASS_DEATH_KNIGHT) && m_spellInfo->runeCostID) + { + castFlags |= CAST_FLAG_UNKNOWN10; // same as in SMSG_SPELL_START + castFlags |= CAST_FLAG_UNKNOWN6; // makes cooldowns visible + castFlags |= CAST_FLAG_UNKNOWN7; // rune cooldowns list + } + WorldPacket data(SMSG_SPELL_GO, 50); // guess size if(m_CastItem) data.append(m_CastItem->GetPackGUID()); @@ -2858,17 +2909,53 @@ void Spell::SendSpellGo() data.append(m_caster->GetPackGUID()); data.append(m_caster->GetPackGUID()); - data << uint32(m_spellInfo->Id); - data << uint16(castFlags); + data << uint8(m_cast_count); // pending spell cast? + data << uint32(m_spellInfo->Id); // spellId + data << uint32(castFlags); // cast flags data << uint32(getMSTime()); // timestamp WriteSpellGoTargets(&data); m_targets.write(&data); - if( castFlags & CAST_FLAG_AMMO ) + if ( castFlags & CAST_FLAG_UNKNOWN6 ) // unknown wotlk, predicted power? + data << uint32(0); + + if ( castFlags & CAST_FLAG_UNKNOWN7 ) // rune cooldowns list + { + uint8 v1 = m_runesState; + uint8 v2 = ((Player*)m_caster)->GetRunesState(); + data << uint8(v1); // runes state before + data << uint8(v2); // runes state after + for(uint8 i = 0; i < MAX_RUNES; ++i) + { + uint8 m = (1 << i); + if(m & v1) // usable before... + if(!(m & v2)) // ...but on cooldown now... + data << uint8(0); // some unknown byte (time?) + } + } + + if ( castFlags & CAST_FLAG_UNKNOWN4 ) // unknown wotlk + { + data << float(0); + data << uint32(0); + } + + if ( castFlags & CAST_FLAG_AMMO ) WriteAmmoToPacket(&data); + if ( castFlags & CAST_FLAG_UNKNOWN5 ) // unknown wotlk + { + data << uint32(0); + data << uint32(0); + } + + if ( m_targets.m_targetMask & TARGET_FLAG_DEST_LOCATION ) + { + data << uint8(0); + } + m_caster->SendMessageToSet(&data, true); } @@ -2996,30 +3083,19 @@ void Spell::SendLogExecute() data << uint8(0); break; case SPELL_EFFECT_CREATE_ITEM: + case SPELL_EFFECT_157: data << uint32(m_spellInfo->EffectItemType[0]); break; case SPELL_EFFECT_SUMMON: - case SPELL_EFFECT_SUMMON_WILD: - case SPELL_EFFECT_SUMMON_GUARDIAN: case SPELL_EFFECT_TRANS_DOOR: case SPELL_EFFECT_SUMMON_PET: - case SPELL_EFFECT_SUMMON_POSSESSED: - case SPELL_EFFECT_SUMMON_TOTEM: case SPELL_EFFECT_SUMMON_OBJECT_WILD: case SPELL_EFFECT_CREATE_HOUSE: case SPELL_EFFECT_DUEL: - case SPELL_EFFECT_SUMMON_TOTEM_SLOT1: - case SPELL_EFFECT_SUMMON_TOTEM_SLOT2: - case SPELL_EFFECT_SUMMON_TOTEM_SLOT3: - case SPELL_EFFECT_SUMMON_TOTEM_SLOT4: - case SPELL_EFFECT_SUMMON_PHANTASM: - case SPELL_EFFECT_SUMMON_CRITTER: case SPELL_EFFECT_SUMMON_OBJECT_SLOT1: case SPELL_EFFECT_SUMMON_OBJECT_SLOT2: case SPELL_EFFECT_SUMMON_OBJECT_SLOT3: case SPELL_EFFECT_SUMMON_OBJECT_SLOT4: - case SPELL_EFFECT_SUMMON_DEMON: - case SPELL_EFFECT_150: if(Unit *unit = m_targets.getUnitTarget()) data.append(unit->GetPackGUID()); else if(m_targets.getItemTargetGUID()) @@ -3038,6 +3114,13 @@ void Spell::SendLogExecute() else data << uint8(0); break; + case SPELL_EFFECT_RESURRECT: + case SPELL_EFFECT_RESURRECT_NEW: + if(Unit *unit = m_targets.getUnitTarget()) + data.append(unit->GetPackGUID()); + else + data << uint8(0); + break; default: return; } @@ -3051,13 +3134,16 @@ void Spell::SendInterrupted(uint8 result) { WorldPacket data(SMSG_SPELL_FAILURE, (8+4+1)); data.append(m_caster->GetPackGUID()); - data << m_spellInfo->Id; - data << result; + data << uint8(m_cast_count); + data << uint32(m_spellInfo->Id); + data << uint8(result); m_caster->SendMessageToSet(&data, true); data.Initialize(SMSG_SPELL_FAILED_OTHER, (8+4)); data.append(m_caster->GetPackGUID()); - data << m_spellInfo->Id; + data << uint8(m_cast_count); + data << uint32(m_spellInfo->Id); + data << uint8(result); m_caster->SendMessageToSet(&data, true); } @@ -3125,10 +3211,19 @@ void Spell::SendChannelStart(uint32 duration) void Spell::SendResurrectRequest(Player* target) { - WorldPacket data(SMSG_RESURRECT_REQUEST, (8+4+2+4)); - data << m_caster->GetGUID(); - data << uint32(1) << uint16(0) << uint32(1); + // Both players and NPCs can resurrect using spells - have a look at creature 28487 for example + // However, the packet structure differs slightly + const char* sentName = m_caster->GetTypeId()==TYPEID_PLAYER ?"":m_caster->GetNameForLocaleIdx(target->GetSession()->GetSessionDbLocaleIndex()); + + WorldPacket data(SMSG_RESURRECT_REQUEST, (8+4+strlen(sentName)+1+1+1)); + data << uint64(m_caster->GetGUID()); + data << uint32(strlen(sentName)+1); + + data << sentName; + data << uint8(0); + + data << uint8(m_caster->GetTypeId()==TYPEID_PLAYER ?0:1); target->GetSession()->SendPacket(&data); } @@ -3225,6 +3320,12 @@ void Spell::TakePower() Powers powerType = Powers(m_spellInfo->powerType); + if(powerType == POWER_RUNE) + { + TakeRunePower(); + return; + } + m_caster->ModifyPower(powerType, -(int32)m_powerCost); // Set the five second timer @@ -3232,6 +3333,116 @@ void Spell::TakePower() m_caster->SetLastManaUse(getMSTime()); } +uint8 Spell::CheckRuneCost(uint32 runeCostID) +{ + if(m_caster->GetTypeId() != TYPEID_PLAYER) + return 0; + + Player *plr = (Player*)m_caster; + + if(plr->getClass() != CLASS_DEATH_KNIGHT) + return 0; + + SpellRuneCostEntry const *src = sSpellRuneCostStore.LookupEntry(runeCostID); + + if(!src) + return 0; + + if(src->NoRuneCost()) + return 0; + + int32 runeCost[NUM_RUNE_TYPES]; // blood, frost, unholy, death + + for(uint32 i = 0; i < RUNE_DEATH; ++i) + { + runeCost[i] = src->RuneCost[i]; + } + + runeCost[RUNE_DEATH] = 0; // calculated later + + for(uint32 i = 0; i < MAX_RUNES; ++i) + { + uint8 rune = plr->GetCurrentRune(i); + if((plr->GetRuneCooldown(i) == 0) && (runeCost[rune] > 0)) + { + runeCost[rune]--; + } + } + + for(uint32 i = 0; i < RUNE_DEATH; ++i) + { + if(runeCost[i] > 0) + { + runeCost[RUNE_DEATH] += runeCost[i]; + } + } + + if(runeCost[RUNE_DEATH] > 0) + return SPELL_FAILED_NO_POWER; // not sure if result code is correct + + return 0; +} + +void Spell::TakeRunePower() +{ + if(m_caster->GetTypeId() != TYPEID_PLAYER) + return; + + Player *plr = (Player*)m_caster; + + if(plr->getClass() != CLASS_DEATH_KNIGHT) + return; + + SpellRuneCostEntry const *src = sSpellRuneCostStore.LookupEntry(m_spellInfo->runeCostID); + + if(!src || (src->NoRuneCost() && src->NoRunicPowerGain())) + return; + + m_runesState = plr->GetRunesState(); // store previous state + + int32 runeCost[NUM_RUNE_TYPES]; // blood, frost, unholy, death + + for(uint32 i = 0; i < RUNE_DEATH; ++i) + { + runeCost[i] = src->RuneCost[i]; + } + + runeCost[RUNE_DEATH] = 0; // calculated later + + for(uint32 i = 0; i < MAX_RUNES; ++i) + { + uint8 rune = plr->GetCurrentRune(i); + if((plr->GetRuneCooldown(i) == 0) && (runeCost[rune] > 0)) + { + plr->SetRuneCooldown(i, RUNE_COOLDOWN); // 5*2=10 sec + runeCost[rune]--; + } + } + + runeCost[RUNE_DEATH] = runeCost[RUNE_BLOOD] + runeCost[RUNE_UNHOLY] + runeCost[RUNE_FROST]; + + if(runeCost[RUNE_DEATH] > 0) + { + for(uint32 i = 0; i < MAX_RUNES; ++i) + { + uint8 rune = plr->GetCurrentRune(i); + if((plr->GetRuneCooldown(i) == 0) && (rune == RUNE_DEATH)) + { + plr->SetRuneCooldown(i, RUNE_COOLDOWN); // 5*2=10 sec + runeCost[rune]--; + plr->ConvertRune(i, plr->GetBaseRune(i)); + if(runeCost[RUNE_DEATH] == 0) + break; + } + } + } + + // you can gain some runic power when use runes + float rp = src->runePowerGain;; + rp *= sWorld.getRate(RATE_POWER_RUNICPOWER_INCOME); + plr->ModifyPower(POWER_RUNIC_POWER, (int32)rp); +} + void Spell::TakeReagents() { if(m_IsTriggeredSpell) // reagents used in triggered spell removed by original spell or don't must be removed. @@ -3240,11 +3451,9 @@ void Spell::TakeReagents() if (m_caster->GetTypeId() != TYPEID_PLAYER) return; - if (m_spellInfo->AttributesEx5 & SPELL_ATTR_EX5_NO_REAGENT_WHILE_PREP && - m_caster->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PREPARATION)) - return; - Player* p_caster = (Player*)m_caster; + if (p_caster->CanNoReagentCast(m_spellInfo)) + return; for(uint32 x=0;x<8;x++) { @@ -3367,12 +3576,25 @@ uint8 Spell::CanCast(bool strict) // for now, ignore triggered spells if( strict && !m_IsTriggeredSpell) { - // Cannot be used in this stance/form - if(uint8 shapeError = GetErrorAtShapeshiftedCast(m_spellInfo, m_caster->m_form)) - return shapeError; + bool checkForm = true; + // Ignore form req aura + Unit::AuraList const& ignore = m_caster->GetAurasByType(SPELL_AURA_MOD_IGNORE_SHAPESHIFT); + for(Unit::AuraList::const_iterator i = ignore.begin(); i != ignore.end(); ++i) + { + if (!(*i)->isAffectedOnSpell(m_spellInfo)) + continue; + checkForm = false; + break; + } + if (checkForm) + { + // Cannot be used in this stance/form + if(uint8 shapeError = GetErrorAtShapeshiftedCast(m_spellInfo, m_caster->m_form)) + return shapeError; - if ((m_spellInfo->Attributes & SPELL_ATTR_ONLY_STEALTHED) && !(m_caster->HasStealthAura())) - return SPELL_FAILED_ONLY_STEALTHED; + if ((m_spellInfo->Attributes & SPELL_ATTR_ONLY_STEALTHED) && !(m_caster->HasStealthAura())) + return SPELL_FAILED_ONLY_STEALTHED; + } } // caster state requirements @@ -3708,7 +3930,7 @@ uint8 Spell::CanCast(bool strict) case SPELL_EFFECT_SCHOOL_DAMAGE: { // Hammer of Wrath - if(m_spellInfo->SpellVisual == 7250) + if(m_spellInfo->SpellVisual[0] == 7250) { if (!m_targets.getUnitTarget()) return SPELL_FAILED_BAD_IMPLICIT_TARGETS; @@ -3753,15 +3975,9 @@ uint8 Spell::CanCast(bool strict) if(!learn_spellproto) return SPELL_FAILED_NOT_KNOWN; - if(!pet->CanTakeMoreActiveSpells(learn_spellproto->Id)) - return SPELL_FAILED_TOO_MANY_SKILLS; - if(m_spellInfo->spellLevel > pet->getLevel()) return SPELL_FAILED_LOWLEVEL; - if(!pet->HasTPForSpell(learn_spellproto->Id)) - return SPELL_FAILED_TRAINING_POINTS; - break; } case SPELL_EFFECT_LEARN_PET_SPELL: @@ -3776,15 +3992,9 @@ uint8 Spell::CanCast(bool strict) if(!learn_spellproto) return SPELL_FAILED_NOT_KNOWN; - if(!pet->CanTakeMoreActiveSpells(learn_spellproto->Id)) - return SPELL_FAILED_TOO_MANY_SKILLS; - if(m_spellInfo->spellLevel > pet->getLevel()) return SPELL_FAILED_LOWLEVEL; - if(!pet->HasTPForSpell(learn_spellproto->Id)) - return SPELL_FAILED_TRAINING_POINTS; - break; } case SPELL_EFFECT_FEED_PET: @@ -3887,27 +4097,27 @@ uint8 Spell::CanCast(bool strict) { // check for lock - key pair (checked by client also, just prevent cheating bool ok_key = false; - for(int it = 0; it < 5; ++it) + for(int it = 0; it < 8; ++it) { - switch(lockInfo->keytype[it]) + switch(lockInfo->Type[it]) { case LOCK_KEY_NONE: break; case LOCK_KEY_ITEM: { - if(lockInfo->key[it]) + if(lockInfo->Index[it]) { - if(m_CastItem && m_CastItem->GetEntry()==lockInfo->key[it]) + if(m_CastItem && m_CastItem->GetEntry()==lockInfo->Index[it]) ok_key =true; break; } } case LOCK_KEY_SKILL: { - if(uint32(m_spellInfo->EffectMiscValue[i])!=lockInfo->key[it]) + if(uint32(m_spellInfo->EffectMiscValue[i])!=lockInfo->Index[it]) break; - switch(lockInfo->key[it]) + switch(lockInfo->Index[it]) { case LOCKTYPE_HERBALISM: if(((Player*)m_caster)->HasSkill(SKILL_HERBALISM)) @@ -3964,9 +4174,9 @@ uint8 Spell::CanCast(bool strict) { // check for lock - key pair bool ok = false; - for(int it = 0; it < 5; ++it) + for(int it = 0; it < 8; ++it) { - if(lockInfo->keytype[it]==LOCK_KEY_ITEM && lockInfo->key[it] && m_CastItem && m_CastItem->GetEntry()==lockInfo->key[it]) + if(lockInfo->Type[it]==LOCK_KEY_ITEM && lockInfo->Index[it] && m_CastItem && m_CastItem->GetEntry()==lockInfo->Index[it]) { // if so, we're good to go ok = true; @@ -3977,9 +4187,9 @@ uint8 Spell::CanCast(bool strict) break; if (m_spellInfo->EffectMiscValue[i] == LOCKTYPE_PICKLOCK) - ReqValue = lockInfo->requiredlockskill; + ReqValue = lockInfo->Skill[1]; else - ReqValue = lockInfo->requiredminingskill; + ReqValue = lockInfo->Skill[0]; } // skill doesn't meet the required value @@ -4027,7 +4237,6 @@ uint8 Spell::CanCast(bool strict) } // Don't make this check for SPELL_EFFECT_SUMMON_CRITTER, SPELL_EFFECT_SUMMON_WILD or SPELL_EFFECT_SUMMON_GUARDIAN. // These won't show up in m_caster->GetPetGUID() - case SPELL_EFFECT_SUMMON_POSSESSED: case SPELL_EFFECT_SUMMON_PHANTASM: case SPELL_EFFECT_SUMMON_DEMON: { @@ -4163,7 +4372,7 @@ uint8 Spell::CanCast(bool strict) if( form == FORM_CAT || form == FORM_TREE || form == FORM_TRAVEL || form == FORM_AQUA || form == FORM_BEAR || form == FORM_DIREBEAR || form == FORM_CREATUREBEAR || form == FORM_GHOSTWOLF || form == FORM_FLIGHT || - form == FORM_FLIGHT_EPIC || form == FORM_MOONKIN ) + form == FORM_FLIGHT_EPIC || form == FORM_MOONKIN || form == FORM_METAMORPHOSIS ) return SPELL_FAILED_NOT_SHAPESHIFT; break; @@ -4185,8 +4394,8 @@ uint8 Spell::CanCast(bool strict) // not allow cast fly spells at old maps by players (all spells is self target) if(m_caster->GetTypeId()==TYPEID_PLAYER) { - if( !((Player*)m_caster)->isGameMaster() && - GetVirtualMapForMapAndZone(m_caster->GetMapId(),m_caster->GetZoneId()) != 530) + uint32 v_map = GetVirtualMapForMapAndZone(m_caster->GetMapId(), m_caster->GetZoneId()); + if( !((Player*)m_caster)->isGameMaster() && v_map != 530 && !(v_map == 571 && ((Player*)m_caster)->HasSpell(54197))) return SPELL_FAILED_NOT_HERE; } @@ -4504,9 +4713,12 @@ int32 Spell::CalculatePowerCost() case POWER_FOCUS: case POWER_ENERGY: case POWER_HAPPINESS: - // case POWER_RUNES: powerCost += m_spellInfo->ManaCostPercentage * m_caster->GetMaxPower(Powers(m_spellInfo->powerType)) / 100; break; + case POWER_RUNE: + case POWER_RUNIC_POWER: + sLog.outDebug("Spell::CalculateManaCost: Not implemented yet!"); + break; default: sLog.outError("Spell::CalculateManaCost: Unknown power type '%d' in spell %d", m_spellInfo->powerType, m_spellInfo->Id); return 0; @@ -4551,6 +4763,11 @@ uint8 Spell::CheckPower() sLog.outError("Spell::CheckMana: Unknown power type '%d'", m_spellInfo->powerType); return SPELL_FAILED_UNKNOWN; } + + uint8 failReason = CheckRuneCost(m_spellInfo->runeCostID); + if(failReason) + return failReason; + // Check power amount Powers powerType = Powers(m_spellInfo->powerType); if(m_caster->GetPower(powerType) < m_powerCost) @@ -4590,6 +4807,8 @@ uint8 Spell::CheckItems() uint32 ItemClass = proto->Class; if (ItemClass == ITEM_CLASS_CONSUMABLE && m_targets.getUnitTarget()) { + // such items should only fail if there is no suitable effect at all - see Rejuvenation Potions for example + uint8 failReason = 0; for (int i = 0; i < 3; i++) { // skip check, pet not required like checks, and for TARGET_PET m_targets.getUnitTarget() is not the real target but the caster @@ -4597,21 +4816,43 @@ uint8 Spell::CheckItems() continue; if (m_spellInfo->Effect[i] == SPELL_EFFECT_HEAL) + { if (m_targets.getUnitTarget()->GetHealth() == m_targets.getUnitTarget()->GetMaxHealth()) - return (uint8)SPELL_FAILED_ALREADY_AT_FULL_HEALTH; + { + failReason = (uint8)SPELL_FAILED_ALREADY_AT_FULL_HEALTH; + continue; + } + else + { + failReason = 0; + break; + } + } // Mana Potion, Rage Potion, Thistle Tea(Rogue), ... if (m_spellInfo->Effect[i] == SPELL_EFFECT_ENERGIZE) { if(m_spellInfo->EffectMiscValue[i] < 0 || m_spellInfo->EffectMiscValue[i] >= MAX_POWERS) - return (uint8)SPELL_FAILED_ALREADY_AT_FULL_POWER; + { + failReason = (uint8)SPELL_FAILED_ALREADY_AT_FULL_POWER; + continue; + } Powers power = Powers(m_spellInfo->EffectMiscValue[i]); - if (m_targets.getUnitTarget()->GetPower(power) == m_targets.getUnitTarget()->GetMaxPower(power)) - return (uint8)SPELL_FAILED_ALREADY_AT_FULL_POWER; + { + failReason = (uint8)SPELL_FAILED_ALREADY_AT_FULL_POWER; + continue; + } + else + { + failReason = 0; + break; + } } } + if (failReason) + return failReason; } } } @@ -4654,8 +4895,7 @@ uint8 Spell::CheckItems() focusObject = ok; // game object found in range } - if (!(m_spellInfo->AttributesEx5 & SPELL_ATTR_EX5_NO_REAGENT_WHILE_PREP && - m_caster->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PREPARATION))) + if (!p_caster->CanNoReagentCast(m_spellInfo)) { for(uint32 i=0;i<8;i++) { @@ -4823,13 +5063,36 @@ uint8 Spell::CheckItems() return SPELL_FAILED_LOW_CASTLEVEL; //make sure the player has the required ores in inventory if(m_targets.getItemTarget()->GetCount() < 5) - return SPELL_FAILED_PROSPECT_NEED_MORE; + return SPELL_FAILED_NEED_MORE_ITEMS; if(!LootTemplates_Prospecting.HaveLootFor(m_targets.getItemTargetEntry())) return SPELL_FAILED_CANT_BE_PROSPECTED; break; } + case SPELL_EFFECT_MILLING: + { + if(!m_targets.getItemTarget()) + return SPELL_FAILED_CANT_BE_MILLED; + //ensure item is a millable herb + if(!(m_targets.getItemTarget()->GetProto()->BagFamily & BAG_FAMILY_MASK_HERBS) || m_targets.getItemTarget()->GetProto()->Class != ITEM_CLASS_TRADE_GOODS) + return SPELL_FAILED_CANT_BE_MILLED; + //prevent milling in trade slot + if( m_targets.getItemTarget()->GetOwnerGUID() != m_caster->GetGUID() ) + return SPELL_FAILED_CANT_BE_MILLED; + //Check for enough skill in inscription + uint32 item_millingskilllevel = m_targets.getItemTarget()->GetProto()->RequiredSkillRank; + if(item_millingskilllevel >p_caster->GetSkillValue(SKILL_INSCRIPTION)) + return SPELL_FAILED_LOW_CASTLEVEL; + //make sure the player has the required herbs in inventory + if(m_targets.getItemTarget()->GetCount() < 5) + return SPELL_FAILED_NEED_MORE_ITEMS; + + if(!LootTemplates_Milling.HaveLootFor(m_targets.getItemTargetEntry())) + return SPELL_FAILED_CANT_BE_MILLED; + + break; + } case SPELL_EFFECT_WEAPON_DAMAGE: case SPELL_EFFECT_WEAPON_DAMAGE_NOSCHOOL: { @@ -5002,9 +5265,9 @@ void Spell::UpdatePointers() m_targets.Update(m_caster); } -bool Spell::IsAffectedBy(SpellEntry const *spellInfo, uint32 effectId) +bool Spell::IsAffectedByAura(Aura *aura) { - return spellmgr.IsAffectedBySpell(m_spellInfo,spellInfo->Id,effectId,spellInfo->EffectItemType[effectId]); + return spellmgr.IsAffectedByMod(m_spellInfo, aura->getAuraSpellMod()); } bool Spell::CheckTargetCreatureType(Unit* target) const diff --git a/src/game/Spell.h b/src/game/Spell.h index beea49c6d..2d2367028 100644 --- a/src/game/Spell.h +++ b/src/game/Spell.h @@ -45,32 +45,51 @@ enum SpellCastTargetFlags TARGET_FLAG_RESURRECTABLE = 0x8000*/ TARGET_FLAG_SELF = 0x00000000, + TARGET_FLAG_UNUSED1 = 0x00000001, // not used in any spells as of 3.0.3 (can be set dynamically) TARGET_FLAG_UNIT = 0x00000002, // pguid + TARGET_FLAG_UNUSED2 = 0x00000004, // not used in any spells as of 3.0.3 (can be set dynamically) + TARGET_FLAG_UNUSED3 = 0x00000008, // not used in any spells as of 3.0.3 (can be set dynamically) TARGET_FLAG_ITEM = 0x00000010, // pguid TARGET_FLAG_SOURCE_LOCATION = 0x00000020, // 3 float TARGET_FLAG_DEST_LOCATION = 0x00000040, // 3 float - TARGET_FLAG_OBJECT_UNK = 0x00000080, // ? + TARGET_FLAG_OBJECT_UNK = 0x00000080, // used in 7 spells only + TARGET_FLAG_UNIT_UNK = 0x00000100, // looks like self target (480 spells) TARGET_FLAG_PVP_CORPSE = 0x00000200, // pguid - TARGET_FLAG_OBJECT = 0x00000800, // pguid - TARGET_FLAG_TRADE_ITEM = 0x00001000, // pguid - TARGET_FLAG_STRING = 0x00002000, // string - TARGET_FLAG_UNK1 = 0x00004000, // ? - TARGET_FLAG_CORPSE = 0x00008000, // pguid - TARGET_FLAG_UNK2 = 0x00010000 // pguid + TARGET_FLAG_UNIT_CORPSE = 0x00000400, // 10 spells (gathering professions) + TARGET_FLAG_OBJECT = 0x00000800, // pguid, 2 spells + TARGET_FLAG_TRADE_ITEM = 0x00001000, // pguid, 0 spells + TARGET_FLAG_STRING = 0x00002000, // string, 0 spells + TARGET_FLAG_UNK1 = 0x00004000, // 199 spells, opening object/lock + TARGET_FLAG_CORPSE = 0x00008000, // pguid, resurrection spells + TARGET_FLAG_UNK2 = 0x00010000, // pguid, not used in any spells as of 3.0.3 (can be set dynamically) + TARGET_FLAG_GLYPH = 0x00020000 // used in glyph spells }; enum SpellCastFlags { + CAST_FLAG_NONE = 0x00000000, + CAST_FLAG_UNKNOWN0 = 0x00000001, // may be pending spell cast CAST_FLAG_UNKNOWN1 = 0x00000002, + CAST_FLAG_UNKNOWN11 = 0x00000004, + CAST_FLAG_UNKNOWN12 = 0x00000008, CAST_FLAG_UNKNOWN2 = 0x00000010, - CAST_FLAG_AMMO = 0x00000020, + CAST_FLAG_AMMO = 0x00000020, // Projectiles visual CAST_FLAG_UNKNOWN8 = 0x00000040, CAST_FLAG_UNKNOWN9 = 0x00000080, CAST_FLAG_UNKNOWN3 = 0x00000100, - CAST_FLAG_UNKNOWN6 = 0x00000800, // wotlk + CAST_FLAG_UNKNOWN13 = 0x00000200, + CAST_FLAG_UNKNOWN14 = 0x00000400, + CAST_FLAG_UNKNOWN6 = 0x00000800, // wotlk, trigger rune cooldown + CAST_FLAG_UNKNOWN15 = 0x00001000, + CAST_FLAG_UNKNOWN16 = 0x00002000, + CAST_FLAG_UNKNOWN17 = 0x00004000, + CAST_FLAG_UNKNOWN18 = 0x00008000, + CAST_FLAG_UNKNOWN19 = 0x00010000, CAST_FLAG_UNKNOWN4 = 0x00020000, // wotlk + CAST_FLAG_UNKNOWN10 = 0x00040000, CAST_FLAG_UNKNOWN5 = 0x00080000, // wotlk - CAST_FLAG_UNKNOWN7 = 0x00200000 // wotlk + CAST_FLAG_UNKNOWN20 = 0x00100000, + CAST_FLAG_UNKNOWN7 = 0x00200000 // wotlk, rune cooldown list }; enum SpellNotifyPushType @@ -252,6 +271,7 @@ class Spell void EffectStuck(uint32 i); void EffectSummonPlayer(uint32 i); void EffectActivateObject(uint32 i); + void EffectApplyGlyph(uint32 i); void EffectSummonTotem(uint32 i); void EffectEnchantHeldItem(uint32 i); void EffectSummonObject(uint32 i); @@ -269,6 +289,7 @@ class Spell void EffectSkinning(uint32 i); void EffectCharge(uint32 i); void EffectProspecting(uint32 i); + void EffectMilling(uint32 i); void EffectSendTaxi(uint32 i); void EffectSummonCritter(uint32 i); void EffectKnockBack(uint32 i); @@ -294,6 +315,8 @@ class Spell void EffectTriggerRitualOfSummoning(uint32 i); void EffectKillCredit(uint32 i); void EffectQuestFail(uint32 i); + void EffectActivateRune(uint32 i); + void EffectTitanGrip(uint32 i); Spell( Unit* Caster, SpellEntry const *info, bool triggered, uint64 originalCasterGUID = 0, Spell** triggeringContainer = NULL ); ~Spell(); @@ -304,6 +327,8 @@ class Spell void cast(bool skipCheck = false); void finish(bool ok = true); void TakePower(); + uint8 CheckRuneCost(uint32 runeCostID); + void TakeRunePower(); void TakeReagents(); void TakeCastItem(); void TriggerSpell(); @@ -362,6 +387,7 @@ class Spell int32 m_currentBasePoints[3]; // cache SpellEntry::EffectBasePoints and use for set custom base points Item* m_CastItem; uint8 m_cast_count; + uint32 m_glyphIndex; SpellCastTargets m_targets; int32 GetCastTime() const { return m_casttime; } @@ -397,7 +423,7 @@ class Spell void UpdatePointers(); // must be used at call Spell code after time delay (non triggered spell cast/update spell call/etc) - bool IsAffectedBy(SpellEntry const *spellInfo, uint32 effectId); + bool IsAffectedByAura(Aura *aura); bool CheckTargetCreatureType(Unit* target) const; @@ -424,6 +450,7 @@ class Spell int32 m_casttime; // Calculated spell cast time initialized only in Spell::prepare bool m_canReflect; // can reflect this spell? bool m_autoRepeat; + uint8 m_runesState; uint8 m_delayAtDamageCount; int32 GetNextDelayAtDamageMsTime() { return m_delayAtDamageCount < 5 ? 1000 - (m_delayAtDamageCount++)* 200 : 200; } diff --git a/src/game/SpellAuraDefines.h b/src/game/SpellAuraDefines.h index 7b6f72b5c..342987d57 100644 --- a/src/game/SpellAuraDefines.h +++ b/src/game/SpellAuraDefines.h @@ -18,14 +18,19 @@ #ifndef MANGOS_SPELLAURADEFINES_H #define MANGOS_SPELLAURADEFINES_H -#define MAX_AURAS 56 -#define MAX_POSITIVE_AURAS 40 +#define MAX_AURAS 64 // client support up to 255, but it will cause problems with group auras updating enum AURA_FLAGS { - AFLAG_NEGATIVE = 0x09, - AFLAG_POSITIVE = 0x1F, - AFLAG_MASK = 0xFF + AFLAG_NONE = 0x00, + AFLAG_EFF_INDEX_0 = 0x01, + AFLAG_EFF_INDEX_1 = 0x02, + AFLAG_EFF_INDEX_2 = 0x04, + AFLAG_NOT_CASTER = 0x08, + AFLAG_POSITIVE = 0x10, + AFLAG_DURATION = 0x20, + AFLAG_UNK2 = 0x40, + AFLAG_NEGATIVE = 0x80 }; //m_schoolAbsorb @@ -231,7 +236,7 @@ enum AuraType SPELL_AURA_USE_NORMAL_MOVEMENT_SPEED = 191, SPELL_AURA_HASTE_MELEE = 192, SPELL_AURA_MELEE_SLOW = 193, - SPELL_AURA_MOD_DEPRICATED_1 = 194, // not used now, old SPELL_AURA_MOD_SPELL_DAMAGE_OF_INTELLECT + SPELL_AURA_MOD_IGNORE_ABSORB_SCHOOL = 194, SPELL_AURA_MOD_DEPRICATED_2 = 195, // not used now, old SPELL_AURA_MOD_SPELL_HEALING_OF_INTELLECT SPELL_AURA_MOD_COOLDOWN = 196, // only 24818 Noxious Breath SPELL_AURA_MOD_ATTACKER_SPELL_AND_WEAPON_CRIT_CHANCE = 197, @@ -273,7 +278,7 @@ enum AuraType SPELL_AURA_233 = 233, SPELL_AURA_MECHANIC_DURATION_MOD_NOT_STACK = 234, SPELL_AURA_MOD_DISPEL_RESIST = 235, - SPELL_AURA_236 = 236, + SPELL_AURA_CONTROL_VEHICLE = 236, SPELL_AURA_MOD_SPELL_DAMAGE_OF_ATTACK_POWER = 237, SPELL_AURA_MOD_SPELL_HEALING_OF_ATTACK_POWER = 238, SPELL_AURA_MOD_SCALE_2 = 239, @@ -283,28 +288,51 @@ enum AuraType SPELL_AURA_243 = 243, SPELL_AURA_COMPREHEND_LANGUAGE = 244, SPELL_AURA_MOD_DURATION_OF_MAGIC_EFFECTS = 245, - SPELL_AURA_246 = 246, + SPELL_AURA_MOD_DURATION_OF_EFFECTS_BY_DISPEL = 246, SPELL_AURA_247 = 247, SPELL_AURA_MOD_COMBAT_RESULT_CHANCE = 248, - SPELL_AURA_249 = 249, + SPELL_AURA_CONVERT_RUNE = 249, SPELL_AURA_MOD_INCREASE_HEALTH_2 = 250, SPELL_AURA_MOD_ENEMY_DODGE = 251, SPELL_AURA_252 = 252, - SPELL_AURA_253 = 253, - SPELL_AURA_254 = 254, - SPELL_AURA_255 = 255, - SPELL_AURA_256 = 256, - SPELL_AURA_257 = 257, + SPELL_AURA_MOD_BLOCK_CRIT_CHANCE = 253, + SPELL_AURA_MOD_DISARM_SHIELD = 254, + SPELL_AURA_MOD_MECHANIC_DAMAGE_TAKEN_PERCENT = 255, + SPELL_AURA_NO_REAGENT_USE = 256, + SPELL_AURA_MOD_TARGET_RESIST_BY_SPELL_CLASS = 257, SPELL_AURA_258 = 258, SPELL_AURA_259 = 259, SPELL_AURA_260 = 260, SPELL_AURA_261 = 261, - TOTAL_AURAS=262 + SPELL_AURA_262 = 262, + SPELL_AURA_ALLOW_ONLY_ABILITY = 263, + SPELL_AURA_264 = 264, + SPELL_AURA_265 = 265, + SPELL_AURA_266 = 266, + SPELL_AURA_267 = 267, + SPELL_AURA_MOD_ATTACK_POWER_OF_STAT_PERCENT = 268, + SPELL_AURA_269 = 269, + SPELL_AURA_270 = 270, + SPELL_AURA_271 = 271, + SPELL_AURA_272 = 272, + SPELL_AURA_273 = 273, + SPELL_AURA_274 = 274, + SPELL_AURA_MOD_IGNORE_SHAPESHIFT = 275, + SPELL_AURA_276 = 276, // Only "Test Mod Damage % Mechanic" spell, possible mod damage done + SPELL_AURA_MOD_MAX_AFFECTED_TARGETS = 277, + SPELL_AURA_MOD_DISARM_RANGED = 278, + SPELL_AURA_279 = 279, + SPELL_AURA_MOD_TARGET_ARMOR_PCT = 280, + SPELL_AURA_MOD_HONOR_GAIN = 281, + SPELL_AURA_MOD_BASE_HEALTH_PCT = 282, + SPELL_AURA_MOD_HEALING_RECEIVED = 283, // Possibly only for some spell family class spells + TOTAL_AURAS = 284 }; enum AreaAuraType { AREA_AURA_PARTY, + AREA_AURA_RAID, AREA_AURA_FRIEND, AREA_AURA_ENEMY, AREA_AURA_PET, diff --git a/src/game/SpellAuras.cpp b/src/game/SpellAuras.cpp index d1cf86568..f995d6c7f 100644 --- a/src/game/SpellAuras.cpp +++ b/src/game/SpellAuras.cpp @@ -159,7 +159,7 @@ pAuraHandler AuraHandler[TOTAL_AURAS]= &Aura::HandleAuraHover, //106 SPELL_AURA_HOVER &Aura::HandleAddModifier, //107 SPELL_AURA_ADD_FLAT_MODIFIER &Aura::HandleAddModifier, //108 SPELL_AURA_ADD_PCT_MODIFIER - &Aura::HandleNoImmediateEffect, //109 SPELL_AURA_ADD_TARGET_TRIGGER + &Aura::HandleAddTargetTrigger, //109 SPELL_AURA_ADD_TARGET_TRIGGER &Aura::HandleModPowerRegenPCT, //110 SPELL_AURA_MOD_POWER_REGEN_PERCENT &Aura::HandleNULL, //111 SPELL_AURA_ADD_CASTER_HIT_TRIGGER &Aura::HandleNoImmediateEffect, //112 SPELL_AURA_OVERRIDE_CLASS_SCRIPTS @@ -224,7 +224,7 @@ pAuraHandler AuraHandler[TOTAL_AURAS]= &Aura::HandleAuraModIncreaseSpeed, //171 SPELL_AURA_MOD_SPEED_NOT_STACK &Aura::HandleAuraModIncreaseMountedSpeed, //172 SPELL_AURA_MOD_MOUNTED_SPEED_NOT_STACK &Aura::HandleUnused, //173 SPELL_AURA_ALLOW_CHAMPION_SPELLS only for Proclaim Champion spell - &Aura::HandleModSpellDamagePercentFromStat, //174 SPELL_AURA_MOD_SPELL_DAMAGE_OF_STAT_PERCENT implemented in Unit::SpellBaseDamageBonus (by default intellect, dependent from SPELL_AURA_MOD_SPELL_HEALING_OF_STAT_PERCENT) + &Aura::HandleModSpellDamagePercentFromStat, //174 SPELL_AURA_MOD_SPELL_DAMAGE_OF_STAT_PERCENT implemented in Unit::SpellBaseDamageBonus &Aura::HandleModSpellHealingPercentFromStat, //175 SPELL_AURA_MOD_SPELL_HEALING_OF_STAT_PERCENT implemented in Unit::SpellBaseHealingBonus &Aura::HandleSpiritOfRedemption, //176 SPELL_AURA_SPIRIT_OF_REDEMPTION only for Spirit of Redemption spell, die at aura end &Aura::HandleNULL, //177 SPELL_AURA_AOE_CHARM @@ -244,7 +244,7 @@ pAuraHandler AuraHandler[TOTAL_AURAS]= &Aura::HandleAuraModUseNormalSpeed, //191 SPELL_AURA_USE_NORMAL_MOVEMENT_SPEED &Aura::HandleModMeleeRangedSpeedPct, //192 SPELL_AURA_HASTE_MELEE &Aura::HandleModCombatSpeedPct, //193 SPELL_AURA_MELEE_SLOW (in fact combat (any type attack) speed pct) - &Aura::HandleUnused, //194 SPELL_AURA_MOD_DEPRICATED_1 not used now (old SPELL_AURA_MOD_SPELL_DAMAGE_OF_INTELLECT) + &Aura::HandleUnused, //194 SPELL_AURA_MOD_IGNORE_ABSORB_SCHOOL &Aura::HandleUnused, //195 SPELL_AURA_MOD_DEPRICATED_2 not used now (old SPELL_AURA_MOD_SPELL_HEALING_OF_INTELLECT) &Aura::HandleNULL, //196 SPELL_AURA_MOD_COOLDOWN &Aura::HandleNoImmediateEffect, //197 SPELL_AURA_MOD_ATTACKER_SPELL_AND_WEAPON_CRIT_CHANCE implemented in Unit::SpellCriticalBonus Unit::GetUnitCriticalChance @@ -270,7 +270,7 @@ pAuraHandler AuraHandler[TOTAL_AURAS]= &Aura::HandleUnused, //217 unused &Aura::HandleAuraModRangedHaste, //218 SPELL_AURA_HASTE_RANGED &Aura::HandleModManaRegen, //219 SPELL_AURA_MOD_MANA_REGEN_FROM_STAT - &Aura::HandleNULL, //220 SPELL_AURA_MOD_RATING_FROM_STAT + &Aura::HandleModRatingFromStat, //220 SPELL_AURA_MOD_RATING_FROM_STAT &Aura::HandleNULL, //221 ignored &Aura::HandleUnused, //222 unused &Aura::HandleNULL, //223 Cold Stare @@ -286,7 +286,7 @@ pAuraHandler AuraHandler[TOTAL_AURAS]= &Aura::HandleNULL, //233 set model id to the one of the creature with id m_modifier.m_miscvalue &Aura::HandleNoImmediateEffect, //234 SPELL_AURA_MECHANIC_DURATION_MOD_NOT_STACK implement in Unit::CalculateSpellDuration &Aura::HandleAuraModDispelResist, //235 SPELL_AURA_MOD_DISPEL_RESIST implement in Unit::MagicSpellHitResult - &Aura::HandleUnused, //236 unused + &Aura::HandleAuraControlVehicle, //236 SPELL_AURA_CONTROL_VEHICLE &Aura::HandleModSpellDamagePercentFromAttackPower, //237 SPELL_AURA_MOD_SPELL_DAMAGE_OF_ATTACK_POWER implemented in Unit::SpellBaseDamageBonus &Aura::HandleModSpellHealingPercentFromAttackPower, //238 SPELL_AURA_MOD_SPELL_HEALING_OF_ATTACK_POWER implemented in Unit::SpellBaseHealingBonus &Aura::HandleAuraModScale, //239 SPELL_AURA_MOD_SCALE_2 only in Noggenfogger Elixir (16595) before 2.3.0 aura 61 @@ -296,22 +296,44 @@ pAuraHandler AuraHandler[TOTAL_AURAS]= &Aura::HandleUnused, //243 used by two test spells &Aura::HandleComprehendLanguage, //244 Comprehend language &Aura::HandleUnused, //245 SPELL_AURA_MOD_DURATION_OF_MAGIC_EFFECTS - &Aura::HandleUnused, //246 unused + &Aura::HandleNoImmediateEffect, //246 SPELL_AURA_MOD_DURATION_OF_EFFECTS_BY_DISPEL &Aura::HandleUnused, //247 unused &Aura::HandleNoImmediateEffect, //248 SPELL_AURA_MOD_COMBAT_RESULT_CHANCE implemented in Unit::RollMeleeOutcomeAgainst - &Aura::HandleNULL, //249 + &Aura::HandleAuraConvertRune, //249 SPELL_AURA_CONVERT_RUNE &Aura::HandleAuraModIncreaseHealth, //250 SPELL_AURA_MOD_INCREASE_HEALTH_2 &Aura::HandleNULL, //251 SPELL_AURA_MOD_ENEMY_DODGE - &Aura::HandleUnused, //252 unused - &Aura::HandleUnused, //253 unused - &Aura::HandleUnused, //254 unused - &Aura::HandleUnused, //255 unused - &Aura::HandleUnused, //256 unused - &Aura::HandleUnused, //257 unused - &Aura::HandleUnused, //258 unused - &Aura::HandleUnused, //259 unused - &Aura::HandleUnused, //260 unused - &Aura::HandleNULL //261 SPELL_AURA_261 some phased state (44856 spell) + &Aura::HandleNULL, //252 haste all? + &Aura::HandleNULL, //253 SPELL_AURA_MOD_BLOCK_CRIT_CHANCE + &Aura::HandleNULL, //254 SPELL_AURA_MOD_DISARM_SHIELD disarm Shield + &Aura::HandleNULL, //255 SPELL_AURA_MOD_MECHANIC_DAMAGE_TAKEN_PERCENT + &Aura::HandleNoReagentUseAura, //256 SPELL_AURA_NO_REAGENT_USE Use SpellClassMask for spell select + &Aura::HandleNULL, //257 SPELL_AURA_MOD_TARGET_RESIST_BY_SPELL_CLASS Use SpellClassMask for spell select + &Aura::HandleNULL, //258 SPELL_AURA_MOD_SPELL_VISUAL + &Aura::HandleNULL, //259 corrupt healing over time spell + &Aura::HandleNULL, //260 + &Aura::HandleNULL, //261 out of phase? + &Aura::HandleNULL, //262 + &Aura::HandleNULL, //263 SPELL_AURA_ALLOW_ONLY_ABILITY player can use only abilites set in SpellClassMask + &Aura::HandleNULL, //264 unused + &Aura::HandleNULL, //265 unused + &Aura::HandleNULL, //266 unused + &Aura::HandleNULL, //267 some immunity? + &Aura::HandleAuraModAttackPowerOfStatPercent, //268 SPELL_AURA_MOD_ATTACK_POWER_OF_STAT_PERCENT + &Aura::HandleNULL, //269 ignore DR effects? + &Aura::HandleNULL, //270 + &Aura::HandleNULL, //271 increase damage done? + &Aura::HandleNULL, //272 reduce spell cast time? + &Aura::HandleNULL, //273 + &Aura::HandleNULL, //274 proc free shot? + &Aura::HandleNoImmediateEffect, //275 SPELL_AURA_MOD_IGNORE_SHAPESHIFT Use SpellClassMask for spell select + &Aura::HandleNULL, //276 mod damage % mechanic? + &Aura::HandleNoImmediateEffect, //277 SPELL_AURA_MOD_MAX_AFFECTED_TARGETS Use SpellClassMask for spell select + &Aura::HandleNULL, //278 SPELL_AURA_MOD_DISARM_RANGED disarm ranged weapon + &Aura::HandleNULL, //279 + &Aura::HandleNULL, //280 SPELL_AURA_MOD_TARGET_ARMOR_PCT + &Aura::HandleNULL, //281 SPELL_AURA_MOD_HONOR_GAIN + &Aura::HandleAuraIncreaseBaseHealthPercent, //282 SPELL_AURA_INCREASE_BASE_HEALTH_PERCENT + &Aura::HandleNULL //283 SPD/heal from AP? }; Aura::Aura(SpellEntry const* spellproto, uint32 eff, int32 *currentBasePoints, Unit *target, Unit *caster, Item* castItem) : @@ -430,6 +452,11 @@ Unit *caster, Item* castItem) : Aura(spellproto, eff, currentBasePoints, target, if(target->GetTypeId() == TYPEID_UNIT && ((Creature*)target)->isTotem()) m_modifier.m_auraname = SPELL_AURA_NONE; break; + case SPELL_EFFECT_APPLY_AREA_AURA_RAID: + m_areaAuraType = AREA_AURA_RAID; + if(target->GetTypeId() == TYPEID_UNIT && ((Creature*)target)->isTotem()) + m_modifier.m_auraname = SPELL_AURA_NONE; + break; case SPELL_EFFECT_APPLY_AREA_AURA_FRIEND: m_areaAuraType = AREA_AURA_FRIEND; break; @@ -659,6 +686,41 @@ void AreaAura::Update(uint32 diff) } break; } + case AREA_AURA_RAID: + { + Group *pGroup = NULL; + + if (owner->GetTypeId() == TYPEID_PLAYER) + pGroup = ((Player*)owner)->GetGroup(); + + if( pGroup) + { + uint8 subgroup = ((Player*)owner)->GetSubGroup(); + for(GroupReference *itr = pGroup->GetFirstMember(); itr != NULL; itr = itr->next()) + { + Player* Target = itr->getSource(); + if(Target && Target->isAlive() && caster->IsFriendlyTo(Target)) + { + if(caster->IsWithinDistInMap(Target, m_radius)) + targets.push_back(Target); + Pet *pet = Target->GetPet(); + if(pet && pet->isAlive() && caster->IsWithinDistInMap(pet, m_radius)) + targets.push_back(pet); + } + } + } + else + { + // add owner + if( owner != caster && caster->IsWithinDistInMap(owner, m_radius) ) + targets.push_back(owner); + // add caster's pet + Unit* pet = caster->GetPet(); + if( pet && caster->IsWithinDistInMap(pet, m_radius)) + targets.push_back(pet); + } + break; + } case AREA_AURA_FRIEND: { CellPair p(MaNGOS::ComputeCellPair(caster->GetPositionX(), caster->GetPositionY())); @@ -758,6 +820,24 @@ void AreaAura::Update(uint32 diff) tmp_target->RemoveAura(tmp_spellId, tmp_effIndex); } } + else if( m_areaAuraType == AREA_AURA_RAID) // TODO: fix me! + { + // not check group if target == owner or target == pet + if (caster->GetCharmerOrOwnerGUID() != tmp_target->GetGUID() && caster->GetGUID() != tmp_target->GetCharmerOrOwnerGUID()) + { + Player* check = caster->GetCharmerOrOwnerPlayerOrPlayerItself(); + + Group *pGroup = check ? check->GetGroup() : NULL; + if( pGroup ) + { + Player* checkTarget = tmp_target->GetCharmerOrOwnerPlayerOrPlayerItself(); + if(!checkTarget) + tmp_target->RemoveAura(tmp_spellId, tmp_effIndex); + } + else + tmp_target->RemoveAura(tmp_spellId, tmp_effIndex); + } + } else if( m_areaAuraType == AREA_AURA_PET || m_areaAuraType == AREA_AURA_OWNER ) { if( tmp_target->GetGUID() != caster->GetCharmerOrOwnerGUID() ) @@ -808,47 +888,6 @@ void Aura::ApplyModifier(bool apply, bool Real) m_in_use = false; } -void Aura::UpdateAuraDuration() -{ - if(m_auraSlot >= MAX_AURAS || m_isPassive) - return; - - if( m_target->GetTypeId() == TYPEID_PLAYER) - { - WorldPacket data(SMSG_UPDATE_AURA_DURATION, 5); - data << (uint8)m_auraSlot << (uint32)m_duration; - ((Player*)m_target)->SendDirectMessage(&data); - - data.Initialize(SMSG_SET_EXTRA_AURA_INFO, (8+1+4+4+4)); - data.append(m_target->GetPackGUID()); - data << uint8(m_auraSlot); - data << uint32(GetId()); - data << uint32(GetAuraMaxDuration()); - data << uint32(GetAuraDuration()); - ((Player*)m_target)->SendDirectMessage(&data); - } - - // not send in case player loading (will not work anyway until player not added to map), sent in visibility change code - if(m_target->GetTypeId() == TYPEID_PLAYER && ((Player*)m_target)->GetSession()->PlayerLoading()) - return; - - Unit* caster = GetCaster(); - - if(caster && caster->GetTypeId() == TYPEID_PLAYER && caster != m_target) - SendAuraDurationForCaster((Player*)caster); -} - -void Aura::SendAuraDurationForCaster(Player* caster) -{ - WorldPacket data(SMSG_SET_EXTRA_AURA_INFO_NEED_UPDATE, (8+1+4+4+4)); - data.append(m_target->GetPackGUID()); - data << uint8(m_auraSlot); - data << uint32(GetId()); - data << uint32(GetAuraMaxDuration()); // full - data << uint32(GetAuraDuration()); // remain - caster->GetSession()->SendPacket(&data); -} - void Aura::_AddAura() { if (!GetId()) @@ -908,22 +947,13 @@ void Aura::_AddAura() { if(!samespell) // new slot need { - if (IsPositive()) // empty positive slot + if(m_target->GetVisibleAurasCount() < MAX_AURAS) { - for (uint8 i = 0; i < MAX_POSITIVE_AURAS; i++) + Unit::VisibleAuraMap const *visibleAuras = m_target->GetVisibleAuras(); + for(uint8 i = 0; i < MAX_AURAS; ++i) { - if (m_target->GetUInt32Value((uint16)(UNIT_FIELD_AURA + i)) == 0) - { - slot = i; - break; - } - } - } - else // empty negative slot - { - for (uint8 i = MAX_POSITIVE_AURAS; i < MAX_AURAS; i++) - { - if (m_target->GetUInt32Value((uint16)(UNIT_FIELD_AURA + i)) == 0) + Unit::VisibleAuraMap::const_iterator itr = visibleAuras->find(i); + if(itr == visibleAuras->end()) { slot = i; break; @@ -938,16 +968,15 @@ void Aura::_AddAura() { if(slot < MAX_AURAS) // slot found { - SetAura(slot, false); - SetAuraFlag(slot, true); - SetAuraLevel(slot,caster ? caster->getLevel() : sWorld.getConfig(CONFIG_MAX_PLAYER_LEVEL)); + SetAura(false); + SetAuraFlags((1 << GetEffIndex()) | AFLAG_NOT_CASTER | ((GetAuraMaxDuration() > 0) ? AFLAG_DURATION : AFLAG_NONE) | (IsPositive() ? AFLAG_POSITIVE : AFLAG_NEGATIVE)); + SetAuraLevel(caster ? caster->getLevel() : sWorld.getConfig(CONFIG_MAX_PLAYER_LEVEL)); UpdateAuraCharges(); + SendAuraUpdate(false); // update for out of range group members m_target->UpdateAuraForGroup(slot); } - - UpdateAuraDuration(); } } else // use found slot @@ -1004,7 +1033,7 @@ void Aura::_RemoveAura() if(slot >= MAX_AURAS) // slot not set return; - if(m_target->GetUInt32Value((uint16)(UNIT_FIELD_AURA + slot)) == 0) + if(m_target->GetVisibleAura(slot) == 0) return; bool samespell = false; @@ -1033,11 +1062,12 @@ void Aura::_RemoveAura() // only remove icon when the last aura of the spell is removed (current aura already removed from list) if (!samespell) { - SetAura(slot, true); - SetAuraFlag(slot, false); - SetAuraLevel(slot,caster ? caster->getLevel() : sWorld.getConfig(CONFIG_MAX_PLAYER_LEVEL)); + SetAura(true); + SetAuraFlags(AFLAG_NONE); + SetAuraLevel(0); + SetAuraCharges(0); + SendAuraUpdate(true); - SetAuraApplication(slot, 0); // update for out of range group members m_target->UpdateAuraForGroup(slot); @@ -1078,40 +1108,36 @@ void Aura::_RemoveAura() UpdateSlotCounterAndDuration(false); } -void Aura::SetAuraFlag(uint32 slot, bool add) +void Aura::SendAuraUpdate(bool remove) { - uint32 index = slot / 4; - uint32 byte = (slot % 4) * 8; - uint32 val = m_target->GetUInt32Value(UNIT_FIELD_AURAFLAGS + index); - val &= ~((uint32)AFLAG_MASK << byte); - if(add) + WorldPacket data(SMSG_AURA_UPDATE); + data.append(m_target->GetPackGUID()); + data << uint8(GetAuraSlot()); + data << uint32(remove ? 0 : GetId()); + + if(remove) { - if (IsPositive()) - val |= ((uint32)AFLAG_POSITIVE << byte); - else - val |= ((uint32)AFLAG_NEGATIVE << byte); + m_target->SendMessageToSet(&data, true); + return; } - m_target->SetUInt32Value(UNIT_FIELD_AURAFLAGS + index, val); -} -void Aura::SetAuraLevel(uint32 slot,uint32 level) -{ - uint32 index = slot / 4; - uint32 byte = (slot % 4) * 8; - uint32 val = m_target->GetUInt32Value(UNIT_FIELD_AURALEVELS + index); - val &= ~(0xFF << byte); - val |= (level << byte); - m_target->SetUInt32Value(UNIT_FIELD_AURALEVELS + index, val); -} + uint8 auraFlags = GetAuraFlags(); + data << uint8(auraFlags); + data << uint8(GetAuraLevel()); + data << uint8(m_procCharges >= 0 ? m_procCharges : 0); -void Aura::SetAuraApplication(uint32 slot, int8 count) -{ - uint32 index = slot / 4; - uint32 byte = (slot % 4) * 8; - uint32 val = m_target->GetUInt32Value(UNIT_FIELD_AURAAPPLICATIONS + index); - val &= ~(0xFF << byte); - val |= ((uint8(count)) << byte); - m_target->SetUInt32Value(UNIT_FIELD_AURAAPPLICATIONS + index, val); + if(!(auraFlags & AFLAG_NOT_CASTER)) + { + data << uint8(0); // pguid + } + + if(auraFlags & AFLAG_DURATION) + { + data << uint32(GetAuraMaxDuration()); + data << uint32(GetAuraDuration()); + } + + m_target->SendMessageToSet(&data, true); } void Aura::UpdateSlotCounterAndDuration(bool add) @@ -1142,9 +1168,22 @@ void Aura::UpdateSlotCounterAndDuration(bool add) if(!add) --count; - SetAuraApplication(slot, count); + SetAuraCharges(count); + SendAuraUpdate(false); +} - UpdateAuraDuration(); +bool Aura::isAffectedOnSpell(SpellEntry const *spell) const +{ + // Check family name + if (spell->SpellFamilyName != m_spellProto->SpellFamilyName) + return false; + // Check EffectClassMask + uint32 const *ptr = getAuraSpellClassMask(); + if (((uint64*)ptr)[0] & spell->SpellFamilyFlags) + return true; + if (ptr[2] & spell->SpellFamilyFlags2) + return true; + return false; } /*********************************************************/ @@ -1155,10 +1194,6 @@ void Aura::HandleAddModifier(bool apply, bool Real) if(m_target->GetTypeId() != TYPEID_PLAYER || !Real) return; - SpellEntry const *spellInfo = GetSpellProto(); - if(!spellInfo) - return; - if(m_modifier.m_miscvalue >= MAX_SPELLMOD) return; @@ -1179,15 +1214,25 @@ void Aura::HandleAddModifier(bool apply, bool Real) mod->value = m_modifier.m_amount; mod->type = SpellModType(m_modifier.m_auraname); // SpellModType value == spell aura types mod->spellId = GetId(); - mod->effectId = m_effIndex; - mod->lastAffected = NULL; - uint64 spellAffectMask = spellmgr.GetSpellAffectMask(GetId(), m_effIndex); - - if (spellAffectMask) - mod->mask = spellAffectMask; + uint32 const *ptr; + SpellAffectEntry const *spellAffect = spellmgr.GetSpellAffect(GetId(), m_effIndex); + if (spellAffect) + ptr = &spellAffect->SpellClassMask[0]; else - mod->mask = spellInfo->EffectItemType[m_effIndex]; + { + switch (m_effIndex) + { + case 0: ptr = &m_spellProto->EffectSpellClassMaskA[0]; break; + case 1: ptr = &m_spellProto->EffectSpellClassMaskB[0]; break; + case 2: ptr = &m_spellProto->EffectSpellClassMaskC[0]; break; + default: + return; + } + } + + mod->mask = (uint64)ptr[0] | (uint64)ptr[1]<<32; + mod->mask2= (uint64)ptr[2]; if (m_procCharges > 0) mod->charges = m_procCharges; @@ -1202,7 +1247,7 @@ void Aura::HandleAddModifier(bool apply, bool Real) ((Player*)m_target)->AddSpellMod(m_spellmod, apply); // reapply some passive spells after add/remove related spellmods - if(spellInfo->SpellFamilyName==SPELLFAMILY_WARRIOR && (spellFamilyMask & 0x0000100000000000LL)) + if(m_spellProto->SpellFamilyName==SPELLFAMILY_WARRIOR && (spellFamilyMask & 0x0000100000000000LL)) { m_target->RemoveAurasDueToSpell(45471); @@ -1210,7 +1255,42 @@ void Aura::HandleAddModifier(bool apply, bool Real) m_target->CastSpell(m_target,45471,true); } } +void Aura::HandleAddTargetTrigger(bool apply, bool Real) +{ + // Use SpellModifier structure for check + // used only fields: + // spellId, mask, mask2 + if (apply) + { + SpellModifier *mod = new SpellModifier; + mod->spellId = GetId(); + uint32 const *ptr; + SpellAffectEntry const *spellAffect = spellmgr.GetSpellAffect(GetId(), m_effIndex); + if (spellAffect) + ptr = &spellAffect->SpellClassMask[0]; + else + { + switch (m_effIndex) + { + case 0: ptr = &m_spellProto->EffectSpellClassMaskA[0]; break; + case 1: ptr = &m_spellProto->EffectSpellClassMaskB[0]; break; + case 2: ptr = &m_spellProto->EffectSpellClassMaskC[0]; break; + default: + return; + } + } + + mod->mask = (uint64)ptr[0] | (uint64)ptr[1]<<32; + mod->mask2= (uint64)ptr[2]; + m_spellmod = mod; + } + else + { + delete m_spellmod; + m_spellmod = NULL; + } +} void Aura::TriggerSpell() { Unit* caster = GetCaster(); @@ -2147,7 +2227,8 @@ void Aura::HandleAuraDummy(bool apply, bool Real) return; // final heal - m_target->CastCustomSpell(m_target,33778,&m_modifier.m_amount,NULL,NULL,true,NULL,this,GetCasterGUID()); + if(m_target->IsInWorld()) + m_target->CastCustomSpell(m_target,33778,&m_modifier.m_amount,NULL,NULL,true,NULL,this,GetCasterGUID()); } return; } @@ -2168,10 +2249,8 @@ void Aura::HandleAuraDummy(bool apply, bool Real) mod->value = m_modifier.m_amount/7; mod->type = SPELLMOD_FLAT; mod->spellId = GetId(); - mod->effectId = m_effIndex; - mod->lastAffected = NULL; mod->mask = 0x001000000000LL; - mod->charges = 0; + mod->mask2= 0LL; m_spellmod = mod; } @@ -2194,10 +2273,8 @@ void Aura::HandleAuraDummy(bool apply, bool Real) mod->value = m_modifier.m_amount; mod->type = SPELLMOD_FLAT; mod->spellId = GetId(); - mod->effectId = m_effIndex; - mod->lastAffected = NULL; mod->mask = 0x4000000000000LL; - mod->charges = 0; + mod->mask2= 0LL; m_spellmod = mod; } @@ -2219,18 +2296,17 @@ void Aura::HandleAuraDummy(bool apply, bool Real) mod->value = m_modifier.m_amount; mod->type = SPELLMOD_PCT; mod->spellId = GetId(); - mod->effectId = m_effIndex; - mod->lastAffected = NULL; switch (m_effIndex) { case 0: mod->mask = 0x00200000000LL; // Windfury Totem + mod->mask2= 0LL; break; case 1: mod->mask = 0x00400000000LL; // Flametongue Totem + mod->mask2= 0LL; break; } - mod->charges = 0; m_spellmod = mod; } @@ -2259,6 +2335,8 @@ void Aura::HandleAuraPeriodicDummy(bool apply, bool Real) if(!Real) return; + Unit* caster = GetCaster(); + SpellEntry const*spell = GetSpellProto(); switch( spell->SpellFamilyName) { @@ -2282,6 +2360,16 @@ void Aura::HandleAuraPeriodicDummy(bool apply, bool Real) ((Player*)m_target)->UpdateManaRegen(); break; } + // Explosive Shot + if (spell->SpellFamilyFlags & 0x8000000000000000LL) + { + if (apply && caster) + { + int32 damage = m_modifier.m_amount + caster->GetTotalAttackPowerValue(RANGED_ATTACK) * 8 / 100; + caster->CastCustomSpell(m_target, 53352, &damage, 0, 0, true, 0, this); + } + break; + } break; } } @@ -2948,6 +3036,7 @@ void Aura::HandleModPossess(bool apply, bool Real) { WorldPacket data(SMSG_PET_SPELLS, 8); data << uint64(0); + data << uint32(0); ((Player*)caster)->GetSession()->SendPacket(&data); } if(m_target->GetTypeId() == TYPEID_UNIT) @@ -2970,18 +3059,31 @@ void Aura::HandleModPossessPet(bool apply, bool Real) Unit* caster = GetCaster(); if(!caster || caster->GetTypeId() != TYPEID_PLAYER) return; - if(caster->GetPet() != m_target) + + Pet *pet = caster->GetPet(); + if(!pet || pet != m_target) return; + if(apply) + pet->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_UNKNOWN5); + else + pet->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_UNKNOWN5); + + ((Player*)caster)->SetFarSight(apply ? pet->GetGUID() : NULL); + ((Player*)caster)->SetCharm(apply ? pet : NULL); + ((Player*)caster)->SetClientControl(pet, apply ? 1 : 0); + if(apply) { - caster->SetUInt64Value(PLAYER_FARSIGHT, m_target->GetGUID()); - m_target->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_UNKNOWN5); + pet->StopMoving(); + pet->GetMotionMaster()->Clear(); + pet->GetMotionMaster()->MoveIdle(); } else { - caster->SetUInt64Value(PLAYER_FARSIGHT, 0); - m_target->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_UNKNOWN5); + pet->AttackStop(); + pet->GetMotionMaster()->MoveFollow(caster, PET_FOLLOW_DIST, PET_FOLLOW_ANGLE); + pet->SetUnitMovementFlags(MOVEMENTFLAG_NONE); } } @@ -3080,6 +3182,7 @@ void Aura::HandleModCharm(bool apply, bool Real) { WorldPacket data(SMSG_PET_SPELLS, 8); data << uint64(0); + data << uint32(0); ((Player*)caster)->GetSession()->SendPacket(&data); } if(m_target->GetTypeId() == TYPEID_UNIT) @@ -3199,7 +3302,7 @@ void Aura::HandleAuraModStun(bool apply, bool Real) m_target->addUnitState(UNIT_STAT_STUNNED); m_target->SetUInt64Value(UNIT_FIELD_TARGET, 0); - m_target->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_ROTATE); + m_target->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_STUNNED); m_target->CastStop(m_target->GetGUID() == GetCasterGUID() ? GetId() : 0); // Creature specific @@ -3221,7 +3324,7 @@ void Aura::HandleAuraModStun(bool apply, bool Real) return; m_target->clearUnitState(UNIT_STAT_STUNNED); - m_target->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_ROTATE); + m_target->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_STUNNED); if(!m_target->hasUnitState(UNIT_STAT_ROOT)) // prevent allow move if have also root effect { @@ -4103,7 +4206,7 @@ void Aura::HandlePeriodicDamage(bool apply, bool Real) case SPELLFAMILY_ROGUE: { // Deadly poison aura state - if((m_spellProto->SpellFamilyFlags & 0x10000) && m_spellProto->SpellVisual==5100) + if((m_spellProto->SpellFamilyFlags & 0x10000) && m_spellProto->SpellVisual[0]==5100) { if(apply) m_target->ModifyAuraState(AURA_STATE_DEADLY_POISON,true); @@ -4115,7 +4218,7 @@ void Aura::HandlePeriodicDamage(bool apply, bool Real) for(Unit::AuraList::const_iterator itr = auras.begin(); itr != auras.end(); ++itr) { SpellEntry const* itr_spell = (*itr)->GetSpellProto(); - if(itr_spell && itr_spell->SpellFamilyName==SPELLFAMILY_ROGUE && (itr_spell->SpellFamilyFlags & 0x10000) && itr_spell->SpellVisual==5100) + if(itr_spell && itr_spell->SpellFamilyName==SPELLFAMILY_ROGUE && (itr_spell->SpellFamilyFlags & 0x10000) && itr_spell->SpellVisual[0]==5100) { found = true; break; @@ -4702,6 +4805,11 @@ void Aura::HandleAuraModIncreaseHealthPercent(bool apply, bool /*Real*/) m_target->HandleStatModifier(UNIT_MOD_HEALTH, TOTAL_PCT, float(m_modifier.m_amount), apply); } +void Aura::HandleAuraIncreaseBaseHealthPercent(bool apply, bool /*Real*/) +{ + m_target->HandleStatModifier(UNIT_MOD_HEALTH, BASE_PCT, float(m_modifier.m_amount), apply); +} + /********************************/ /*** FIGHT ***/ /********************************/ @@ -4775,13 +4883,28 @@ void Aura::HandleAuraModCritPercent(bool apply, bool Real) void Aura::HandleModHitChance(bool apply, bool Real) { - m_target->m_modMeleeHitChance += apply ? m_modifier.m_amount : (-m_modifier.m_amount); - m_target->m_modRangedHitChance += apply ? m_modifier.m_amount : (-m_modifier.m_amount); + if(m_target->GetTypeId() == TYPEID_PLAYER) + { + ((Player*)m_target)->UpdateMeleeHitChances(); + ((Player*)m_target)->UpdateRangedHitChances(); + } + else + { + m_target->m_modMeleeHitChance += apply ? m_modifier.m_amount : (-m_modifier.m_amount); + m_target->m_modRangedHitChance += apply ? m_modifier.m_amount : (-m_modifier.m_amount); + } } void Aura::HandleModSpellHitChance(bool apply, bool Real) { - m_target->m_modSpellHitChance += apply ? m_modifier.m_amount: (-m_modifier.m_amount); + if(m_target->GetTypeId() == TYPEID_PLAYER) + { + ((Player*)m_target)->UpdateSpellHitChances(); + } + else + { + m_target->m_modSpellHitChance += apply ? m_modifier.m_amount: (-m_modifier.m_amount); + } } void Aura::HandleModSpellCritChance(bool apply, bool Real) @@ -4906,17 +5029,23 @@ void Aura::HandleAuraModRangedAttackPowerOfStatPercent(bool apply, bool Real) if(m_target->GetTypeId() == TYPEID_PLAYER && (m_target->getClassMask() & CLASSMASK_WAND_USERS)!=0) return; - if(m_modifier.m_miscvalue != STAT_INTELLECT) - { - // support required adding UpdateAttackPowerAndDamage calls at stat update - sLog.outError("Aura SPELL_AURA_MOD_RANGED_ATTACK_POWER_OF_STAT_PERCENT (212) need support non-intelect stats!"); - return; - } - // Recalculate bonus ((Player*)m_target)->UpdateAttackPowerAndDamage(true); } +void Aura::HandleAuraModAttackPowerOfStatPercent(bool apply, bool Real) +{ + // spells required only Real aura add/remove + if(!Real) + return; + + if(m_target->GetTypeId() == TYPEID_PLAYER && (m_target->getClassMask() & CLASSMASK_WAND_USERS)!=0) + return; + + // Recalculate bonus + ((Player*)m_target)->UpdateAttackPowerAndDamage(false); +} + /********************************/ /*** DAMAGE BONUS ***/ /********************************/ @@ -5098,6 +5227,28 @@ void Aura::HandleModPowerCost(bool apply, bool Real) m_target->ApplyModInt32Value(UNIT_FIELD_POWER_COST_MODIFIER+i,m_modifier.m_amount,apply); } +void Aura::HandleNoReagentUseAura(bool Apply, bool Real) +{ + // spells required only Real aura add/remove + if(!Real) + return; + if(m_target->GetTypeId() != TYPEID_PLAYER) + return; + uint32 mask[3] = {0, 0, 0}; + Unit::AuraList const& noReagent = m_target->GetAurasByType(SPELL_AURA_NO_REAGENT_USE); + for(Unit::AuraList::const_iterator i = noReagent.begin(); i != noReagent.end(); ++i) + { + uint32 const *ptr = (*i)->getAuraSpellClassMask(); + mask[0]|=ptr[0]; + mask[1]|=ptr[1]; + mask[2]|=ptr[2]; + } + + m_target->SetUInt32Value(PLAYER_NO_REAGENT_COST_1 , mask[0]); + m_target->SetUInt32Value(PLAYER_NO_REAGENT_COST_1+1, mask[1]); + m_target->SetUInt32Value(PLAYER_NO_REAGENT_COST_1+2, mask[2]); +} + /*********************************************************/ /*** OTHERS ***/ /*********************************************************/ @@ -5319,6 +5470,20 @@ void Aura::HandleModRating(bool apply, bool Real) ((Player*)m_target)->ApplyRatingMod(CombatRating(rating), m_modifier.m_amount, apply); } +void Aura::HandleModRatingFromStat(bool apply, bool Real) +{ + // spells required only Real aura add/remove + if(!Real) + return; + + if(m_target->GetTypeId() != TYPEID_PLAYER) + return; + // Just recalculate ratings + for (uint32 rating = 0; rating < MAX_COMBAT_RATING; ++rating) + if (m_modifier.m_miscvalue & (1 << rating)) + ((Player*)m_target)->ApplyRatingMod(CombatRating(rating), 0, apply); +} + void Aura::HandleForceMoveForward(bool apply, bool Real) { if(!Real || m_target->GetTypeId() != TYPEID_PLAYER) @@ -5608,6 +5773,7 @@ void Aura::PeriodicTick() data << (uint32)GetSpellSchoolMask(GetSpellProto()); // will be mask in 2.4.x data << (uint32)absorb; data << (uint32)resist; + data << uint32(0); // wotlk m_target->SendMessageToSet(&data,true); Unit* target = m_target; // aura can be deleted in DealDamage @@ -5768,7 +5934,7 @@ void Aura::PeriodicTick() return; // heal for caster damage (must be alive) - if(m_target != pCaster && GetSpellProto()->SpellVisual==163 && !pCaster->isAlive()) + if(m_target != pCaster && GetSpellProto()->SpellVisual[0]==163 && !pCaster->isAlive()) return; // ignore non positive values (can be result apply spellmods to aura damage @@ -5793,6 +5959,7 @@ void Aura::PeriodicTick() data << uint32(1); data << uint32(m_modifier.m_auraname); data << (uint32)pdamage; + data << uint32(0); // wotlk m_target->SendMessageToSet(&data,true); int32 gain = m_target->ModifyHealth(pdamage); @@ -5812,7 +5979,7 @@ void Aura::PeriodicTick() bool haveCastItem = GetCastItemGUID()!=0; // heal for caster damage - if(m_target!=pCaster && spellProto->SpellVisual==163) + if(m_target!=pCaster && spellProto->SpellVisual[0]==163) { uint32 dmg = spellProto->manaPerSecond; if(pCaster->GetHealth() <= dmg && pCaster->GetTypeId()==TYPEID_PLAYER) @@ -6033,114 +6200,136 @@ void Aura::PeriodicTick() void Aura::PeriodicDummyTick() { + Unit *caster = GetCaster(); SpellEntry const* spell = GetSpellProto(); - switch (spell->Id) + switch (spell->SpellFamilyName) { - // Drink - case 430: - case 431: - case 432: - case 1133: - case 1135: - case 1137: - case 10250: - case 22734: - case 27089: - case 34291: - case 43706: - case 46755: + case SPELLFAMILY_GENERIC: + switch (spell->Id) { - if (m_target->GetTypeId() != TYPEID_PLAYER) - return; - // Search SPELL_AURA_MOD_POWER_REGEN aura for this spell and add bonus - Unit::AuraList const& aura = m_target->GetAurasByType(SPELL_AURA_MOD_POWER_REGEN); - for(Unit::AuraList::const_iterator i = aura.begin(); i != aura.end(); ++i) + // Drink + case 430: + case 431: + case 432: + case 1133: + case 1135: + case 1137: + case 10250: + case 22734: + case 27089: + case 34291: + case 43706: + case 46755: + case 49472: // Drink Coffee + case 61830: { - if ((*i)->GetId() == GetId()) - { - // Get tick number - int32 tick = (m_maxduration - m_duration) / m_modifier.periodictime; - // Default case (not on arenas) - if (tick == 0) - { - (*i)->GetModifier()->m_amount = m_modifier.m_amount; - ((Player*)m_target)->UpdateManaRegen(); - // Disable continue - m_isPeriodic = false; - } + if (m_target->GetTypeId() != TYPEID_PLAYER) return; - //********************************************** - // Code commended since arena patch not added - // This feature uses only in arenas - //********************************************** - // Here need increase mana regen per tick (6 second rule) - // on 0 tick - 0 (handled in 2 second) - // on 1 tick - 166% (handled in 4 second) - // on 2 tick - 133% (handled in 6 second) - // Not need update after 3 tick - /* - if (tick > 3) - return; - // Apply bonus for 0 - 3 tick - switch (tick) + // Search SPELL_AURA_MOD_POWER_REGEN aura for this spell and add bonus + Unit::AuraList const& aura = m_target->GetAurasByType(SPELL_AURA_MOD_POWER_REGEN); + for(Unit::AuraList::const_iterator i = aura.begin(); i != aura.end(); ++i) + { + if ((*i)->GetId() == GetId()) { - case 0: // 0% - (*i)->GetModifier()->m_amount = m_modifier.m_amount = 0; - break; - case 1: // 166% - (*i)->GetModifier()->m_amount = m_modifier.m_amount * 5 / 3; - break; - case 2: // 133% - (*i)->GetModifier()->m_amount = m_modifier.m_amount * 4 / 3; - break; - default: // 100% - normal regen + // Get tick number + int32 tick = (m_maxduration - m_duration) / m_modifier.periodictime; + // Default case (not on arenas) + if (tick == 0) + { (*i)->GetModifier()->m_amount = m_modifier.m_amount; - break; + ((Player*)m_target)->UpdateManaRegen(); + // Disable continue + m_isPeriodic = false; + } + return; + //********************************************** + // Code commended since arena patch not added + // This feature uses only in arenas + //********************************************** + // Here need increase mana regen per tick (6 second rule) + // on 0 tick - 0 (handled in 2 second) + // on 1 tick - 166% (handled in 4 second) + // on 2 tick - 133% (handled in 6 second) + // Not need update after 3 tick + /* + if (tick > 3) + return; + // Apply bonus for 0 - 3 tick + switch (tick) + { + case 0: // 0% + (*i)->GetModifier()->m_amount = m_modifier.m_amount = 0; + break; + case 1: // 166% + (*i)->GetModifier()->m_amount = m_modifier.m_amount * 5 / 3; + break; + case 2: // 133% + (*i)->GetModifier()->m_amount = m_modifier.m_amount * 4 / 3; + break; + default: // 100% - normal regen + (*i)->GetModifier()->m_amount = m_modifier.m_amount; + break; + } + ((Player*)m_target)->UpdateManaRegen(); + return;*/ } - ((Player*)m_target)->UpdateManaRegen(); - return;*/ } + return; + } + // Forsaken Skills + case 7054: + { + // Possibly need cast one of them (but + // 7038 Forsaken Skill: Swords + // 7039 Forsaken Skill: Axes + // 7040 Forsaken Skill: Daggers + // 7041 Forsaken Skill: Maces + // 7042 Forsaken Skill: Staves + // 7043 Forsaken Skill: Bows + // 7044 Forsaken Skill: Guns + // 7045 Forsaken Skill: 2H Axes + // 7046 Forsaken Skill: 2H Maces + // 7047 Forsaken Skill: 2H Swords + // 7048 Forsaken Skill: Defense + // 7049 Forsaken Skill: Fire + // 7050 Forsaken Skill: Frost + // 7051 Forsaken Skill: Holy + // 7053 Forsaken Skill: Shadow + return; } - return; - } // // Panda // case 19230: break; -// // Master of Subtlety -// case 31666: break; // // Gossip NPC Periodic - Talk // case 33208: break; // // Gossip NPC Periodic - Despawn // case 33209: break; -// // Force of Nature -// case 33831: break; - // Aspect of the Viper - case 34074: - { - if (m_target->GetTypeId() != TYPEID_PLAYER) + + // TODO: now its not periodic dummy - need move out from here + // Aspect of the Viper + case 34074: + { + if (m_target->GetTypeId() != TYPEID_PLAYER) + return; + // Should be manauser + if (m_target->getPowerType()!=POWER_MANA) + return; + if (!caster) + return; + // Regen amount is max (100% from spell) on 21% or less mana and min on 92.5% or greater mana (20% from spell) + int mana = m_target->GetPower(POWER_MANA); + int max_mana = m_target->GetMaxPower(POWER_MANA); + int32 base_regen = caster->CalculateSpellDamage(m_spellProto, m_effIndex, m_currentBasePoints, m_target); + float regen_pct = 1.20f - 1.1f * mana / max_mana; + if (regen_pct > 1.0f) regen_pct = 1.0f; + else if (regen_pct < 0.2f) regen_pct = 0.2f; + m_modifier.m_amount = int32 (base_regen * regen_pct); + ((Player*)m_target)->UpdateManaRegen(); return; - // Should be manauser - if (m_target->getPowerType()!=POWER_MANA) - return; - Unit *caster = GetCaster(); - if (!caster) - return; - // Regen amount is max (100% from spell) on 21% or less mana and min on 92.5% or greater mana (20% from spell) - int mana = m_target->GetPower(POWER_MANA); - int max_mana = m_target->GetMaxPower(POWER_MANA); - int32 base_regen = caster->CalculateSpellDamage(m_spellProto, m_effIndex, m_currentBasePoints, m_target); - float regen_pct = 1.20f - 1.1f * mana / max_mana; - if (regen_pct > 1.0f) regen_pct = 1.0f; - else if (regen_pct < 0.2f) regen_pct = 0.2f; - m_modifier.m_amount = int32 (base_regen * regen_pct); - ((Player*)m_target)->UpdateManaRegen(); - return; - } + } // // Steal Weapon // case 36207: break; // // Simon Game START timer, (DND) // case 39993: break; -// // Harpooner's Mark -// case 40084: break; // // Knockdown Fel Cannon: break; The Aggro Burst // case 40119: break; // // Old Mount Spell @@ -6153,6 +6342,8 @@ void Aura::PeriodicDummyTick() // case 40846: break; // // Copy Weapon // case 41054: break; +// // Dementia +// case 41404: break; // // Ethereal Ring Visual, Lightning Aura // case 41477: break; // // Ethereal Ring Visual, Lightning Aura (Fork) @@ -6201,6 +6392,8 @@ void Aura::PeriodicDummyTick() // case 43310: break; // // Headless Horseman - Maniacal Laugh, Maniacal, Delayed 17 // case 43884: break; +// // Wretched! +// case 43963: break; // // Headless Horseman - Maniacal Laugh, Maniacal, other, Delayed 17 // case 44000: break; // // Energy Feedback @@ -6267,14 +6460,179 @@ void Aura::PeriodicDummyTick() // case 47407: break; // // Mole Machine Port Schedule // case 47489: break; +// case 47941: break; // Crystal Spike +// case 48200: break; // Healer Aura +// case 48630: break; // Summon Gauntlet Mobs Periodic +// case 49313: break; // Proximity Mine Area Aura // // Mole Machine Portal Schedule // case 49466: break; -// // Drink Coffee -// case 49472: break; +// case 49555: break; // Corpse Explode +// case 49592: break; // Temporal Rift +// case 49957: break; // Cutting Laser +// case 50085: break; // Slow Fall // // Listening to Music // case 50493: break; // // Love Rocket Barrage // case 50530: break; +// Exist more after, need add later + default: + break; + } + break; + case SPELLFAMILY_MAGE: + { + // Mirror Image +// if (spell->Id == 55342) +// return; + break; + } + case SPELLFAMILY_WARRIOR: + { + // Armored to the Teeth + if (spell->SpellIconID == 3516) + { + // Increases your attack power by $s1 for every $s2 armor value you have. + // Calculate AP bonus (from 1 efect of this spell) + int32 apBonus = m_modifier.m_amount * m_target->GetArmor() / m_target->CalculateSpellDamage(spell, 1, spell->EffectBasePoints[1], m_target); + m_target->CastCustomSpell(m_target, 61217, &apBonus, &apBonus, 0, true, 0, this); + return; + } + break; + } + case SPELLFAMILY_DRUID: + { + switch (spell->Id) + { + // Frenzied Regeneration + case 22842: + { + // Converts up to 10 rage per second into health for $d. Each point of rage is converted into ${$m2/10}.1% of max health. + // Should be manauser + if (m_target->getPowerType()!=POWER_RAGE) + return; + uint32 rage = m_target->GetPower(POWER_RAGE); + // Nothing todo + if (rage == 0) + return; + int32 mod = (rage < 100) ? rage : 100; + int32 points = m_target->CalculateSpellDamage(spell, 1, spell->EffectBasePoints[1], m_target); + int32 regen = m_target->GetMaxHealth() * (mod * points / 10) / 1000; + m_target->CastCustomSpell(m_target, 22845, ®en, 0, 0, true, 0, this); + m_target->SetPower(POWER_RAGE, rage-mod); + return; + } + // Force of Nature + case 33831: + return; + default: + break; + } + break; + } + case SPELLFAMILY_ROGUE: + { +// switch (spell->Id) +// { + // Master of Subtlety +// case 31666: break; + // Killing Spree +// case 51690: break; + // Overkill +// case 58428: break; +// default: +// break; +// } + break; + } + case SPELLFAMILY_HUNTER: + { + // Explosive Shot + if (spell->SpellFamilyFlags & 0x8000000000000000LL) + { + if (!caster) + return; + // Skip 0 tick + if (m_duration < m_modifier.periodictime) + return; + int32 damage = caster->CalculateSpellDamage(spell, GetEffIndex(), GetBasePoints(), m_target); + damage+=caster->GetTotalAttackPowerValue(RANGED_ATTACK) * 8 / 100; + damage/=4; + caster->CastCustomSpell(m_target, 56298, &damage, 0, 0, true, 0, this); + return; + } + switch (spell->Id) + { + // Harpooner's Mark + // case 40084: + // return; + // Feeding Frenzy Rank 1 + case 53511: + if ( m_target->GetHealth() * 100 < m_target->GetMaxHealth() * 35 ) + m_target->CastSpell(m_target, 60096, true, 0, this); + return; + // Feeding Frenzy Rank 2 + case 53512: + if ( m_target->GetHealth() * 100 < m_target->GetMaxHealth() * 35 ) + m_target->CastSpell(m_target, 60097, true, 0, this); + return; + default: + break; + } + break; + } + case SPELLFAMILY_SHAMAN: + { + // Astral Shift +// if (spell->Id == 52179) +// return; + break; + } + case SPELLFAMILY_DEATHKNIGHT: + { + // Death and Decay +// if (spell->SpellFamilyFlags & 0x0000000000000020LL) +// return; + // Raise Dead +// if (spell->SpellFamilyFlags & 0x0000000000001000LL) +// return; + // Chains of Ice + if (spell->SpellFamilyFlags & 0x0000400000000000LL) + { + // Get 0 effect aura + Aura *slow = m_target->GetAura(GetId(), 0); + if (slow) + { + slow->ApplyModifier(false, true); + Modifier *mod = slow->GetModifier(); + mod->m_amount+= m_modifier.m_amount; + if (mod->m_amount > 0) mod->m_amount = 0; + slow->ApplyModifier(true, true); + } + return; + } + // Summon Gargoyle +// if (spell->SpellFamilyFlags & 0x0000008000000000LL) +// return; + // Death Rune Mastery +// if (spell->SpellFamilyFlags & 0x0000000000004000LL) +// return; + // Bladed Armor + if (spell->SpellIconID == 2653) + { + // Increases your attack power by $s1 for every $s2 armor value you have. + // Calculate AP bonus (from 1 efect of this spell) + int32 apBonus = m_modifier.m_amount * m_target->GetArmor() / m_target->CalculateSpellDamage(spell, 1, spell->EffectBasePoints[1], m_target); + m_target->CastCustomSpell(m_target, 61217, &apBonus, &apBonus, 0, true, 0, this); + return; + } + // Reaping +// if (spell->SpellIconID == 22) +// return; + // Blood of the North +// if (spell->SpellIconID == 30412) +// return; + break; + } default: break; } @@ -6338,3 +6696,53 @@ void Aura::HandleArenaPreparation(bool apply, bool Real) else m_target->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PREPARATION); } + +void Aura::HandleAuraControlVehicle(bool apply, bool Real) +{ + if(!Real) + return; + + if(m_target->GetTypeId() != TYPEID_PLAYER) + return; + + if(Pet *pet = m_target->GetPet()) + pet->Remove(PET_SAVE_AS_CURRENT); + + WorldPacket data(SMSG_ON_CANCEL_EXPECTED_RIDE_VEHICLE_AURA, 0); + ((Player*)m_target)->GetSession()->SendPacket(&data); +} + +void Aura::HandleAuraConvertRune(bool apply, bool Real) +{ + if(!Real) + return; + + if(m_target->GetTypeId() != TYPEID_PLAYER) + return; + + Player *plr = (Player*)m_target; + + if(plr->getClass() != CLASS_DEATH_KNIGHT) + return; + + // how to determine what rune need to be converted? + for(uint32 i = 0; i < MAX_RUNES; ++i) + { + if(apply) + { + if(!plr->GetRuneCooldown(i)) + { + plr->ConvertRune(i, GetSpellProto()->EffectMiscValueB[m_effIndex]); + break; + } + } + else + { + if(plr->GetCurrentRune(i) == GetSpellProto()->EffectMiscValueB[m_effIndex]) + { + plr->ConvertRune(i, plr->GetBaseRune(i)); + break; + } + } + } +} diff --git a/src/game/SpellAuras.h b/src/game/SpellAuras.h index ea4f25ff4..b62470ac1 100644 --- a/src/game/SpellAuras.h +++ b/src/game/SpellAuras.h @@ -98,6 +98,7 @@ class MANGOS_DLL_SPEC Aura void HandleAuraFeatherFall(bool Apply, bool Real); void HandleAuraHover(bool Apply, bool Real); void HandleAddModifier(bool Apply, bool Real); + void HandleAddTargetTrigger(bool Apply, bool Real); void HandleAuraModStun(bool Apply, bool Real); void HandleModDamageDone(bool Apply, bool Real); void HandleAuraUntrackable(bool Apply, bool Real); @@ -182,10 +183,12 @@ class MANGOS_DLL_SPEC Aura void HandleAuraGhost(bool Apply, bool Real); void HandleAuraAllowFlight(bool Apply, bool Real); void HandleModRating(bool apply, bool Real); + void HandleModRatingFromStat(bool apply, bool Real); void HandleModTargetResistance(bool apply, bool Real); void HandleAuraModAttackPowerPercent(bool apply, bool Real); void HandleAuraModRangedAttackPowerPercent(bool apply, bool Real); void HandleAuraModRangedAttackPowerOfStatPercent(bool apply, bool Real); + void HandleAuraModAttackPowerOfStatPercent(bool apply, bool Real); void HandleSpiritOfRedemption(bool apply, bool Real); void HandleModManaRegen(bool apply, bool Real); void HandleComprehendLanguage(bool apply, bool Real); @@ -195,6 +198,7 @@ class MANGOS_DLL_SPEC Aura void HandleModSpellDamagePercentFromStat(bool apply, bool Real); void HandleModSpellHealingPercentFromStat(bool apply, bool Real); void HandleAuraModDispelResist(bool apply, bool Real); + void HandleAuraControlVehicle(bool apply, bool Real); void HandleModSpellDamagePercentFromAttackPower(bool apply, bool Real); void HandleModSpellHealingPercentFromAttackPower(bool apply, bool Real); void HandleAuraModPacifyAndSilence(bool Apply, bool Real); @@ -207,6 +211,9 @@ class MANGOS_DLL_SPEC Aura void HandlePreventFleeing(bool apply, bool Real); void HandleManaShield(bool apply, bool Real); void HandleArenaPreparation(bool apply, bool Real); + void HandleAuraConvertRune(bool apply, bool Real); + void HandleAuraIncreaseBaseHealthPercent(bool Apply, bool Real); + void HandleNoReagentUseAura(bool Apply, bool Real); virtual ~Aura(); @@ -226,8 +233,8 @@ class MANGOS_DLL_SPEC Aura int32 GetAuraDuration() const { return m_duration; } void SetAuraDuration(int32 duration) { m_duration = duration; } time_t GetAuraApplyTime() { return m_applyTime; } - void UpdateAuraDuration(); - void SendAuraDurationForCaster(Player* caster); + + SpellModifier *getAuraSpellMod() {return m_spellmod; } uint64 const& GetCasterGUID() const { return m_caster_guid; } Unit* GetCaster() const; @@ -244,13 +251,19 @@ class MANGOS_DLL_SPEC Aura uint8 GetAuraSlot() const { return m_auraSlot; } void SetAuraSlot(uint8 slot) { m_auraSlot = slot; } + uint8 GetAuraFlags() const { return m_auraFlags; } + void SetAuraFlags(uint8 flags) { m_auraFlags = flags; } + uint8 GetAuraLevel() const { return m_auraLevel; } + void SetAuraLevel(uint8 level) { m_auraLevel = level; } + uint8 GetAuraCharges() const { return m_procCharges; } + void SetAuraCharges(uint8 charges) { m_procCharges = charges; } + void SetAura(bool remove) { m_target->SetVisibleAura(m_auraSlot, remove ? 0 : GetId()); } + void SendAuraUpdate(bool remove); void UpdateAuraCharges() { - uint8 slot = GetAuraSlot(); - // only aura in slot with charges and without stack limitation - if (slot < MAX_AURAS && m_procCharges >= 1 && GetSpellProto()->StackAmount==0) - SetAuraApplication(slot, m_procCharges - 1); + if (m_auraSlot < MAX_AURAS && m_procCharges >= 1 && GetSpellProto()->StackAmount==0) + SetAuraCharges(m_procCharges - 1); } bool IsPositive() { return m_positive; } @@ -292,6 +305,9 @@ class MANGOS_DLL_SPEC Aura void PeriodicTick(); void PeriodicDummyTick(); + + uint32 const *getAuraSpellClassMask() const { return m_spellProto->EffectSpellClassMaskA + m_effIndex * 3; } + bool isAffectedOnSpell(SpellEntry const *spell) const; protected: Aura(SpellEntry const* spellproto, uint32 eff, int32 *currentBasePoints, Unit *target, Unit *caster = NULL, Item* castItem = NULL); @@ -311,6 +327,8 @@ class MANGOS_DLL_SPEC Aura AuraRemoveMode m_removeMode; uint8 m_auraSlot; + uint8 m_auraFlags; + uint8 m_auraLevel; bool m_positive:1; bool m_permanent:1; @@ -330,10 +348,6 @@ class MANGOS_DLL_SPEC Aura private: void UpdateSlotCounterAndDuration(bool add); void CleanupTriggeredSpells(); - void SetAura(uint32 slot, bool remove) { m_target->SetUInt32Value(UNIT_FIELD_AURA + slot, remove ? 0 : GetId()); } - void SetAuraFlag(uint32 slot, bool add); - void SetAuraLevel(uint32 slot, uint32 level); - void SetAuraApplication(uint32 slot, int8 count); }; class MANGOS_DLL_SPEC AreaAura : public Aura diff --git a/src/game/SpellEffects.cpp b/src/game/SpellEffects.cpp index 4f8baefc4..bd0004333 100644 --- a/src/game/SpellEffects.cpp +++ b/src/game/SpellEffects.cpp @@ -122,16 +122,16 @@ pEffect SpellEffects[TOTAL_SPELL_EFFECTS]= &Spell::EffectPowerBurn, // 62 SPELL_EFFECT_POWER_BURN &Spell::EffectThreat, // 63 SPELL_EFFECT_THREAT &Spell::EffectTriggerSpell, // 64 SPELL_EFFECT_TRIGGER_SPELL - &Spell::EffectUnused, // 65 SPELL_EFFECT_HEALTH_FUNNEL unused - &Spell::EffectUnused, // 66 SPELL_EFFECT_POWER_FUNNEL unused + &Spell::EffectApplyAreaAura, // 65 SPELL_EFFECT_APPLY_AREA_AURA_RAID + &Spell::EffectUnused, // 66 SPELL_EFFECT_CREATE_MANA_GEM (possibly recharge it, misc - is item ID) &Spell::EffectHealMaxHealth, // 67 SPELL_EFFECT_HEAL_MAX_HEALTH &Spell::EffectInterruptCast, // 68 SPELL_EFFECT_INTERRUPT_CAST &Spell::EffectDistract, // 69 SPELL_EFFECT_DISTRACT &Spell::EffectPull, // 70 SPELL_EFFECT_PULL one spell: Distract Move &Spell::EffectPickPocket, // 71 SPELL_EFFECT_PICKPOCKET &Spell::EffectAddFarsight, // 72 SPELL_EFFECT_ADD_FARSIGHT - &Spell::EffectSummonGuardian, // 73 SPELL_EFFECT_SUMMON_POSSESSED - &Spell::EffectSummonTotem, // 74 SPELL_EFFECT_SUMMON_TOTEM + &Spell::EffectUnused, // 73 SPELL_EFFECT_UNTRAIN_TALENTS + &Spell::EffectApplyGlyph, // 74 SPELL_EFFECT_APPLY_GLYPH &Spell::EffectHealMechanical, // 75 SPELL_EFFECT_HEAL_MECHANICAL one spell: Mechanical Patch Kit &Spell::EffectSummonObjectWild, // 76 SPELL_EFFECT_SUMMON_OBJECT_WILD &Spell::EffectScriptEffect, // 77 SPELL_EFFECT_SCRIPT_EFFECT @@ -144,10 +144,10 @@ pEffect SpellEffects[TOTAL_SPELL_EFFECTS]= &Spell::EffectStuck, // 84 SPELL_EFFECT_STUCK &Spell::EffectSummonPlayer, // 85 SPELL_EFFECT_SUMMON_PLAYER &Spell::EffectActivateObject, // 86 SPELL_EFFECT_ACTIVATE_OBJECT - &Spell::EffectSummonTotem, // 87 SPELL_EFFECT_SUMMON_TOTEM_SLOT1 - &Spell::EffectSummonTotem, // 88 SPELL_EFFECT_SUMMON_TOTEM_SLOT2 - &Spell::EffectSummonTotem, // 89 SPELL_EFFECT_SUMMON_TOTEM_SLOT3 - &Spell::EffectSummonTotem, // 90 SPELL_EFFECT_SUMMON_TOTEM_SLOT4 + &Spell::EffectUnused, // 87 SPELL_EFFECT_WMO_DAMAGE + &Spell::EffectUnused, // 88 SPELL_EFFECT_WMO_REPAIR + &Spell::EffectUnused, // 89 SPELL_EFFECT_WMO_CHANGE + &Spell::EffectUnused, // 90 SPELL_EFFECT_KILL_CREDIT &Spell::EffectUnused, // 91 SPELL_EFFECT_THREAT_ALL one spell: zzOLDBrainwash &Spell::EffectEnchantHeldItem, // 92 SPELL_EFFECT_ENCHANT_HELD_ITEM &Spell::EffectUnused, // 93 SPELL_EFFECT_SUMMON_PHANTASM @@ -189,21 +189,21 @@ pEffect SpellEffects[TOTAL_SPELL_EFFECTS]= &Spell::EffectApplyAreaAura, //129 SPELL_EFFECT_APPLY_AREA_AURA_ENEMY &Spell::EffectNULL, //130 SPELL_EFFECT_REDIRECT_THREAT &Spell::EffectUnused, //131 SPELL_EFFECT_131 used in some test spells - &Spell::EffectNULL, //132 SPELL_EFFECT_PLAY_MUSIC sound id in misc value + &Spell::EffectNULL, //132 SPELL_EFFECT_PLAY_MUSIC sound id in misc value (SoundEntries.dbc) &Spell::EffectUnlearnSpecialization, //133 SPELL_EFFECT_UNLEARN_SPECIALIZATION unlearn profession specialization &Spell::EffectKillCredit, //134 SPELL_EFFECT_KILL_CREDIT misc value is creature entry &Spell::EffectNULL, //135 SPELL_EFFECT_CALL_PET &Spell::EffectHealPct, //136 SPELL_EFFECT_HEAL_PCT &Spell::EffectEnergisePct, //137 SPELL_EFFECT_ENERGIZE_PCT &Spell::EffectNULL, //138 SPELL_EFFECT_138 Leap - &Spell::EffectUnused, //139 SPELL_EFFECT_139 unused + &Spell::EffectUnused, //139 SPELL_EFFECT_CLEAR_QUEST (misc - is quest ID) &Spell::EffectForceCast, //140 SPELL_EFFECT_FORCE_CAST &Spell::EffectNULL, //141 SPELL_EFFECT_141 damage and reduce speed? &Spell::EffectTriggerSpellWithValue, //142 SPELL_EFFECT_TRIGGER_SPELL_WITH_VALUE &Spell::EffectApplyAreaAura, //143 SPELL_EFFECT_APPLY_AREA_AURA_OWNER &Spell::EffectNULL, //144 SPELL_EFFECT_144 Spectral Blast &Spell::EffectNULL, //145 SPELL_EFFECT_145 Black Hole Effect - &Spell::EffectUnused, //146 SPELL_EFFECT_146 unused + &Spell::EffectActivateRune, //146 SPELL_EFFECT_ACTIVATE_RUNE &Spell::EffectQuestFail, //147 SPELL_EFFECT_QUEST_FAIL quest fail &Spell::EffectUnused, //148 SPELL_EFFECT_148 unused &Spell::EffectNULL, //149 SPELL_EFFECT_149 swoop @@ -211,6 +211,12 @@ pEffect SpellEffects[TOTAL_SPELL_EFFECTS]= &Spell::EffectTriggerRitualOfSummoning, //151 SPELL_EFFECT_TRIGGER_SPELL_2 &Spell::EffectNULL, //152 SPELL_EFFECT_152 summon Refer-a-Friend &Spell::EffectNULL, //153 SPELL_EFFECT_CREATE_PET misc value is creature entry + &Spell::EffectNULL, //154 unused + &Spell::EffectTitanGrip, //155 SPELL_EFFECT_TITAN_GRIP Allows you to equip two-handed axes, maces and swords in one hand, but you attack $49152s1% slower than normal. + &Spell::EffectNULL, //156 Add Socket + &Spell::EffectNULL, //157 create/learn random item/spell for profession + &Spell::EffectMilling, //158 milling + &Spell::EffectNULL //159 allow rename pet once again }; void Spell::EffectNULL(uint32 /*i*/) @@ -336,6 +342,13 @@ void Spell::EffectSchoolDMG(uint32 effect_idx) damage = 200; break; } + // Intercept (warrior spell trigger) + case 20253: + case 61491: + { + damage+= uint32(m_caster->GetTotalAttackPowerValue(BASE_ATTACK) * 0.12f); + break; + } } break; } @@ -365,6 +378,12 @@ void Spell::EffectSchoolDMG(uint32 effect_idx) damage = uint32(damage * m_caster->GetTotalAttackPowerValue(BASE_ATTACK) / 100); m_caster->ModifyAuraState(AURA_STATE_WARRIOR_VICTORY_RUSH, false); } + // Revenge ${$m1+$AP*0.207} to ${$M1+$AP*0.207} + else if(m_spellInfo->SpellFamilyFlags & 0x0000000000000400LL) + damage+= uint32(m_caster->GetTotalAttackPowerValue(BASE_ATTACK) * 0.207f); + // Heroic Throw ${$m1+$AP*.50} + else if(m_spellInfo->SpellFamilyFlags & 0x0000000100000000LL) + damage+= uint32(m_caster->GetTotalAttackPowerValue(BASE_ATTACK) * 0.5f); break; } case SPELLFAMILY_WARLOCK: @@ -374,18 +393,20 @@ void Spell::EffectSchoolDMG(uint32 effect_idx) { // Incinerate does more dmg (dmg*0.25) if the target is Immolated. if(unitTarget->HasAuraState(AURA_STATE_IMMOLATE)) - damage += int32(damage*0.25); + damage += int32(damage*0.25f); } break; } case SPELLFAMILY_DRUID: { // Ferocious Bite - if((m_spellInfo->SpellFamilyFlags & 0x000800000) && m_spellInfo->SpellVisual==6587) + if(m_caster->GetTypeId()==TYPEID_PLAYER && (m_spellInfo->SpellFamilyFlags & 0x000800000) && m_spellInfo->SpellVisual[0]==6587) { - // converts each extra point of energy into ($f1+$AP/630) additional damage - float multiple = m_caster->GetTotalAttackPowerValue(BASE_ATTACK) / 630 + m_spellInfo->DmgMultiplier[effect_idx]; + // converts each extra point of energy into ($f1+$AP/410) additional damage + float ap = m_caster->GetTotalAttackPowerValue(BASE_ATTACK); + float multiple = ap / 410 + m_spellInfo->DmgMultiplier[effect_idx]; damage += int32(m_caster->GetPower(POWER_ENERGY) * multiple); + damage += int32(((Player*)m_caster)->GetComboPoints() * ap * 7 / 100); m_caster->SetPower(POWER_ENERGY,0); } // Rake @@ -461,7 +482,7 @@ void Spell::EffectSchoolDMG(uint32 effect_idx) { // Deadly poison (only attacker applied) if( (*itr)->GetSpellProto()->SpellFamilyName==SPELLFAMILY_ROGUE && ((*itr)->GetSpellProto()->SpellFamilyFlags & 0x10000) && - (*itr)->GetSpellProto()->SpellVisual==5100 && (*itr)->GetCasterGUID()==m_caster->GetGUID() ) + (*itr)->GetSpellProto()->SpellVisual[0]==5100 && (*itr)->GetCasterGUID()==m_caster->GetGUID() ) { --combo; ++doses; @@ -487,26 +508,47 @@ void Spell::EffectSchoolDMG(uint32 effect_idx) { if(uint32 combo = ((Player*)m_caster)->GetComboPoints()) { - damage += int32(m_caster->GetTotalAttackPowerValue(BASE_ATTACK) * combo * 0.03f); + float ap = m_caster->GetTotalAttackPowerValue(BASE_ATTACK); + damage += irand(int32(ap * combo * 0.03f), int32(ap * combo * 0.07f)); // Eviscerate and Envenom Bonus Damage (item set effect) if(m_caster->GetDummyAura(37169)) damage += combo*40; } } + // Gouge + else if(m_spellInfo->SpellFamilyFlags & 0x0000000000000008LL) + { + damage += int32(m_caster->GetTotalAttackPowerValue(BASE_ATTACK)*0.02f); + } + // Instant Poison + else if(m_spellInfo->SpellFamilyFlags & 0x0000000000002000LL) + { + damage += int32(m_caster->GetTotalAttackPowerValue(BASE_ATTACK)*0.10f); + } + // Wound Poison + else if(m_spellInfo->SpellFamilyFlags & 0x0000000010000000LL) + { + damage += int32(m_caster->GetTotalAttackPowerValue(BASE_ATTACK)*0.04f); + } break; } case SPELLFAMILY_HUNTER: { // Mongoose Bite - if((m_spellInfo->SpellFamilyFlags & 0x000000002) && m_spellInfo->SpellVisual==342) + if((m_spellInfo->SpellFamilyFlags & 0x000000002) && m_spellInfo->SpellVisual[0]==342) { - damage += int32(m_caster->GetTotalAttackPowerValue(BASE_ATTACK)*0.2); + damage += int32(m_caster->GetTotalAttackPowerValue(BASE_ATTACK)*0.2f); + } + // Counterattack + else if(m_spellInfo->SpellFamilyFlags & 0x0008000000000000LL) + { + damage += int32(m_caster->GetTotalAttackPowerValue(BASE_ATTACK)*0.2f); } // Arcane Shot else if((m_spellInfo->SpellFamilyFlags & 0x00000800) && m_spellInfo->maxLevel > 0) { - damage += int32(m_caster->GetTotalAttackPowerValue(RANGED_ATTACK)*0.15); + damage += int32(m_caster->GetTotalAttackPowerValue(RANGED_ATTACK)*0.15f); } // Steady Shot else if(m_spellInfo->SpellFamilyFlags & 0x100000000LL) @@ -514,16 +556,16 @@ void Spell::EffectSchoolDMG(uint32 effect_idx) int32 base = irand((int32)m_caster->GetWeaponDamageRange(RANGED_ATTACK, MINDAMAGE),(int32)m_caster->GetWeaponDamageRange(RANGED_ATTACK, MAXDAMAGE)); damage += int32(float(base)/m_caster->GetAttackTime(RANGED_ATTACK)*2800 + m_caster->GetTotalAttackPowerValue(RANGED_ATTACK)*0.2f); } - //Explosive Trap Effect + // Explosive Trap Effect else if(m_spellInfo->SpellFamilyFlags & 0x00000004) { - damage += int32(m_caster->GetTotalAttackPowerValue(RANGED_ATTACK)*0.1); + damage += int32(m_caster->GetTotalAttackPowerValue(RANGED_ATTACK)*0.1f); } break; } case SPELLFAMILY_PALADIN: { - //Judgement of Vengeance + // Judgement of Vengeance if((m_spellInfo->SpellFamilyFlags & 0x800000000LL) && m_spellInfo->SpellIconID==2292) { uint32 stacks = 0; @@ -537,6 +579,38 @@ void Spell::EffectSchoolDMG(uint32 effect_idx) else damage *= stacks; } + // Avenger's Shield ($m1+0.07*$SPH+0.07*$AP) + else if(m_spellInfo->SpellFamilyFlags & 0x0000000000004000LL) + { + float ap = m_caster->GetTotalAttackPowerValue(BASE_ATTACK); + int32 holy = m_caster->SpellBaseDamageBonus(GetSpellSchoolMask(m_spellInfo)) + + m_caster->SpellBaseDamageBonusForVictim(GetSpellSchoolMask(m_spellInfo), unitTarget); + damage += int32(ap * 0.07f) + int32(holy * 7 / 100); + } + // Exorcism ($m1+0.15*$SPH+0.15*$AP) + else if(m_spellInfo->SpellFamilyFlags & 0x0000000200000000LL) + { + float ap = m_caster->GetTotalAttackPowerValue(BASE_ATTACK); + int32 holy = m_caster->SpellBaseDamageBonus(GetSpellSchoolMask(m_spellInfo)) + + m_caster->SpellBaseDamageBonusForVictim(GetSpellSchoolMask(m_spellInfo), unitTarget); + damage += int32(ap * 0.15f) + int32(holy * 15 / 100); + } + // Hammer of Wrath ($m1+0.15*$SPH+0.15*$AP) + else if(m_spellInfo->SpellFamilyFlags & 0x0000008000000000LL) + { + float ap = m_caster->GetTotalAttackPowerValue(BASE_ATTACK); + int32 holy = m_caster->SpellBaseDamageBonus(GetSpellSchoolMask(m_spellInfo)) + + m_caster->SpellBaseDamageBonusForVictim(GetSpellSchoolMask(m_spellInfo), unitTarget); + damage += int32(ap * 0.15f) + int32(holy * 15 / 100); + } + // Holy Wrath ($m1+0.07*$SPH+0.07*$AP) + else if(m_spellInfo->SpellFamilyFlags & 0x0020000000000000LL) + { + float ap = m_caster->GetTotalAttackPowerValue(BASE_ATTACK); + int32 holy = m_caster->SpellBaseDamageBonus(GetSpellSchoolMask(m_spellInfo)) + + m_caster->SpellBaseDamageBonusForVictim(GetSpellSchoolMask(m_spellInfo), unitTarget); + damage += int32(ap * 0.15f) + int32(holy * 15 / 100); + } break; } } @@ -1109,6 +1183,12 @@ void Spell::EffectDummy(uint32 i) m_caster->CastSpell(m_caster, 30452, true, NULL); return; } + case 53341: + case 53343: + { + m_caster->CastSpell(m_caster,54586,true); + return; + } } //All IconID Check in there @@ -1182,7 +1262,7 @@ void Spell::EffectDummy(uint32 i) break; case SPELLFAMILY_WARRIOR: // Charge - if(m_spellInfo->SpellFamilyFlags & 0x1 && m_spellInfo->SpellVisual == 867) + if(m_spellInfo->SpellFamilyFlags & 0x1 && m_spellInfo->SpellVisual[0] == 867) { int32 chargeBasePoints0 = damage; m_caster->CastCustomSpell(m_caster,34846,&chargeBasePoints0,NULL,NULL,true); @@ -1469,10 +1549,8 @@ void Spell::EffectDummy(uint32 i) mod->value = -50; mod->type = SPELLMOD_PCT; mod->spellId = m_spellInfo->Id; - mod->effectId = i; - mod->lastAffected = NULL; mod->mask = 0x0000020000000000LL; - mod->charges = 0; + mod->mask2= 0LL; ((Player*)m_caster)->AddSpellMod(mod, true); m_caster->CastSpell(unitTarget,spell_proto,true,NULL); @@ -2577,7 +2655,7 @@ void Spell::DoCreateItem(uint32 i, uint32 itemtype) return; } - if(BattleGround* bg = sBattleGroundMgr.GetBattleGround(bgType)) + if(BattleGround* bg = sBattleGroundMgr.GetBattleGroundTemplate(bgType)) bg->SendRewardMarkByMail(player,newitemid,no_space); } } @@ -2875,10 +2953,10 @@ void Spell::EffectOpenLock(uint32 /*i*/) } // check key - for(int i = 0; i < 5; ++i) + for(int i = 0; i < 8; ++i) { - // type==1 This means lockInfo->key[i] is an item - if(lockInfo->keytype[i]==LOCK_KEY_ITEM && lockInfo->key[i] && m_CastItem && m_CastItem->GetEntry()==lockInfo->key[i]) + // Type==1 This means lockInfo->Index[i] is an item + if(lockInfo->Type[i]==LOCK_KEY_ITEM && lockInfo->Index[i] && m_CastItem && m_CastItem->GetEntry()==lockInfo->Index[i]) { SendLoot(guid, loottype); return; @@ -2896,9 +2974,9 @@ void Spell::EffectOpenLock(uint32 /*i*/) // skill bonus provided by casting spell (mostly item spells) uint32 spellSkillBonus = uint32(m_currentBasePoints[0]+1); - uint32 reqSkillValue = lockInfo->requiredminingskill; + uint32 reqSkillValue = lockInfo->Skill[0]; - if(lockInfo->requiredlockskill) // required pick lock skill applying + if(lockInfo->Skill[1]) // required pick lock skill applying { if(SkillId != SKILL_LOCKPICKING) // wrong skill (cheating?) { @@ -2906,7 +2984,7 @@ void Spell::EffectOpenLock(uint32 /*i*/) return; } - reqSkillValue = lockInfo->requiredlockskill; + reqSkillValue = lockInfo->Skill[1]; } else if(SkillId == SKILL_LOCKPICKING) // apply picklock skill to wrong target { @@ -3230,7 +3308,7 @@ void Spell::EffectLearnSpell(uint32 i) Player *player = (Player*)unitTarget; - uint32 spellToLearn = (m_spellInfo->Id==SPELL_ID_GENERIC_LEARN) ? damage : m_spellInfo->EffectTriggerSpell[i]; + uint32 spellToLearn = ((m_spellInfo->Id==SPELL_ID_GENERIC_LEARN) || (m_spellInfo->Id==SPELL_ID_GENERIC_LEARN_PET)) ? damage : m_spellInfo->EffectTriggerSpell[i]; player->learnSpell(spellToLearn); sLog.outDebug( "Spell: Player %u have learned spell %u from NpcGUID=%u", player->GetGUIDLow(), spellToLearn, m_caster->GetGUIDLow() ); @@ -3367,7 +3445,7 @@ void Spell::EffectDispel(uint32 i) void Spell::EffectDualWield(uint32 /*i*/) { - if (unitTarget->GetTypeId() == TYPEID_PLAYER) + if (unitTarget && unitTarget->GetTypeId() == TYPEID_PLAYER) ((Player*)unitTarget)->SetCanDualWield(true); } @@ -3820,13 +3898,13 @@ void Spell::EffectEnchantItemTmp(uint32 i) else if(m_spellInfo->SpellFamilyName==SPELLFAMILY_SHAMAN) duration = 1800; // 30 mins // other cases with this SpellVisual already selected - else if(m_spellInfo->SpellVisual==215) + else if(m_spellInfo->SpellVisual[0]==215) duration = 1800; // 30 mins // some fishing pole bonuses - else if(m_spellInfo->SpellVisual==563) + else if(m_spellInfo->SpellVisual[0]==563) duration = 600; // 10 mins // shaman rockbiter enchantments - else if(m_spellInfo->SpellVisual==0) + else if(m_spellInfo->SpellVisual[0]==0) duration = 1800; // 30 mins else if(m_spellInfo->Id==29702) duration = 300; // 5 mins @@ -3888,14 +3966,16 @@ void Spell::EffectTameCreature(uint32 /*i*/) creatureTarget->RemoveCorpse(); creatureTarget->SetHealth(0); // just for nice GM-mode view + uint32 level = (creatureTarget->getLevel() < (m_caster->getLevel() - 5)) ? (m_caster->getLevel() - 5) : creatureTarget->getLevel(); + // prepare visual effect for levelup - pet->SetUInt32Value(UNIT_FIELD_LEVEL,creatureTarget->getLevel()-1); + pet->SetUInt32Value(UNIT_FIELD_LEVEL, level - 1); // add to world pet->GetMap()->Add((Creature*)pet); // visual effect for levelup - pet->SetUInt32Value(UNIT_FIELD_LEVEL,creatureTarget->getLevel()); + pet->SetUInt32Value(UNIT_FIELD_LEVEL, level); // caster have pet now m_caster->SetPet(pet); @@ -4093,7 +4173,6 @@ void Spell::EffectLearnPetSpell(uint32 i) if(!learn_spellproto) return; - pet->SetTP(pet->m_TrainingPoints - pet->GetTPForSpell(learn_spellproto->Id)); pet->learnSpell(learn_spellproto->Id); pet->SavePetToDB(PET_SAVE_AS_CURRENT); @@ -4161,7 +4240,7 @@ void Spell::EffectWeaponDmg(uint32 i) spell_bonus += m_caster->CalculateDamage (OFF_ATTACK, normalized); } // Devastate bonus and sunder armor refresh - else if(m_spellInfo->SpellVisual == 671 && m_spellInfo->SpellIconID == 1508) + else if(m_spellInfo->SpellVisual[0] == 671 && m_spellInfo->SpellIconID == 1508) { customBonusDamagePercentMod = true; bonusDamagePercentMod = 0.0f; // only applied if auras found @@ -4170,11 +4249,11 @@ void Spell::EffectWeaponDmg(uint32 i) for(Unit::AuraList::const_iterator itr=list.begin();itr!=list.end();++itr) { SpellEntry const *proto = (*itr)->GetSpellProto(); - if(proto->SpellVisual == 406 && proto->SpellIconID == 565) + if(proto->SpellVisual[0] == 406 && proto->SpellIconID == 565) { int32 duration = GetSpellDuration(proto); (*itr)->SetAuraDuration(duration); - (*itr)->UpdateAuraDuration(); + (*itr)->SendAuraUpdate(false); bonusDamagePercentMod += 1.0f; // +100% } } @@ -4813,9 +4892,69 @@ void Spell::EffectScriptEffect(uint32 effIndex) break; } - } + case 51770: + { + if(!unitTarget) + return; - if( m_spellInfo->SpellFamilyName == SPELLFAMILY_PALADIN ) + unitTarget->CastSpell(unitTarget,51771,false); + break; + } + } + if( m_spellInfo->SpellFamilyName == SPELLFAMILY_HUNTER ) + { + switch(m_spellInfo->Id) + { + // Chimera Shot + case 53209: + { + uint32 spellId = 0; + int32 basePoint = 0; + Unit::AuraMap& Auras = unitTarget->GetAuras(); + for(Unit::AuraMap::iterator i = Auras.begin(); i != Auras.end(); ++i) + { + Aura *aura = (*i).second; + if (aura->GetCasterGUID() != m_caster->GetGUID()) + continue; + // Search only Serpent Sting, Viper Sting, Scorpid Sting auras + uint64 familyFlag = aura->GetSpellProto()->SpellFamilyFlags; + if (!(familyFlag & 0x000000800000C000LL)) + continue; + // Refresh aura duration + aura->SetAuraDuration(aura->GetAuraMaxDuration()); + aura->SendAuraUpdate(false); + + // Serpent Sting - Instantly deals 40% of the damage done by your Serpent Sting. + if (familyFlag & 0x0000000000004000LL && aura->GetEffIndex() == 0) + { + spellId = 53353; // 53353 Chimera Shot - Serpent + basePoint = aura->GetModifier()->m_amount * 5 * 40 / 100; + } + // Viper Sting - Instantly restores mana to you equal to 60% of the total amount drained by your Viper Sting. + if (familyFlag & 0x0000008000000000LL && aura->GetEffIndex() == 0) + { + spellId = 53358; // 53358 Chimera Shot - Viper + basePoint = aura->GetModifier()->m_amount * 4 * 60 / 100; + } + // Scorpid Sting - Attempts to Disarm the target for 10 sec. This effect cannot occur more than once per 1 minute. + if (familyFlag & 0x0000000000008000LL) + spellId = 53359; // 53359 Chimera Shot - Scorpid + // ?? nothing say in spell desc (possibly need addition check) + //if (familyFlag & 0x0000010000000000LL || // dot + // familyFlag & 0x0000100000000000LL) // stun + //{ + // spellId = 53366; // 53366 Chimera Shot - Wyvern + //} + } + if (spellId) + m_caster->CastCustomSpell(unitTarget, spellId, &basePoint, 0, 0, false); + return; + } + default: + break; + } + } + else if( m_spellInfo->SpellFamilyName == SPELLFAMILY_PALADIN ) { switch(m_spellInfo->SpellFamilyFlags) { @@ -4924,7 +5063,8 @@ void Spell::EffectDuel(uint32 i) // Players can only fight a duel with each other outside (=not inside dungeons and not in capital cities) // Don't have to check the target's map since you cannot challenge someone across maps - if( caster->GetMapId() != 0 && caster->GetMapId() != 1 && caster->GetMapId() != 530) + uint32 mapid = caster->GetMapId(); + if( mapid != 0 && mapid != 1 && mapid != 530 && mapid != 571 && mapid != 609) { SendCastResult(SPELL_FAILED_NO_DUELING); // Dueling isn't allowed here return; @@ -5063,6 +5203,45 @@ void Spell::EffectActivateObject(uint32 effect_idx) sWorld.ScriptCommandStart(activateCommand, delay_secs, m_caster, gameObjTarget); } +void Spell::EffectApplyGlyph(uint32 i) +{ + if(m_caster->GetTypeId() != TYPEID_PLAYER) + return; + + Player *player = (Player*)m_caster; + + // remove old glyph + if(uint32 oldglyph = player->GetGlyph(m_glyphIndex)) + { + if(GlyphPropertiesEntry const *old_gp = sGlyphPropertiesStore.LookupEntry(oldglyph)) + { + player->RemoveAurasDueToSpell(old_gp->SpellId); + player->SetGlyph(m_glyphIndex, 0); + } + } + + // apply new one + if(uint32 glyph = m_spellInfo->EffectMiscValue[i]) + { + if(GlyphPropertiesEntry const *gp = sGlyphPropertiesStore.LookupEntry(glyph)) + { + if(GlyphSlotEntry const *gs = sGlyphSlotStore.LookupEntry(player->GetGlyphSlot(m_glyphIndex))) + { + if(gp->TypeFlags != gs->TypeFlags) + { + SendCastResult(SPELL_FAILED_INVALID_GLYPH); + return; // glyph slot missmatch + } + } + + player->CastSpell(m_caster, gp->SpellId, true); + player->SetGlyph(m_glyphIndex, glyph); + if(m_CastItem) + player->DestroyItemCount(m_CastItem->GetEntry(), 1, true); + } + } +} + void Spell::EffectSummonTotem(uint32 i) { uint8 slot = 0; @@ -5386,18 +5565,14 @@ void Spell::EffectAddExtraAttacks(uint32 /*i*/) void Spell::EffectParry(uint32 /*i*/) { - if (unitTarget->GetTypeId() == TYPEID_PLAYER) - { + if (unitTarget && unitTarget->GetTypeId() == TYPEID_PLAYER) ((Player*)unitTarget)->SetCanParry(true); - } } void Spell::EffectBlock(uint32 /*i*/) { - if (unitTarget->GetTypeId() != TYPEID_PLAYER) - return; - - ((Player*)unitTarget)->SetCanBlock(true); + if (unitTarget && unitTarget->GetTypeId() == TYPEID_PLAYER) + ((Player*)unitTarget)->SetCanBlock(true); } void Spell::EffectMomentMove(uint32 i) @@ -5910,9 +6085,9 @@ void Spell::EffectTransmitted(uint32 effIndex) { m_caster->SetUInt64Value(UNIT_FIELD_CHANNEL_OBJECT,pGameObj->GetGUID()); // Orientation3 - pGameObj->SetFloatValue(GAMEOBJECT_ROTATION + 2, 0.88431775569915771 ); + pGameObj->SetFloatValue(GAMEOBJECT_PARENTROTATION + 2, 0.88431775569915771 ); // Orientation4 - pGameObj->SetFloatValue(GAMEOBJECT_ROTATION + 3, -0.4668855369091033 ); + pGameObj->SetFloatValue(GAMEOBJECT_PARENTROTATION + 3, -0.4668855369091033 ); m_caster->AddGameObject(pGameObj); // will removed at spell cancel // end time of range when possible catch fish (FISHING_BOBBER_READY_TIME..GetDuration(m_spellInfo)) @@ -6007,6 +6182,28 @@ void Spell::EffectProspecting(uint32 /*i*/) ((Player*)m_caster)->SendLoot(itemTarget->GetGUID(), LOOT_PROSPECTING); } +void Spell::EffectMilling(uint32 /*i*/) +{ + if(m_caster->GetTypeId() != TYPEID_PLAYER) + return; + + Player* p_caster = (Player*)m_caster; + if(!itemTarget || !(itemTarget->GetProto()->BagFamily & BAG_FAMILY_MASK_HERBS)) + return; + + if(itemTarget->GetCount() < 5) + return; + + if( sWorld.getConfig(CONFIG_SKILL_MILLING)) + { + uint32 SkillValue = p_caster->GetPureSkillValue(SKILL_INSCRIPTION); + uint32 reqSkillValue = itemTarget->GetProto()->RequiredSkillRank; + p_caster->UpdateGatherSkill(SKILL_INSCRIPTION, SkillValue, reqSkillValue); + } + + ((Player*)m_caster)->SendLoot(itemTarget->GetGUID(), LOOT_MILLING); +} + void Spell::EffectSkill(uint32 /*i*/) { sLog.outDebug("WORLD: SkillEFFECT"); @@ -6153,3 +6350,28 @@ void Spell::EffectQuestFail(uint32 i) ((Player*)unitTarget)->FailQuest(m_spellInfo->EffectMiscValue[i]); } + +void Spell::EffectActivateRune(uint32 i) +{ + if(m_caster->GetTypeId() != TYPEID_PLAYER) + return; + + Player *plr = (Player*)m_caster; + + if(plr->getClass() != CLASS_DEATH_KNIGHT) + return; + + for(uint32 j = 0; j < MAX_RUNES; ++j) + { + if(plr->GetRuneCooldown(j) && plr->GetCurrentRune(j) == m_spellInfo->EffectMiscValue[i]) + { + plr->SetRuneCooldown(j, 0); + } + } +} + +void Spell::EffectTitanGrip(uint32 i) +{ + if (unitTarget && unitTarget->GetTypeId() == TYPEID_PLAYER) + ((Player*)unitTarget)->SetCanTitanGrip(true); +} diff --git a/src/game/SpellHandler.cpp b/src/game/SpellHandler.cpp index de379d91e..8a4a2f60a 100644 --- a/src/game/SpellHandler.cpp +++ b/src/game/SpellHandler.cpp @@ -35,15 +35,17 @@ void WorldSession::HandleUseItemOpcode(WorldPacket& recvPacket) { // TODO: add targets.read() check - CHECK_PACKET_SIZE(recvPacket,1+1+1+1+8); + CHECK_PACKET_SIZE(recvPacket,1+1+1+4+8+4+1); Player* pUser = _player; uint8 bagIndex, slot; - uint8 spell_count; // number of spells at item, not used + uint8 unk_flags; // flags (if 0x02 - some additional data are received) uint8 cast_count; // next cast if exists (single or not) uint64 item_guid; + uint32 glyphIndex; // something to do with glyphs? + uint32 spellid; // casted spell id - recvPacket >> bagIndex >> slot >> spell_count >> cast_count >> item_guid; + recvPacket >> bagIndex >> slot >> cast_count >> spellid >> item_guid >> glyphIndex >> unk_flags; Item *pItem = pUser->GetItemByPos(bagIndex, slot); if(!pItem) @@ -58,7 +60,7 @@ void WorldSession::HandleUseItemOpcode(WorldPacket& recvPacket) return; } - sLog.outDetail("WORLD: CMSG_USE_ITEM packet, bagIndex: %u, slot: %u, spell_count: %u , cast_count: %u, Item: %u, data length = %i", bagIndex, slot, spell_count, cast_count, pItem->GetEntry(), recvPacket.size()); + sLog.outDetail("WORLD: CMSG_USE_ITEM packet, bagIndex: %u, slot: %u, cast_count: %u, spellid: %u, Item: %u, glyphIndex: %u, unk_flags: %u, data length = %i", bagIndex, slot, cast_count, spellid, pItem->GetEntry(), glyphIndex, unk_flags, recvPacket.size()); ItemPrototype const *proto = pItem->GetProto(); if(!proto) @@ -125,14 +127,15 @@ void WorldSession::HandleUseItemOpcode(WorldPacket& recvPacket) // no script or script not process request by self // special learning case - if(pItem->GetProto()->Spells[0].SpellId==SPELL_ID_GENERIC_LEARN) + if((pItem->GetProto()->Spells[0].SpellId==SPELL_ID_GENERIC_LEARN) || (pItem->GetProto()->Spells[0].SpellId==SPELL_ID_GENERIC_LEARN_PET)) { + uint32 learn_spell_id = pItem->GetProto()->Spells[0].SpellId; uint32 learning_spell_id = pItem->GetProto()->Spells[1].SpellId; - SpellEntry const *spellInfo = sSpellStore.LookupEntry(SPELL_ID_GENERIC_LEARN); + SpellEntry const *spellInfo = sSpellStore.LookupEntry(learn_spell_id); if(!spellInfo) { - sLog.outError("Item (Entry: %u) in have wrong spell id %u, ignoring ",proto->ItemId, SPELL_ID_GENERIC_LEARN); + sLog.outError("Item (Entry: %u) in have wrong spell id %u, ignoring ",proto->ItemId, learn_spell_id); pUser->SendEquipError(EQUIP_ERR_NONE,pItem,NULL); return; } @@ -169,7 +172,8 @@ void WorldSession::HandleUseItemOpcode(WorldPacket& recvPacket) Spell *spell = new Spell(pUser, spellInfo, (count > 0)); spell->m_CastItem = pItem; - spell->m_cast_count = cast_count; //set count of casts + spell->m_cast_count = cast_count; // set count of casts + spell->m_glyphIndex = glyphIndex; // glyph index spell->prepare(&targets); ++count; @@ -224,7 +228,7 @@ void WorldSession::HandleOpenItemOpcode(WorldPacket& recvPacket) } // required picklocking - if(lockInfo->requiredlockskill || lockInfo->requiredminingskill) + if(lockInfo->Skill[1] || lockInfo->Skill[0]) { pUser->SendEquipError(EQUIP_ERR_ITEM_LOCKED, pItem, NULL ); return; @@ -280,15 +284,16 @@ void WorldSession::HandleGameObjectUseOpcode( WorldPacket & recv_data ) void WorldSession::HandleCastSpellOpcode(WorldPacket& recvPacket) { - CHECK_PACKET_SIZE(recvPacket,4+1+2); + CHECK_PACKET_SIZE(recvPacket,1+4+1); uint32 spellId; - uint8 cast_count; - recvPacket >> spellId; + uint8 cast_count, unk_flags; recvPacket >> cast_count; + recvPacket >> spellId; + recvPacket >> unk_flags; // flags (if 0x02 - some additional data are received) - sLog.outDebug("WORLD: got cast spell packet, spellId - %u, cast_count: %u data length = %i", - spellId, cast_count, recvPacket.size()); + sLog.outDebug("WORLD: got cast spell packet, spellId - %u, cast_count: %u, unk_flags %u, data length = %i", + spellId, cast_count, unk_flags, recvPacket.size()); SpellEntry const *spellInfo = sSpellStore.LookupEntry(spellId ); @@ -327,9 +332,12 @@ void WorldSession::HandleCastSpellOpcode(WorldPacket& recvPacket) void WorldSession::HandleCancelCastOpcode(WorldPacket& recvPacket) { - CHECK_PACKET_SIZE(recvPacket,4); + CHECK_PACKET_SIZE(recvPacket,5); + // increments with every CANCEL packet, don't use for now + uint8 counter; uint32 spellId; + recvPacket >> counter; recvPacket >> spellId; //FIXME: hack, ignore unexpected client cancel Deadly Throw cast diff --git a/src/game/SpellMgr.cpp b/src/game/SpellMgr.cpp index 3f43a7531..e25901233 100644 --- a/src/game/SpellMgr.cpp +++ b/src/game/SpellMgr.cpp @@ -182,10 +182,10 @@ SpellSpecific GetSpellSpecific(uint32 spellId) if ((spellInfo->SpellFamilyFlags & 0x00000820180400LL) && (spellInfo->AttributesEx3 & 0x200)) return SPELL_JUDGEMENT; - for (int i = 0; i < 3; i++) + for (int i = 0; i < 3; i++) // TODO: fix it for WotLK!!! { // only paladin auras have this - if (spellInfo->Effect[i] == SPELL_EFFECT_APPLY_AREA_AURA_PARTY) + if (spellInfo->Effect[i] == SPELL_EFFECT_APPLY_AREA_AURA_RAID) return SPELL_AURA; } break; @@ -203,7 +203,7 @@ SpellSpecific GetSpellSpecific(uint32 spellId) } // only warlock armor/skin have this (in additional to family cases) - if( spellInfo->SpellVisual == 130 && spellInfo->SpellIconID == 89) + if( spellInfo->SpellVisual[0] == 130 && spellInfo->SpellIconID == 89) { return SPELL_WARLOCK_ARMOR; } @@ -677,8 +677,8 @@ void SpellMgr::LoadSpellAffects() uint32 count = 0; - // 0 1 2 - QueryResult *result = WorldDatabase.Query("SELECT entry, effectId, SpellFamilyMask FROM spell_affect"); + // 0 1 2 3 4 + QueryResult *result = WorldDatabase.Query("SELECT entry, effectId, SpellClassMask0, SpellClassMask1, SpellClassMask2 FROM spell_affect"); if( !result ) { @@ -725,26 +725,29 @@ void SpellMgr::LoadSpellAffects() continue; } - uint64 spellAffectMask = fields[2].GetUInt64(); + SpellAffectEntry affect; + affect.SpellClassMask[0] = fields[2].GetUInt32(); + affect.SpellClassMask[1] = fields[3].GetUInt32(); + affect.SpellClassMask[2] = fields[4].GetUInt32(); - // Spell.dbc have own data for low part of SpellFamilyMask - if( spellInfo->EffectItemType[effectId]) + // Spell.dbc have own data + uint32 const *ptr = 0; + switch (effectId) { - if(spellInfo->EffectItemType[effectId] == spellAffectMask) - { - sLog.outErrorDb("Spell %u listed in `spell_affect` have redundant (same with EffectItemType%d) data for effect index (%u) and not needed, skipped.", entry,effectId+1,effectId); + case 0: ptr = &spellInfo->EffectSpellClassMaskA[0]; break; + case 1: ptr = &spellInfo->EffectSpellClassMaskB[0]; break; + case 2: ptr = &spellInfo->EffectSpellClassMaskC[0]; break; + default: continue; - } - - // 24429 have wrong data in EffectItemType and overwrites by DB, possible bug in client - if(spellInfo->Id!=24429 && spellInfo->EffectItemType[effectId] != spellAffectMask) - { - sLog.outErrorDb("Spell %u listed in `spell_affect` have different low part from EffectItemType%d for effect index (%u) and not needed, skipped.", entry,effectId+1,effectId); - continue; - } + } + if(ptr[0] == affect.SpellClassMask[0] || ptr[1] == affect.SpellClassMask[1] || ptr[2] == affect.SpellClassMask[2]) + { + char text[]="ABC"; + sLog.outErrorDb("Spell %u listed in `spell_affect` have redundant (same with EffectSpellClassMask%c) data for effect index (%u) and not needed, skipped.", entry, text[effectId], effectId); + continue; } - mSpellAffectMap.insert(SpellAffectMap::value_type((entry<<8) + effectId,spellAffectMask)); + mSpellAffectMap[(entry<<8) + effectId] = affect; ++count; } while( result->NextRow() ); @@ -752,7 +755,7 @@ void SpellMgr::LoadSpellAffects() delete result; sLog.outString(); - sLog.outString( ">> Loaded %u spell affect definitions", count ); + sLog.outString( ">> Loaded %u custom spell affect definitions", count ); for (uint32 id = 0; id < sSpellStore.GetNumRows(); ++id) { @@ -768,7 +771,16 @@ void SpellMgr::LoadSpellAffects() spellInfo->EffectApplyAuraName[effectId] != SPELL_AURA_ADD_TARGET_TRIGGER) ) continue; - if(spellInfo->EffectItemType[effectId] != 0) + uint32 const *ptr = 0; + switch (effectId) + { + case 0: ptr = &spellInfo->EffectSpellClassMaskA[0]; break; + case 1: ptr = &spellInfo->EffectSpellClassMaskB[0]; break; + case 2: ptr = &spellInfo->EffectSpellClassMaskC[0]; break; + default: + continue; + } + if(ptr[0] || ptr[1] || ptr[2]) continue; if(mSpellAffectMap.find((id<<8) + effectId) != mSpellAffectMap.end()) @@ -779,33 +791,20 @@ void SpellMgr::LoadSpellAffects() } } -bool SpellMgr::IsAffectedBySpell(SpellEntry const *spellInfo, uint32 spellId, uint8 effectId, uint64 familyFlags) const +bool SpellMgr::IsAffectedByMod(SpellEntry const *spellInfo, SpellModifier *mod) const { // false for spellInfo == NULL - if (!spellInfo) + if (!spellInfo || !mod) return false; - SpellEntry const *affect_spell = sSpellStore.LookupEntry(spellId); - // false for affect_spell == NULL - if (!affect_spell) + SpellEntry const *affect_spell = sSpellStore.LookupEntry(mod->spellId); + // False if affect_spell == NULL or spellFamily not equal + if (!affect_spell || affect_spell->SpellFamilyName != spellInfo->SpellFamilyName) return false; - // False if spellFamily not equal - if (affect_spell->SpellFamilyName != spellInfo->SpellFamilyName) - return false; - - // If familyFlags == 0 - if (!familyFlags) - { - // Get it from spellAffect table - familyFlags = GetSpellAffectMask(spellId,effectId); - // false if familyFlags == 0 - if (!familyFlags) - return false; - } - // true - if (familyFlags & spellInfo->SpellFamilyFlags) + if (mod->mask & spellInfo->SpellFamilyFlags || + mod->mask2 & spellInfo->SpellFamilyFlags2) return true; return false; @@ -1099,7 +1098,7 @@ bool SpellMgr::canStackSpellRanks(SpellEntry const *spellInfo) { // Paladin aura Spell if(spellInfo->SpellFamilyName == SPELLFAMILY_PALADIN - && spellInfo->Effect[i]==SPELL_EFFECT_APPLY_AREA_AURA_PARTY) + && spellInfo->Effect[i]==SPELL_EFFECT_APPLY_AREA_AURA_RAID) return false; // Druid form Spell if(spellInfo->SpellFamilyName == SPELLFAMILY_DRUID @@ -1154,14 +1153,14 @@ bool SpellMgr::IsNoStackSpellDueToSpell(uint32 spellId_1, uint32 spellId_2) cons // Soulstone Resurrection and Twisting Nether (resurrector) if( spellInfo_1->SpellIconID == 92 && spellInfo_2->SpellIconID == 92 && ( - spellInfo_1->SpellVisual == 99 && spellInfo_2->SpellVisual == 0 || - spellInfo_2->SpellVisual == 99 && spellInfo_1->SpellVisual == 0 ) ) + spellInfo_1->SpellVisual[0] == 99 && spellInfo_2->SpellVisual[0] == 0 || + spellInfo_2->SpellVisual[0] == 99 && spellInfo_1->SpellVisual[0] == 0 ) ) return false; // Heart of the Wild and (Primal Instinct (Idol of Terror) triggering spell or Agility) if( spellInfo_1->SpellIconID == 240 && spellInfo_2->SpellIconID == 240 && ( - spellInfo_1->SpellVisual == 0 && spellInfo_2->SpellVisual == 78 || - spellInfo_2->SpellVisual == 0 && spellInfo_1->SpellVisual == 78 ) ) + spellInfo_1->SpellVisual[0] == 0 && spellInfo_2->SpellVisual[0] == 78 || + spellInfo_2->SpellVisual[0] == 0 && spellInfo_1->SpellVisual[0] == 78 ) ) return false; // Personalized Weather (thunder effect should overwrite rainy aura) @@ -1178,7 +1177,7 @@ bool SpellMgr::IsNoStackSpellDueToSpell(uint32 spellId_1, uint32 spellId_2) cons case SPELLFAMILY_WARRIOR: { // Scroll of Protection and Defensive Stance (multi-family check) - if( spellInfo_1->SpellIconID == 276 && spellInfo_1->SpellVisual == 196 && spellInfo_2->Id == 71) + if( spellInfo_1->SpellIconID == 276 && spellInfo_1->SpellVisual[0] == 196 && spellInfo_2->Id == 71) return false; // Improved Hamstring -> Hamstring (multi-family check) @@ -1190,7 +1189,7 @@ bool SpellMgr::IsNoStackSpellDueToSpell(uint32 spellId_1, uint32 spellId_2) cons case SPELLFAMILY_DRUID: { // Scroll of Stamina and Leader of the Pack (multi-family check) - if( spellInfo_1->SpellIconID == 312 && spellInfo_1->SpellVisual == 216 && spellInfo_2->Id == 24932 ) + if( spellInfo_1->SpellIconID == 312 && spellInfo_1->SpellVisual[0] == 216 && spellInfo_2->Id == 24932 ) return false; // Dragonmaw Illusion (multi-family check) @@ -1221,11 +1220,11 @@ bool SpellMgr::IsNoStackSpellDueToSpell(uint32 spellId_1, uint32 spellId_2) cons case SPELLFAMILY_PALADIN: { // Unstable Currents and other -> *Sanctity Aura (multi-family check) - if( spellInfo_2->SpellIconID==502 && spellInfo_1->SpellIconID==502 && spellInfo_1->SpellVisual==969 ) + if( spellInfo_2->SpellIconID==502 && spellInfo_1->SpellIconID==502 && spellInfo_1->SpellVisual[0]==969 ) return false; // *Band of Eternal Champion and Seal of Command(multi-family check) - if( spellId_1 == 35081 && spellInfo_2->SpellIconID==561 && spellInfo_2->SpellVisual==7992) + if( spellId_1 == 35081 && spellInfo_2->SpellIconID==561 && spellInfo_2->SpellVisual[0]==7992) return false; break; @@ -1241,16 +1240,16 @@ bool SpellMgr::IsNoStackSpellDueToSpell(uint32 spellId_1, uint32 spellId_2) cons return false; // Blink & Improved Blink - if( (spellInfo_1->SpellFamilyFlags & 0x0000000000010000LL) && (spellInfo_2->SpellVisual == 72 && spellInfo_2->SpellIconID == 1499) || - (spellInfo_2->SpellFamilyFlags & 0x0000000000010000LL) && (spellInfo_1->SpellVisual == 72 && spellInfo_1->SpellIconID == 1499) ) + if( (spellInfo_1->SpellFamilyFlags & 0x0000000000010000LL) && (spellInfo_2->SpellVisual[0] == 72 && spellInfo_2->SpellIconID == 1499) || + (spellInfo_2->SpellFamilyFlags & 0x0000000000010000LL) && (spellInfo_1->SpellVisual[0] == 72 && spellInfo_1->SpellIconID == 1499) ) return false; } // Detect Invisibility and Mana Shield (multi-family check) - if( spellInfo_2->Id == 132 && spellInfo_1->SpellIconID == 209 && spellInfo_1->SpellVisual == 968 ) + if( spellInfo_2->Id == 132 && spellInfo_1->SpellIconID == 209 && spellInfo_1->SpellVisual[0] == 968 ) return false; // Combustion and Fire Protection Aura (multi-family check) - if( spellInfo_1->Id == 11129 && spellInfo_2->SpellIconID == 33 && spellInfo_2->SpellVisual == 321 ) + if( spellInfo_1->Id == 11129 && spellInfo_2->SpellIconID == 33 && spellInfo_2->SpellVisual[0] == 321 ) return false; break; @@ -1279,7 +1278,7 @@ bool SpellMgr::IsNoStackSpellDueToSpell(uint32 spellId_1, uint32 spellId_2) cons return false; } // Detect Invisibility and Mana Shield (multi-family check) - if( spellInfo_1->Id == 132 && spellInfo_2->SpellIconID == 209 && spellInfo_2->SpellVisual == 968 ) + if( spellInfo_1->Id == 132 && spellInfo_2->SpellIconID == 209 && spellInfo_2->SpellVisual[0] == 968 ) return false; break; case SPELLFAMILY_WARRIOR: @@ -1301,11 +1300,11 @@ bool SpellMgr::IsNoStackSpellDueToSpell(uint32 spellId_1, uint32 spellId_2) cons return false; // Defensive Stance and Scroll of Protection (multi-family check) - if( spellInfo_1->Id == 71 && spellInfo_2->SpellIconID == 276 && spellInfo_2->SpellVisual == 196 ) + if( spellInfo_1->Id == 71 && spellInfo_2->SpellIconID == 276 && spellInfo_2->SpellVisual[0] == 196 ) return false; // Bloodlust and Bloodthirst (multi-family check) - if( spellInfo_2->Id == 2825 && spellInfo_1->SpellIconID == 38 && spellInfo_1->SpellVisual == 0 ) + if( spellInfo_2->Id == 2825 && spellInfo_1->SpellIconID == 38 && spellInfo_1->SpellVisual[0] == 0 ) return false; break; @@ -1350,7 +1349,7 @@ bool SpellMgr::IsNoStackSpellDueToSpell(uint32 spellId_1, uint32 spellId_2) cons } // Leader of the Pack and Scroll of Stamina (multi-family check) - if( spellInfo_1->Id == 24932 && spellInfo_2->SpellIconID == 312 && spellInfo_2->SpellVisual == 216 ) + if( spellInfo_1->Id == 24932 && spellInfo_2->SpellIconID == 312 && spellInfo_2->SpellVisual[0] == 216 ) return false; // Dragonmaw Illusion (multi-family check) @@ -1367,7 +1366,7 @@ bool SpellMgr::IsNoStackSpellDueToSpell(uint32 spellId_1, uint32 spellId_2) cons } // Garrote -> Garrote-Silence (multi-family check) - if( spellInfo_1->SpellIconID == 498 && spellInfo_2->SpellIconID == 498 && spellInfo_2->SpellVisual == 0 ) + if( spellInfo_1->SpellIconID == 498 && spellInfo_2->SpellIconID == 498 && spellInfo_2->SpellVisual[0] == 0 ) return false; break; case SPELLFAMILY_HUNTER: @@ -1404,15 +1403,15 @@ bool SpellMgr::IsNoStackSpellDueToSpell(uint32 spellId_1, uint32 spellId_2) cons return true; } // Combustion and Fire Protection Aura (multi-family check) - if( spellInfo_2->Id == 11129 && spellInfo_1->SpellIconID == 33 && spellInfo_1->SpellVisual == 321 ) + if( spellInfo_2->Id == 11129 && spellInfo_1->SpellIconID == 33 && spellInfo_1->SpellVisual[0] == 321 ) return false; // *Sanctity Aura -> Unstable Currents and other (multi-family check) - if( spellInfo_1->SpellIconID==502 && spellInfo_2->SpellFamilyName == SPELLFAMILY_GENERIC && spellInfo_2->SpellIconID==502 && spellInfo_2->SpellVisual==969 ) + if( spellInfo_1->SpellIconID==502 && spellInfo_2->SpellFamilyName == SPELLFAMILY_GENERIC && spellInfo_2->SpellIconID==502 && spellInfo_2->SpellVisual[0]==969 ) return false; // *Seal of Command and Band of Eternal Champion (multi-family check) - if( spellInfo_1->SpellIconID==561 && spellInfo_1->SpellVisual==7992 && spellId_2 == 35081) + if( spellInfo_1->SpellIconID==561 && spellInfo_1->SpellVisual[0]==7992 && spellId_2 == 35081) return false; break; case SPELLFAMILY_SHAMAN: @@ -1428,7 +1427,7 @@ bool SpellMgr::IsNoStackSpellDueToSpell(uint32 spellId_1, uint32 spellId_2) cons return false; } // Bloodlust and Bloodthirst (multi-family check) - if( spellInfo_1->Id == 2825 && spellInfo_2->SpellIconID == 38 && spellInfo_2->SpellVisual == 0 ) + if( spellInfo_1->Id == 2825 && spellInfo_2->SpellIconID == 38 && spellInfo_2->SpellVisual[0] == 0 ) return false; break; default: @@ -1516,7 +1515,8 @@ SpellEntry const* SpellMgr::SelectAuraRankForPlayerLevel(SpellEntry const* spell { if( IsPositiveEffect(spellInfo->Id, i) && ( spellInfo->Effect[i] == SPELL_EFFECT_APPLY_AURA || - spellInfo->Effect[i] == SPELL_EFFECT_APPLY_AREA_AURA_PARTY + spellInfo->Effect[i] == SPELL_EFFECT_APPLY_AREA_AURA_PARTY || + spellInfo->Effect[i] == SPELL_EFFECT_APPLY_AREA_AURA_RAID ) ) { needRankSelection = true; @@ -1641,12 +1641,12 @@ void SpellMgr::LoadSpellChains() continue; } - if(node.req!=talentEntry->DependsOnSpell) + /*if(node.req!=talentEntry->DependsOnSpell) { sLog.outErrorDb("Talent %u (prev: %u, first: %u, rank: %d, req: %u) listed in `spell_chain` has wrong required spell.", spell_id,node.prev,node.first,node.rank,node.req); continue; - } + }*/ } } @@ -2058,7 +2058,187 @@ void SpellMgr::LoadSpellPetAuras() sLog.outString( ">> Loaded %u spell pet auras", count ); } -/// Some checks for spells, to prevent adding depricated/broken spells for trainers, spell book, etc +void SpellMgr::LoadPetLevelupSpellMap() +{ + CreatureFamilyEntry const *creatureFamily; + SpellEntry const *spell; + uint32 count = 0; + + for (uint32 i = 0; i < sCreatureFamilyStore.GetNumRows(); ++i) + { + creatureFamily = sCreatureFamilyStore.LookupEntry(i); + + if(!creatureFamily) // not exist + continue; + + if(creatureFamily->petTalentType < 0) // not hunter pet family + continue; + + for(uint32 j = 0; j < sSpellStore.GetNumRows(); ++j) + { + spell = sSpellStore.LookupEntry(j); + + // not exist + if(!spell) + continue; + + // not hunter spell + if(spell->SpellFamilyName != SPELLFAMILY_HUNTER) + continue; + + // not pet spell + if(!(spell->SpellFamilyFlags & 0x1000000000000000LL)) + continue; + + // not Growl or Cower (generics) + if(spell->SpellIconID != 201 && spell->SpellIconID != 958) + { + switch(creatureFamily->ID) + { + case CREATURE_FAMILY_BAT: // Bite and Sonic Blast + if(spell->SpellIconID != 1680 && spell->SpellIconID != 1577) + continue; + break; + case CREATURE_FAMILY_BEAR: // Claw and Swipe + if(spell->SpellIconID != 262 && spell->SpellIconID != 1562) + continue; + break; + case CREATURE_FAMILY_BIRD_OF_PREY: // Claw and Snatch + if(spell->SpellIconID != 262 && spell->SpellIconID != 168) + continue; + break; + case CREATURE_FAMILY_BOAR: // Bite and Gore + if(spell->SpellIconID != 1680 && spell->SpellIconID != 1578) + continue; + break; + case CREATURE_FAMILY_CARRION_BIRD: // Bite and Demoralizing Screech + if(spell->SpellIconID != 1680 && spell->SpellIconID != 1579) + continue; + break; + case CREATURE_FAMILY_CAT: // Claw and Prowl and Rake + if(spell->SpellIconID != 262 && spell->SpellIconID != 495 && spell->SpellIconID != 494) + continue; + break; + case CREATURE_FAMILY_CHIMAERA: // Bite and Froststorm Breath + if(spell->SpellIconID != 1680 && spell->SpellIconID != 62) + continue; + break; + case CREATURE_FAMILY_CORE_HOUND: // Bite and Lava Breath + if(spell->SpellIconID != 1680 && spell->SpellIconID != 1197) + continue; + break; + case CREATURE_FAMILY_CRAB: // Claw and Pin + if(spell->SpellIconID != 262 && spell->SpellIconID != 2679) + continue; + break; + case CREATURE_FAMILY_CROCOLISK: // Bite and Bad Attitude + if(spell->SpellIconID != 1680 && spell->SpellIconID != 1581) + continue; + break; + case CREATURE_FAMILY_DEVILSAUR: // Bite and Monstrous Bite + if(spell->SpellIconID != 1680 && spell->SpellIconID != 599) + continue; + break; + case CREATURE_FAMILY_DRAGONHAWK: // Bite and Fire Breath + if(spell->SpellIconID != 1680 && spell->SpellIconID != 2128) + continue; + break; + case CREATURE_FAMILY_GORILLA: // Smack and Thunderstomp + if(spell->SpellIconID != 473 && spell->SpellIconID != 148) + continue; + break; + case CREATURE_FAMILY_HYENA: // Bite and Tendon Rip + if(spell->SpellIconID != 1680 && spell->SpellIconID != 138) + continue; + break; + case CREATURE_FAMILY_MOTH: // Serenity Dust and Smack + if(spell->SpellIconID != 1714 && spell->SpellIconID != 473) + continue; + break; + case CREATURE_FAMILY_NETHER_RAY: // Bite and Nether Shock + if(spell->SpellIconID != 1680 && spell->SpellIconID != 2027) + continue; + break; + case CREATURE_FAMILY_RAPTOR: // Claw and Savage Rend + if(spell->SpellIconID != 262 && spell->SpellIconID != 245) + continue; + break; + case CREATURE_FAMILY_RAVAGER: // Bite and Ravage + if(spell->SpellIconID != 1680 && spell->SpellIconID != 2253) + continue; + break; + case CREATURE_FAMILY_RHINO: // Smack and Stampede + if(spell->SpellIconID != 473 && spell->SpellIconID != 3066) + continue; + break; + case CREATURE_FAMILY_SCORPID: // Claw and Scorpid Poison + if(spell->SpellIconID != 262 && spell->SpellIconID != 163) + continue; + break; + case CREATURE_FAMILY_SERPENT: // Bite and Poison Spit + if(spell->SpellIconID != 1680 && spell->SpellIconID != 68) + continue; + break; + case CREATURE_FAMILY_SILITHID: // Claw and Venom Web Spray + if(spell->SpellIconID != 262 && (spell->SpellIconID != 272 && spell->SpellVisual[0] != 12013)) + continue; + break; + case CREATURE_FAMILY_SPIDER: // Bite and Web + if(spell->SpellIconID != 1680 && (spell->SpellIconID != 272 && spell->SpellVisual[0] != 684)) + continue; + break; + case CREATURE_FAMILY_SPIRIT_BEAST: // Claw and Prowl and Spirit Strike + if(spell->SpellIconID != 262 && spell->SpellIconID != 495 && spell->SpellIconID != 255) + continue; + break; + case CREATURE_FAMILY_SPOREBAT: // Smack and Spore Cloud + if(spell->SpellIconID != 473 && spell->SpellIconID != 2681) + continue; + break; + case CREATURE_FAMILY_TALLSTRIDER: // Claw and Dust Cloud + if(spell->SpellIconID != 262 && (spell->SpellIconID != 157 && !(spell->Attributes & 0x4000000))) + continue; + break; + case CREATURE_FAMILY_TURTLE: // Bite and Shell Shield + if(spell->SpellIconID != 1680 && spell->SpellIconID != 1588) + continue; + break; + case CREATURE_FAMILY_WARP_STALKER: // Bite and Warp + if(spell->SpellIconID != 1680 && spell->SpellIconID != 1952) + continue; + break; + case CREATURE_FAMILY_WASP: // Smack and Sting + if(spell->SpellIconID != 473 && spell->SpellIconID != 110) + continue; + break; + case CREATURE_FAMILY_WIND_SERPENT: // Bite and Lightning Breath + if(spell->SpellIconID != 1680 && spell->SpellIconID != 62) + continue; + break; + case CREATURE_FAMILY_WOLF: // Bite and Furious Howl + if(spell->SpellIconID != 1680 && spell->SpellIconID != 1573) + continue; + break; + case CREATURE_FAMILY_WORM: // Acid Spit and Bite + if(spell->SpellIconID != 636 && spell->SpellIconID != 1680) + continue; + break; + default: + sLog.outError("LoadPetLevelupSpellMap: Unhandled creature family %u", creatureFamily->ID); + continue; + } + } + + mPetLevelupSpellMap[creatureFamily->ID][spell->spellLevel] = spell->Id; + count++; + } + } + + sLog.outString(); + sLog.outString( ">> Loaded %u pet levelup spells", count ); +} + +/// Some checks for spells, to prevent adding deprecated/broken spells for trainers, spell book, etc bool SpellMgr::IsSpellValid(SpellEntry const* spellInfo, Player* pl, bool msg) { // not exist @@ -2095,15 +2275,15 @@ bool SpellMgr::IsSpellValid(SpellEntry const* spellInfo, Player* pl, bool msg) } case SPELL_EFFECT_LEARN_SPELL: { - SpellEntry const* spellInfo2 = sSpellStore.LookupEntry(spellInfo->EffectTriggerSpell[0]); + SpellEntry const* spellInfo2 = sSpellStore.LookupEntry(spellInfo->EffectTriggerSpell[i]); if( !IsSpellValid(spellInfo2,pl,msg) ) { if(msg) { if(pl) - ChatHandler(pl).PSendSysMessage("Spell %u learn to broken spell %u, and then...",spellInfo->Id,spellInfo->EffectTriggerSpell[0]); + ChatHandler(pl).PSendSysMessage("Spell %u learn to broken spell %u, and then...",spellInfo->Id,spellInfo->EffectTriggerSpell[i]); else - sLog.outErrorDb("Spell %u learn to invalid spell %u, and then...",spellInfo->Id,spellInfo->EffectTriggerSpell[0]); + sLog.outErrorDb("Spell %u learn to invalid spell %u, and then...",spellInfo->Id,spellInfo->EffectTriggerSpell[i]); } return false; } @@ -2136,7 +2316,7 @@ bool SpellMgr::IsSpellValid(SpellEntry const* spellInfo, Player* pl, bool msg) bool IsSpellAllowedInLocation(SpellEntry const *spellInfo,uint32 map_id,uint32 zone_id,uint32 area_id) { // normal case - if( spellInfo->AreaId && spellInfo->AreaId != zone_id && spellInfo->AreaId != area_id ) + if( spellInfo->AreaId > 0 && spellInfo->AreaId != zone_id && spellInfo->AreaId != area_id ) return false; // elixirs (all area dependent elixirs have family SPELLFAMILY_POTION, use this for speedup) diff --git a/src/game/SpellMgr.h b/src/game/SpellMgr.h index c996ac448..2839c1dcc 100644 --- a/src/game/SpellMgr.h +++ b/src/game/SpellMgr.h @@ -27,6 +27,9 @@ #include "Database/SQLStorage.h" #include "Utilities/UnorderedMap.h" + +#include "Player.h" + #include class Player; @@ -36,175 +39,188 @@ extern SQLStorage sSpellThreatStore; enum SpellFailedReason { - SPELL_FAILED_AFFECTING_COMBAT = 0x00, - SPELL_FAILED_ALREADY_AT_FULL_HEALTH = 0x01, - SPELL_FAILED_ALREADY_AT_FULL_MANA = 0x02, - SPELL_FAILED_ALREADY_AT_FULL_POWER = 0x03, - SPELL_FAILED_ALREADY_BEING_TAMED = 0x04, - SPELL_FAILED_ALREADY_HAVE_CHARM = 0x05, - SPELL_FAILED_ALREADY_HAVE_SUMMON = 0x06, - SPELL_FAILED_ALREADY_OPEN = 0x07, - SPELL_FAILED_AURA_BOUNCED = 0x08, - SPELL_FAILED_AUTOTRACK_INTERRUPTED = 0x09, - SPELL_FAILED_BAD_IMPLICIT_TARGETS = 0x0A, - SPELL_FAILED_BAD_TARGETS = 0x0B, - SPELL_FAILED_CANT_BE_CHARMED = 0x0C, - SPELL_FAILED_CANT_BE_DISENCHANTED = 0x0D, - SPELL_FAILED_CANT_BE_DISENCHANTED_SKILL = 0x0E, - SPELL_FAILED_CANT_BE_PROSPECTED = 0x0F, - SPELL_FAILED_CANT_CAST_ON_TAPPED = 0x10, - SPELL_FAILED_CANT_DUEL_WHILE_INVISIBLE = 0x11, - SPELL_FAILED_CANT_DUEL_WHILE_STEALTHED = 0x12, - SPELL_FAILED_CANT_STEALTH = 0x13, - SPELL_FAILED_CASTER_AURASTATE = 0x14, - SPELL_FAILED_CASTER_DEAD = 0x15, - SPELL_FAILED_CHARMED = 0x16, - SPELL_FAILED_CHEST_IN_USE = 0x17, - SPELL_FAILED_CONFUSED = 0x18, - SPELL_FAILED_DONT_REPORT = 0x19, - SPELL_FAILED_EQUIPPED_ITEM = 0x1A, - SPELL_FAILED_EQUIPPED_ITEM_CLASS = 0x1B, - SPELL_FAILED_EQUIPPED_ITEM_CLASS_MAINHAND = 0x1C, - SPELL_FAILED_EQUIPPED_ITEM_CLASS_OFFHAND = 0x1D, - SPELL_FAILED_ERROR = 0x1E, - SPELL_FAILED_FIZZLE = 0x1F, - SPELL_FAILED_FLEEING = 0x20, - SPELL_FAILED_FOOD_LOWLEVEL = 0x21, - SPELL_FAILED_HIGHLEVEL = 0x22, - SPELL_FAILED_HUNGER_SATIATED = 0x23, - SPELL_FAILED_IMMUNE = 0x24, - SPELL_FAILED_INTERRUPTED = 0x25, - SPELL_FAILED_INTERRUPTED_COMBAT = 0x26, - SPELL_FAILED_ITEM_ALREADY_ENCHANTED = 0x27, - SPELL_FAILED_ITEM_GONE = 0x28, - SPELL_FAILED_ITEM_NOT_FOUND = 0x29, - SPELL_FAILED_ITEM_NOT_READY = 0x2A, - SPELL_FAILED_LEVEL_REQUIREMENT = 0x2B, - SPELL_FAILED_LINE_OF_SIGHT = 0x2C, - SPELL_FAILED_LOWLEVEL = 0x2D, - SPELL_FAILED_LOW_CASTLEVEL = 0x2E, - SPELL_FAILED_MAINHAND_EMPTY = 0x2F, - SPELL_FAILED_MOVING = 0x30, - SPELL_FAILED_NEED_AMMO = 0x31, - SPELL_FAILED_NEED_AMMO_POUCH = 0x32, - SPELL_FAILED_NEED_EXOTIC_AMMO = 0x33, - SPELL_FAILED_NOPATH = 0x34, - SPELL_FAILED_NOT_BEHIND = 0x35, - SPELL_FAILED_NOT_FISHABLE = 0x36, - SPELL_FAILED_NOT_FLYING = 0x37, - SPELL_FAILED_NOT_HERE = 0x38, - SPELL_FAILED_NOT_INFRONT = 0x39, - SPELL_FAILED_NOT_IN_CONTROL = 0x3A, - SPELL_FAILED_NOT_KNOWN = 0x3B, - SPELL_FAILED_NOT_MOUNTED = 0x3C, - SPELL_FAILED_NOT_ON_TAXI = 0x3D, - SPELL_FAILED_NOT_ON_TRANSPORT = 0x3E, - SPELL_FAILED_NOT_READY = 0x3F, - SPELL_FAILED_NOT_SHAPESHIFT = 0x40, - SPELL_FAILED_NOT_STANDING = 0x41, - SPELL_FAILED_NOT_TRADEABLE = 0x42, - SPELL_FAILED_NOT_TRADING = 0x43, - SPELL_FAILED_NOT_UNSHEATHED = 0x44, - SPELL_FAILED_NOT_WHILE_GHOST = 0x45, - SPELL_FAILED_NO_AMMO = 0x46, - SPELL_FAILED_NO_CHARGES_REMAIN = 0x47, - SPELL_FAILED_NO_CHAMPION = 0x48, - SPELL_FAILED_NO_COMBO_POINTS = 0x49, - SPELL_FAILED_NO_DUELING = 0x4A, - SPELL_FAILED_NO_ENDURANCE = 0x4B, - SPELL_FAILED_NO_FISH = 0x4C, - SPELL_FAILED_NO_ITEMS_WHILE_SHAPESHIFTED = 0x4D, - SPELL_FAILED_NO_MOUNTS_ALLOWED = 0x4E, - SPELL_FAILED_NO_PET = 0x4F, - SPELL_FAILED_NO_POWER = 0x50, - SPELL_FAILED_NOTHING_TO_DISPEL = 0x51, - SPELL_FAILED_NOTHING_TO_STEAL = 0x52, - SPELL_FAILED_ONLY_ABOVEWATER = 0x53, - SPELL_FAILED_ONLY_DAYTIME = 0x54, - SPELL_FAILED_ONLY_INDOORS = 0x55, - SPELL_FAILED_ONLY_MOUNTED = 0x56, - SPELL_FAILED_ONLY_NIGHTTIME = 0x57, - SPELL_FAILED_ONLY_OUTDOORS = 0x58, - SPELL_FAILED_ONLY_SHAPESHIFT = 0x59, - SPELL_FAILED_ONLY_STEALTHED = 0x5A, - SPELL_FAILED_ONLY_UNDERWATER = 0x5B, - SPELL_FAILED_OUT_OF_RANGE = 0x5C, - SPELL_FAILED_PACIFIED = 0x5D, - SPELL_FAILED_POSSESSED = 0x5E, - SPELL_FAILED_REAGENTS = 0x5F, - SPELL_FAILED_REQUIRES_AREA = 0x60, - SPELL_FAILED_REQUIRES_SPELL_FOCUS = 0x61, - SPELL_FAILED_ROOTED = 0x62, - SPELL_FAILED_SILENCED = 0x63, - SPELL_FAILED_SPELL_IN_PROGRESS = 0x64, - SPELL_FAILED_SPELL_LEARNED = 0x65, - SPELL_FAILED_SPELL_UNAVAILABLE = 0x66, - SPELL_FAILED_STUNNED = 0x67, - SPELL_FAILED_TARGETS_DEAD = 0x68, - SPELL_FAILED_TARGET_AFFECTING_COMBAT = 0x69, - SPELL_FAILED_TARGET_AURASTATE = 0x6A, - SPELL_FAILED_TARGET_DUELING = 0x6B, - SPELL_FAILED_TARGET_ENEMY = 0x6C, - SPELL_FAILED_TARGET_ENRAGED = 0x6D, - SPELL_FAILED_TARGET_FRIENDLY = 0x6E, - SPELL_FAILED_TARGET_IN_COMBAT = 0x6F, - SPELL_FAILED_TARGET_IS_PLAYER = 0x70, - SPELL_FAILED_TARGET_IS_PLAYER_CONTROLLED = 0x71, - SPELL_FAILED_TARGET_NOT_DEAD = 0x72, - SPELL_FAILED_TARGET_NOT_IN_PARTY = 0x73, - SPELL_FAILED_TARGET_NOT_LOOTED = 0x74, - SPELL_FAILED_TARGET_NOT_PLAYER = 0x75, - SPELL_FAILED_TARGET_NO_POCKETS = 0x76, - SPELL_FAILED_TARGET_NO_WEAPONS = 0x77, - SPELL_FAILED_TARGET_UNSKINNABLE = 0x78, - SPELL_FAILED_THIRST_SATIATED = 0x79, - SPELL_FAILED_TOO_CLOSE = 0x7A, - SPELL_FAILED_TOO_MANY_OF_ITEM = 0x7B, - SPELL_FAILED_TOTEM_CATEGORY = 0x7C, - SPELL_FAILED_TOTEMS = 0x7D, - SPELL_FAILED_TRAINING_POINTS = 0x7E, - SPELL_FAILED_TRY_AGAIN = 0x7F, - SPELL_FAILED_UNIT_NOT_BEHIND = 0x80, - SPELL_FAILED_UNIT_NOT_INFRONT = 0x81, - SPELL_FAILED_WRONG_PET_FOOD = 0x82, - SPELL_FAILED_NOT_WHILE_FATIGUED = 0x83, - SPELL_FAILED_TARGET_NOT_IN_INSTANCE = 0x84, - SPELL_FAILED_NOT_WHILE_TRADING = 0x85, - SPELL_FAILED_TARGET_NOT_IN_RAID = 0x86, - SPELL_FAILED_DISENCHANT_WHILE_LOOTING = 0x87, - SPELL_FAILED_PROSPECT_WHILE_LOOTING = 0x88, - SPELL_FAILED_PROSPECT_NEED_MORE = 0x89, - SPELL_FAILED_TARGET_FREEFORALL = 0x8A, - SPELL_FAILED_NO_EDIBLE_CORPSES = 0x8B, - SPELL_FAILED_ONLY_BATTLEGROUNDS = 0x8C, - SPELL_FAILED_TARGET_NOT_GHOST = 0x8D, - SPELL_FAILED_TOO_MANY_SKILLS = 0x8E, - SPELL_FAILED_TRANSFORM_UNUSABLE = 0x8F, - SPELL_FAILED_WRONG_WEATHER = 0x90, - SPELL_FAILED_DAMAGE_IMMUNE = 0x91, - SPELL_FAILED_PREVENTED_BY_MECHANIC = 0x92, - SPELL_FAILED_PLAY_TIME = 0x93, - SPELL_FAILED_REPUTATION = 0x94, - SPELL_FAILED_MIN_SKILL = 0x95, - SPELL_FAILED_NOT_IN_ARENA = 0x96, - SPELL_FAILED_NOT_ON_SHAPESHIFT = 0x97, - SPELL_FAILED_NOT_ON_STEALTHED = 0x98, - SPELL_FAILED_NOT_ON_DAMAGE_IMMUNE = 0x99, - SPELL_FAILED_NOT_ON_MOUNTED = 0x9A, - SPELL_FAILED_TOO_SHALLOW = 0x9B, - SPELL_FAILED_TARGET_NOT_IN_SANCTUARY = 0x9C, - SPELL_FAILED_TARGET_IS_TRIVIAL = 0x9D, - SPELL_FAILED_BM_OR_INVISGOD = 0x9E, - SPELL_FAILED_EXPERT_RIDING_REQUIREMENT = 0x9F, - SPELL_FAILED_ARTISAN_RIDING_REQUIREMENT = 0xA0, - SPELL_FAILED_NOT_IDLE = 0xA1, - SPELL_FAILED_NOT_INACTIVE = 0xA2, - SPELL_FAILED_PARTIAL_PLAYTIME = 0xA3, - SPELL_FAILED_NO_PLAYTIME = 0xA4, - SPELL_FAILED_NOT_IN_BATTLEGROUND = 0xA5, - SPELL_FAILED_ONLY_IN_ARENA = 0xA6, - SPELL_FAILED_TARGET_LOCKED_TO_RAID_INSTANCE = 0xA7, - SPELL_FAILED_UNKNOWN = 0xA8, + SPELL_FAILED_AFFECTING_COMBAT = 0, + SPELL_FAILED_ALREADY_AT_FULL_HEALTH = 1, + SPELL_FAILED_ALREADY_AT_FULL_MANA = 2, + SPELL_FAILED_ALREADY_AT_FULL_POWER = 3, + SPELL_FAILED_ALREADY_BEING_TAMED = 4, + SPELL_FAILED_ALREADY_HAVE_CHARM = 5, + SPELL_FAILED_ALREADY_HAVE_SUMMON = 6, + SPELL_FAILED_ALREADY_OPEN = 7, + SPELL_FAILED_AURA_BOUNCED = 8, + SPELL_FAILED_AUTOTRACK_INTERRUPTED = 9, + SPELL_FAILED_BAD_IMPLICIT_TARGETS = 10, + SPELL_FAILED_BAD_TARGETS = 11, + SPELL_FAILED_CANT_BE_CHARMED = 12, + SPELL_FAILED_CANT_BE_DISENCHANTED = 13, + SPELL_FAILED_CANT_BE_DISENCHANTED_SKILL = 14, + SPELL_FAILED_CANT_BE_MILLED = 15, + SPELL_FAILED_CANT_BE_PROSPECTED = 16, + SPELL_FAILED_CANT_CAST_ON_TAPPED = 17, + SPELL_FAILED_CANT_DUEL_WHILE_INVISIBLE = 18, + SPELL_FAILED_CANT_DUEL_WHILE_STEALTHED = 19, + SPELL_FAILED_CANT_STEALTH = 20, + SPELL_FAILED_CASTER_AURASTATE = 21, + SPELL_FAILED_CASTER_DEAD = 22, + SPELL_FAILED_CHARMED = 23, + SPELL_FAILED_CHEST_IN_USE = 24, + SPELL_FAILED_CONFUSED = 25, + SPELL_FAILED_DONT_REPORT = 26, + SPELL_FAILED_EQUIPPED_ITEM = 27, + SPELL_FAILED_EQUIPPED_ITEM_CLASS = 28, + SPELL_FAILED_EQUIPPED_ITEM_CLASS_MAINHAND = 29, + SPELL_FAILED_EQUIPPED_ITEM_CLASS_OFFHAND = 30, + SPELL_FAILED_ERROR = 31, + SPELL_FAILED_FIZZLE = 32, + SPELL_FAILED_FLEEING = 33, + SPELL_FAILED_FOOD_LOWLEVEL = 34, + SPELL_FAILED_HIGHLEVEL = 35, + SPELL_FAILED_HUNGER_SATIATED = 36, + SPELL_FAILED_IMMUNE = 37, + SPELL_FAILED_INCORRECT_AREA = 38, + SPELL_FAILED_INTERRUPTED = 39, + SPELL_FAILED_INTERRUPTED_COMBAT = 40, + SPELL_FAILED_ITEM_ALREADY_ENCHANTED = 41, + SPELL_FAILED_ITEM_GONE = 42, + SPELL_FAILED_ITEM_NOT_FOUND = 43, + SPELL_FAILED_ITEM_NOT_READY = 44, + SPELL_FAILED_LEVEL_REQUIREMENT = 45, + SPELL_FAILED_LINE_OF_SIGHT = 46, + SPELL_FAILED_LOWLEVEL = 47, + SPELL_FAILED_LOW_CASTLEVEL = 48, + SPELL_FAILED_MAINHAND_EMPTY = 49, + SPELL_FAILED_MOVING = 50, + SPELL_FAILED_NEED_AMMO = 51, + SPELL_FAILED_NEED_AMMO_POUCH = 52, + SPELL_FAILED_NEED_EXOTIC_AMMO = 53, + SPELL_FAILED_NEED_MORE_ITEMS = 54, + SPELL_FAILED_NOPATH = 55, + SPELL_FAILED_NOT_BEHIND = 56, + SPELL_FAILED_NOT_FISHABLE = 57, + SPELL_FAILED_NOT_FLYING = 58, + SPELL_FAILED_NOT_HERE = 59, + SPELL_FAILED_NOT_INFRONT = 60, + SPELL_FAILED_NOT_IN_CONTROL = 61, + SPELL_FAILED_NOT_KNOWN = 62, + SPELL_FAILED_NOT_MOUNTED = 63, + SPELL_FAILED_NOT_ON_TAXI = 64, + SPELL_FAILED_NOT_ON_TRANSPORT = 65, + SPELL_FAILED_NOT_READY = 66, + SPELL_FAILED_NOT_SHAPESHIFT = 67, + SPELL_FAILED_NOT_STANDING = 68, + SPELL_FAILED_NOT_TRADEABLE = 69, + SPELL_FAILED_NOT_TRADING = 70, + SPELL_FAILED_NOT_UNSHEATHED = 71, + SPELL_FAILED_NOT_WHILE_GHOST = 72, + SPELL_FAILED_NOT_WHILE_LOOTING = 73, + SPELL_FAILED_NO_AMMO = 74, + SPELL_FAILED_NO_CHARGES_REMAIN = 75, + SPELL_FAILED_NO_CHAMPION = 76, + SPELL_FAILED_NO_COMBO_POINTS = 77, + SPELL_FAILED_NO_DUELING = 78, + SPELL_FAILED_NO_ENDURANCE = 79, + SPELL_FAILED_NO_FISH = 80, + SPELL_FAILED_NO_ITEMS_WHILE_SHAPESHIFTED = 81, + SPELL_FAILED_NO_MOUNTS_ALLOWED = 82, + SPELL_FAILED_NO_PET = 83, + SPELL_FAILED_NO_POWER = 84, + SPELL_FAILED_NOTHING_TO_DISPEL = 85, + SPELL_FAILED_NOTHING_TO_STEAL = 86, + SPELL_FAILED_ONLY_ABOVEWATER = 87, + SPELL_FAILED_ONLY_DAYTIME = 88, + SPELL_FAILED_ONLY_INDOORS = 89, + SPELL_FAILED_ONLY_MOUNTED = 90, + SPELL_FAILED_ONLY_NIGHTTIME = 91, + SPELL_FAILED_ONLY_OUTDOORS = 92, + SPELL_FAILED_ONLY_SHAPESHIFT = 93, + SPELL_FAILED_ONLY_STEALTHED = 94, + SPELL_FAILED_ONLY_UNDERWATER = 95, + SPELL_FAILED_OUT_OF_RANGE = 96, + SPELL_FAILED_PACIFIED = 97, + SPELL_FAILED_POSSESSED = 98, + SPELL_FAILED_REAGENTS = 99, + SPELL_FAILED_REQUIRES_AREA = 100, + SPELL_FAILED_REQUIRES_SPELL_FOCUS = 101, + SPELL_FAILED_ROOTED = 102, + SPELL_FAILED_SILENCED = 103, + SPELL_FAILED_SPELL_IN_PROGRESS = 104, + SPELL_FAILED_SPELL_LEARNED = 105, + SPELL_FAILED_SPELL_UNAVAILABLE = 106, + SPELL_FAILED_STUNNED = 107, + SPELL_FAILED_TARGETS_DEAD = 108, + SPELL_FAILED_TARGET_AFFECTING_COMBAT = 109, + SPELL_FAILED_TARGET_AURASTATE = 110, + SPELL_FAILED_TARGET_DUELING = 111, + SPELL_FAILED_TARGET_ENEMY = 112, + SPELL_FAILED_TARGET_ENRAGED = 113, + SPELL_FAILED_TARGET_FRIENDLY = 114, + SPELL_FAILED_TARGET_IN_COMBAT = 115, + SPELL_FAILED_TARGET_IS_PLAYER = 116, + SPELL_FAILED_TARGET_IS_PLAYER_CONTROLLED = 117, + SPELL_FAILED_TARGET_NOT_DEAD = 118, + SPELL_FAILED_TARGET_NOT_IN_PARTY = 119, + SPELL_FAILED_TARGET_NOT_LOOTED = 120, + SPELL_FAILED_TARGET_NOT_PLAYER = 121, + SPELL_FAILED_TARGET_NO_POCKETS = 122, + SPELL_FAILED_TARGET_NO_WEAPONS = 123, + SPELL_FAILED_TARGET_NO_RANGED_WEAPONS = 124, + SPELL_FAILED_TARGET_UNSKINNABLE = 125, + SPELL_FAILED_THIRST_SATIATED = 126, + SPELL_FAILED_TOO_CLOSE = 127, + SPELL_FAILED_TOO_MANY_OF_ITEM = 128, + SPELL_FAILED_TOTEM_CATEGORY = 129, + SPELL_FAILED_TOTEMS = 130, + SPELL_FAILED_TRY_AGAIN = 131, + SPELL_FAILED_UNIT_NOT_BEHIND = 132, + SPELL_FAILED_UNIT_NOT_INFRONT = 133, + SPELL_FAILED_WRONG_PET_FOOD = 134, + SPELL_FAILED_NOT_WHILE_FATIGUED = 135, + SPELL_FAILED_TARGET_NOT_IN_INSTANCE = 136, + SPELL_FAILED_NOT_WHILE_TRADING = 137, + SPELL_FAILED_TARGET_NOT_IN_RAID = 138, + SPELL_FAILED_TARGET_FREEFORALL = 139, + SPELL_FAILED_NO_EDIBLE_CORPSES = 140, + SPELL_FAILED_ONLY_BATTLEGROUNDS = 141, + SPELL_FAILED_TARGET_NOT_GHOST = 142, + SPELL_FAILED_TRANSFORM_UNUSABLE = 143, + SPELL_FAILED_WRONG_WEATHER = 144, + SPELL_FAILED_DAMAGE_IMMUNE = 145, + SPELL_FAILED_PREVENTED_BY_MECHANIC = 146, + SPELL_FAILED_PLAY_TIME = 147, + SPELL_FAILED_REPUTATION = 148, + SPELL_FAILED_MIN_SKILL = 149, + SPELL_FAILED_NOT_IN_ARENA = 150, + SPELL_FAILED_NOT_ON_SHAPESHIFT = 151, + SPELL_FAILED_NOT_ON_STEALTHED = 152, + SPELL_FAILED_NOT_ON_DAMAGE_IMMUNE = 153, + SPELL_FAILED_NOT_ON_MOUNTED = 154, + SPELL_FAILED_TOO_SHALLOW = 155, + SPELL_FAILED_TARGET_NOT_IN_SANCTUARY = 156, + SPELL_FAILED_TARGET_IS_TRIVIAL = 157, + SPELL_FAILED_BM_OR_INVISGOD = 158, + SPELL_FAILED_EXPERT_RIDING_REQUIREMENT = 159, + SPELL_FAILED_ARTISAN_RIDING_REQUIREMENT = 160, + SPELL_FAILED_NOT_IDLE = 161, + SPELL_FAILED_NOT_INACTIVE = 162, + SPELL_FAILED_PARTIAL_PLAYTIME = 163, + SPELL_FAILED_NO_PLAYTIME = 164, + SPELL_FAILED_NOT_IN_BATTLEGROUND = 165, + SPELL_FAILED_NOT_IN_RAID_INSTANCE = 166, + SPELL_FAILED_ONLY_IN_ARENA = 167, + SPELL_FAILED_TARGET_LOCKED_TO_RAID_INSTANCE = 168, + SPELL_FAILED_ON_USE_ENCHANT = 169, + SPELL_FAILED_NOT_ON_GROUND = 170, + SPELL_FAILED_CUSTOM_ERROR = 171, + SPELL_FAILED_CANT_DO_THAT_RIGHT_NOW = 172, + SPELL_FAILED_TOO_MANY_SOCKETS = 173, + SPELL_FAILED_INVALID_GLYPH = 174, + SPELL_FAILED_UNIQUE_GLYPH = 175, + SPELL_FAILED_GLYPH_SOCKET_LOCKED = 176, + SPELL_FAILED_NO_VALID_TARGETS = 177, + SPELL_FAILED_ITEM_AT_MAX_CHARGES = 178, + SPELL_FAILED_NOT_IN_BARBERSHOP = 179, + SPELL_FAILED_FISHING_TOO_LOW = 180, + SPELL_FAILED_UNKNOWN = 181 }; enum SpellFamilyNames @@ -221,12 +237,12 @@ enum SpellFamilyNames SPELLFAMILY_HUNTER = 9, SPELLFAMILY_PALADIN = 10, SPELLFAMILY_SHAMAN = 11, - SPELLFAMILY_UNK2 = 12, + SPELLFAMILY_UNK2 = 12, // 2 spells (silence resistance) SPELLFAMILY_POTION = 13, // 14 - unused SPELLFAMILY_DEATHKNIGHT = 15, // 16 - unused - SPELLFAMILY_UNK3 = 17 + SPELLFAMILY_PET = 17 }; //Some SpellFamilyFlags @@ -366,6 +382,7 @@ inline bool IsAreaOfEffectSpell(SpellEntry const *spellInfo) inline bool IsAreaAuraEffect(uint32 effect) { if( effect == SPELL_EFFECT_APPLY_AREA_AURA_PARTY || + effect == SPELL_EFFECT_APPLY_AREA_AURA_RAID || effect == SPELL_EFFECT_APPLY_AREA_AURA_FRIEND || effect == SPELL_EFFECT_APPLY_AREA_AURA_ENEMY || effect == SPELL_EFFECT_APPLY_AREA_AURA_PET || @@ -438,7 +455,11 @@ bool IsDiminishingReturnsGroupDurationLimited(DiminishingGroup group); DiminishingReturnsType GetDiminishingReturnsGroupType(DiminishingGroup group); // Spell affects related declarations (accessed using SpellMgr functions) -typedef std::map SpellAffectMap; +struct SpellAffectEntry +{ + uint32 SpellClassMask[3]; +}; +typedef UNORDERED_MAP SpellAffectMap; // Spell proc event related declarations (accessed using SpellMgr functions) enum ProcFlags @@ -651,6 +672,9 @@ typedef std::multimap SpellLearnSpellMap; typedef std::multimap SkillLineAbilityMap; +typedef std::map PetLevelupSpellSet; +typedef std::map PetLevelupSpellMap; + inline bool IsPrimaryProfessionSkill(uint32 skill) { SkillLineEntry const *pSkill = sSkillLineStore.LookupEntry(skill); @@ -678,15 +702,15 @@ class SpellMgr // Accessors (const or static functions) public: // Spell affects - uint64 GetSpellAffectMask(uint16 spellId, uint8 effectId) const + SpellAffectEntry const*GetSpellAffect(uint16 spellId, uint8 effectId) const { SpellAffectMap::const_iterator itr = mSpellAffectMap.find((spellId<<8) + effectId); if( itr != mSpellAffectMap.end( ) ) - return itr->second; + return &itr->second; return 0; } - bool IsAffectedBySpell(SpellEntry const *spellInfo, uint32 spellId, uint8 effectId, uint64 familyFlags) const; + bool IsAffectedByMod(SpellEntry const *spellInfo, SpellModifier *mod) const; SpellElixirMap const& GetSpellElixirMap() const { return mSpellElixirs; } @@ -866,6 +890,15 @@ class SpellMgr return NULL; } + PetLevelupSpellSet const* GetPetLevelupSpellList(uint32 petFamily) const + { + PetLevelupSpellMap::const_iterator itr = mPetLevelupSpellMap.find(petFamily); + if(itr != mPetLevelupSpellMap.end()) + return &itr->second; + else + return NULL; + } + // Modifiers public: static SpellMgr& Instance(); @@ -882,6 +915,7 @@ class SpellMgr void LoadSpellThreats(); void LoadSkillLineAbilityMap(); void LoadSpellPetAuras(); + void LoadPetLevelupSpellMap(); private: SpellScriptTarget mSpellScriptTarget; @@ -895,6 +929,7 @@ class SpellMgr SpellProcEventMap mSpellProcEventMap; SkillLineAbilityMap mSkillLineAbilityMap; SpellPetAuraMap mSpellPetAuraMap; + PetLevelupSpellMap mPetLevelupSpellMap; }; #define spellmgr SpellMgr::Instance() diff --git a/src/game/StatSystem.cpp b/src/game/StatSystem.cpp index d94e68fef..a4127e832 100644 --- a/src/game/StatSystem.cpp +++ b/src/game/StatSystem.cpp @@ -49,24 +49,17 @@ bool Player::UpdateStats(Stats stat) switch(stat) { case STAT_STRENGTH: - UpdateAttackPowerAndDamage(); UpdateShieldBlockValue(); break; case STAT_AGILITY: UpdateArmor(); - UpdateAttackPowerAndDamage(true); - if(getClass() == CLASS_ROGUE || getClass() == CLASS_HUNTER || getClass() == CLASS_DRUID && m_form==FORM_CAT) - UpdateAttackPowerAndDamage(); - UpdateAllCritPercentages(); UpdateDodgePercentage(); break; - case STAT_STAMINA: UpdateMaxHealth(); break; case STAT_INTELLECT: UpdateMaxPower(POWER_MANA); UpdateAllSpellCritChances(); - UpdateAttackPowerAndDamage(true); //SPELL_AURA_MOD_RANGED_ATTACK_POWER_OF_STAT_PERCENT, only intelect currently UpdateArmor(); //SPELL_AURA_MOD_RESISTANCE_OF_INTELLECT_PERCENT, only armor currently break; @@ -76,8 +69,25 @@ bool Player::UpdateStats(Stats stat) default: break; } + // Need update (exist AP from stat auras) + UpdateAttackPowerAndDamage(); + UpdateAttackPowerAndDamage(true); + UpdateSpellDamageAndHealingBonus(); UpdateManaRegen(); + + // Update ratings in exist SPELL_AURA_MOD_RATING_FROM_STAT and only depends from stat + uint32 mask = 0; + AuraList const& modRatingFromStat = GetAurasByType(SPELL_AURA_MOD_RATING_FROM_STAT); + for(AuraList::const_iterator i = modRatingFromStat.begin();i != modRatingFromStat.end(); ++i) + if (Stats((*i)->GetMiscBValue()) == stat) + mask |= (*i)->GetMiscValue(); + if (mask) + { + for (uint32 rating = 0; rating < MAX_COMBAT_RATING; ++rating) + if (mask & (1 << rating)) + ApplyRatingMod(CombatRating(rating), 0, true); + } return true; } @@ -253,6 +263,7 @@ void Player::UpdateAttackPowerAndDamage(bool ranged ) { case CLASS_WARRIOR: val2 = level*3.0f + GetStat(STAT_STRENGTH)*2.0f - 20.0f; break; case CLASS_PALADIN: val2 = level*3.0f + GetStat(STAT_STRENGTH)*2.0f - 20.0f; break; + case CLASS_DEATH_KNIGHT: val2 = level*3.0f + GetStat(STAT_STRENGTH)*2.0f - 20.0f; break; case CLASS_ROGUE: val2 = level*2.0f + GetStat(STAT_STRENGTH) + GetStat(STAT_AGILITY) - 20.0f; break; case CLASS_HUNTER: val2 = level*2.0f + GetStat(STAT_STRENGTH) + GetStat(STAT_AGILITY) - 20.0f; break; case CLASS_SHAMAN: val2 = level*2.0f + GetStat(STAT_STRENGTH)*2.0f - 20.0f; break; @@ -307,11 +318,20 @@ void Player::UpdateAttackPowerAndDamage(bool ranged ) float attPowerMod = GetModifierValue(unitMod, TOTAL_VALUE); //add dynamic flat mods - if( ranged && (getClassMask() & CLASSMASK_WAND_USERS)==0) + if ((getClassMask() & CLASSMASK_WAND_USERS)==0) { - AuraList const& mRAPbyIntellect = GetAurasByType(SPELL_AURA_MOD_RANGED_ATTACK_POWER_OF_STAT_PERCENT); - for(AuraList::const_iterator i = mRAPbyIntellect.begin();i != mRAPbyIntellect.end(); ++i) - attPowerMod += int32(GetStat(Stats((*i)->GetModifier()->m_miscvalue)) * (*i)->GetModifier()->m_amount / 100.0f); + if( ranged ) + { + AuraList const& mRAPbyIntellect = GetAurasByType(SPELL_AURA_MOD_RANGED_ATTACK_POWER_OF_STAT_PERCENT); + for(AuraList::const_iterator i = mRAPbyIntellect.begin();i != mRAPbyIntellect.end(); ++i) + attPowerMod += int32(GetStat(Stats((*i)->GetModifier()->m_miscvalue)) * (*i)->GetModifier()->m_amount / 100.0f); + } + else + { + AuraList const& mRAPbyIntellect = GetAurasByType(SPELL_AURA_MOD_ATTACK_POWER_OF_STAT_PERCENT); + for(AuraList::const_iterator i = mRAPbyIntellect.begin();i != mRAPbyIntellect.end(); ++i) + attPowerMod += int32(GetStat(Stats((*i)->GetModifier()->m_miscvalue)) * (*i)->GetModifier()->m_amount / 100.0f); + } } float attPowerMultiplier = GetModifierValue(unitMod, TOTAL_PCT) - 1.0f; @@ -550,6 +570,24 @@ void Player::UpdateSpellCritChance(uint32 school) SetFloatValue(PLAYER_SPELL_CRIT_PERCENTAGE1 + school, crit); } +void Player::UpdateMeleeHitChances() +{ + m_modMeleeHitChance = GetTotalAuraModifier(SPELL_AURA_MOD_HIT_CHANCE); + m_modMeleeHitChance+= GetRatingBonusValue(CR_HIT_MELEE); +} + +void Player::UpdateRangedHitChances() +{ + m_modRangedHitChance = GetTotalAuraModifier(SPELL_AURA_MOD_HIT_CHANCE); + m_modRangedHitChance+= GetRatingBonusValue(CR_HIT_RANGED); +} + +void Player::UpdateSpellHitChances() +{ + m_modSpellHitChance = GetTotalAuraModifier(SPELL_AURA_MOD_SPELL_HIT_CHANCE); + m_modSpellHitChance+= GetRatingBonusValue(CR_HIT_SPELL); +} + void Player::UpdateAllSpellCritChances() { for (int i = SPELL_SCHOOL_NORMAL; i < MAX_SPELL_SCHOOL; i++) @@ -620,9 +658,9 @@ void Player::UpdateManaRegen() int32 modManaRegenInterrupt = GetTotalAuraModifier(SPELL_AURA_MOD_MANA_REGEN_INTERRUPT); if (modManaRegenInterrupt > 100) modManaRegenInterrupt = 100; - SetStatFloatValue(PLAYER_FIELD_MOD_MANA_REGEN_INTERRUPT, power_regen_mp5 + power_regen * modManaRegenInterrupt / 100.0f); + SetStatFloatValue(UNIT_FIELD_POWER_REGEN_INTERRUPTED_FLAT_MODIFIER, power_regen_mp5 + power_regen * modManaRegenInterrupt / 100.0f); - SetStatFloatValue(PLAYER_FIELD_MOD_MANA_REGEN, power_regen_mp5 + power_regen); + SetStatFloatValue(UNIT_FIELD_POWER_REGEN_FLAT_MODIFIER, power_regen_mp5 + power_regen); } void Player::_ApplyAllStatBonuses() @@ -879,7 +917,7 @@ void Pet::UpdateAttackPowerAndDamage(bool ranged) if(getPetType() == HUNTER_PET) //hunter pets benefit from owner's attack power { bonusAP = owner->GetTotalAttackPowerValue(RANGED_ATTACK) * 0.22f; - SetBonusDamage( int32(owner->GetTotalAttackPowerValue(RANGED_ATTACK) * 0.125f)); + SetBonusDamage( int32(owner->GetTotalAttackPowerValue(RANGED_ATTACK) * 0.1287f)); } //demons benefit from warlocks shadow or fire damage else if(getPetType() == SUMMON_PET && owner->getClass() == CLASS_WARLOCK) diff --git a/src/game/TaxiHandler.cpp b/src/game/TaxiHandler.cpp index 30c6df133..391268011 100644 --- a/src/game/TaxiHandler.cpp +++ b/src/game/TaxiHandler.cpp @@ -69,7 +69,7 @@ void WorldSession::SendTaxiStatus( uint64 guid ) sLog.outDebug( "WORLD: Sent SMSG_TAXINODE_STATUS" ); } -void WorldSession::HandleTaxiQueryAvailableNodesOpcode( WorldPacket & recv_data ) +void WorldSession::HandleTaxiQueryAvailableNodes( WorldPacket & recv_data ) { CHECK_PACKET_SIZE(recv_data,8); diff --git a/src/game/Transports.cpp b/src/game/Transports.cpp index 3c736b8fb..c5606aff9 100644 --- a/src/game/Transports.cpp +++ b/src/game/Transports.cpp @@ -135,7 +135,7 @@ void MapManager::LoadTransports() Transport::Transport() : GameObject() { // 2.3.2 - 0x5A - m_updateFlag = (UPDATEFLAG_TRANSPORT | UPDATEFLAG_LOWGUID | UPDATEFLAG_HIGHGUID | UPDATEFLAG_HASPOSITION); + m_updateFlag = (UPDATEFLAG_TRANSPORT | UPDATEFLAG_LOWGUID | UPDATEFLAG_HIGHGUID | UPDATEFLAG_HAS_POSITION); } bool Transport::Create(uint32 guidlow, uint32 mapid, float x, float y, float z, float ang, uint32 animprogress, uint32 dynflags) @@ -166,8 +166,9 @@ bool Transport::Create(uint32 guidlow, uint32 mapid, float x, float y, float z, SetFloatValue(OBJECT_FIELD_SCALE_X, goinfo->size); SetUInt32Value(GAMEOBJECT_FACTION, goinfo->faction); - SetUInt32Value(GAMEOBJECT_FLAGS, goinfo->flags); - + //SetUInt32Value(GAMEOBJECT_FLAGS, goinfo->flags); + SetUInt32Value(GAMEOBJECT_FLAGS, MAKE_PAIR32(0x28, 0x64)); + SetUInt32Value(GAMEOBJECT_LEVEL, m_period); SetEntry(goinfo->id); SetUInt32Value(GAMEOBJECT_DISPLAYID, goinfo->displayId); @@ -177,7 +178,7 @@ bool Transport::Create(uint32 guidlow, uint32 mapid, float x, float y, float z, SetGoAnimProgress(animprogress); if(dynflags) - SetUInt32Value(GAMEOBJECT_DYN_FLAGS, dynflags); + SetUInt32Value(GAMEOBJECT_DYNAMIC, MAKE_PAIR32(0, dynflags)); return true; } diff --git a/src/game/Unit.cpp b/src/game/Unit.cpp index 7a259fa85..99003f865 100644 --- a/src/game/Unit.cpp +++ b/src/game/Unit.cpp @@ -56,6 +56,7 @@ float baseMoveSpeed[MAX_MOVE_TYPE] = 3.141594f, // MOVE_TURN_RATE 7.0f, // MOVE_FLIGHT 4.5f, // MOVE_FLIGHT_BACK + 3.14f // MOVE_PITCH_RATE }; void InitTriggerAuraData(); @@ -149,7 +150,7 @@ Unit::Unit() m_objectType |= TYPEMASK_UNIT; m_objectTypeId = TYPEID_UNIT; // 2.3.2 - 0x70 - m_updateFlag = (UPDATEFLAG_HIGHGUID | UPDATEFLAG_LIVING | UPDATEFLAG_HASPOSITION); + m_updateFlag = (UPDATEFLAG_LOWGUID | UPDATEFLAG_HIGHGUID | UPDATEFLAG_LIVING | UPDATEFLAG_HAS_POSITION); m_attackTimer[BASE_ATTACK] = 0; m_attackTimer[OFF_ATTACK] = 0; @@ -609,25 +610,6 @@ uint32 Unit::DealDamage(Unit *pVictim, uint32 damage, CleanDamage const* cleanDa ((Creature*)pVictim)->SetLootRecipient(this); if (health <= damage) { - // battleground things - if(pVictim->GetTypeId() == TYPEID_PLAYER && (((Player*)pVictim)->InBattleGround())) - { - Player *killed = ((Player*)pVictim); - Player *killer = NULL; - if(GetTypeId() == TYPEID_PLAYER) - killer = ((Player*)this); - else if(GetTypeId() == TYPEID_UNIT && ((Creature*)this)->isPet()) - { - Unit *owner = GetOwner(); - if(owner && owner->GetTypeId() == TYPEID_PLAYER) - killer = ((Player*)owner); - } - - if(killer) - if(BattleGround *bg = killed->GetBattleGround()) - bg->HandleKillPlayer(killed, killer); // drop flags and etc - } - DEBUG_LOG("DealDamage: victim just died"); // find player: owner of controlled `this` or `this` itself maybe @@ -703,6 +685,15 @@ uint32 Unit::DealDamage(Unit *pVictim, uint32 damage, CleanDamage const* cleanDa if (GetTypeId() == TYPEID_UNIT && ((Creature*)this)->AI()) ((Creature*)this)->AI()->KilledUnit(pVictim); + // achievement stuff + if ( pVictim->GetTypeId() == TYPEID_PLAYER) + { + if(GetTypeId() == TYPEID_UNIT) + ((Player*)pVictim)->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_KILLED_BY_CREATURE, GetEntry()); + else if(GetTypeId() == TYPEID_PLAYER) + ((Player*)pVictim)->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_KILLED_BY_PLAYER, 1); + } + // 10% durability loss on death // clean InHateListOf if (pVictim->GetTypeId() == TYPEID_PLAYER) @@ -770,6 +761,19 @@ uint32 Unit::DealDamage(Unit *pVictim, uint32 damage, CleanDamage const* cleanDa he->DuelComplete(DUEL_INTERUPTED); } + + // battleground things (do this at the end, so the death state flag will be properly set to handle in the bg->handlekill) + if(pVictim->GetTypeId() == TYPEID_PLAYER && ((Player*)pVictim)->InBattleGround()) + { + Player *killed = ((Player*)pVictim); + if(BattleGround *bg = killed->GetBattleGround()) + if(player) + bg->HandleKillPlayer(killed, player); + //later we can add support for creature->player kills here i'm + //not sure, but i guess those kills also get counted in av + //else if(GetTypeId() == TYPEID_UNIT) + // bg->HandleKillPlayer(killed,(Creature*)this); + } } else // if (health <= damage) { @@ -2370,9 +2374,7 @@ void Unit::DoAttackDamage (Unit *pVictim, uint32 *damage, CleanDamage *cleanDama case MELEE_HIT_BLOCK_CRIT: case MELEE_HIT_CRIT: { - //*hitInfo = 0xEA; - // 0xEA - *hitInfo = HITINFO_CRITICALHIT | HITINFO_NORMALSWING2 | 0x8; + *hitInfo = HITINFO_CRITICALHIT | HITINFO_NORMALSWING2 | HITINFO_UNK2; // Crit bonus calc uint32 crit_bonus; @@ -2631,6 +2633,7 @@ void Unit::DoAttackDamage (Unit *pVictim, uint32 *damage, CleanDamage *cleanDama { case CLASS_WARRIOR: case CLASS_ROGUE: + case CLASS_DEATH_KNIGHT: maxLowEnd = 0.91; //If the attacker is a melee class then instead the lower value of 0.91 } @@ -2705,7 +2708,7 @@ void Unit::DoAttackDamage (Unit *pVictim, uint32 *damage, CleanDamage *cleanDama ((*itr).second->GetCasterGUID() == GetGUID() && (!spellCasted || spellCasted->Id == 35395)) ) { (*itr).second->SetAuraDuration((*itr).second->GetAuraMaxDuration()); - (*itr).second->UpdateAuraDuration(); + (*itr).second->SendAuraUpdate(false); } } } @@ -2832,21 +2835,20 @@ MeleeHitOutcome Unit::RollPhysicalOutcomeAgainst (Unit const *pVictim, WeaponAtt { // Increase from SPELL_AURA_MOD_SPELL_CRIT_CHANCE_SCHOOL aura crit_chance += GetTotalAuraModifierByMiscMask(SPELL_AURA_MOD_SPELL_CRIT_CHANCE_SCHOOL, spellInfo->SchoolMask); - - if( dodge_chance != 0.0f ) // if dodge chance is already 0, ignore talents for speed + // Ignore combat result aura + AuraList const& ignore = GetAurasByType(SPELL_AURA_IGNORE_COMBAT_RESULT); + for(AuraList::const_iterator i = ignore.begin(); i != ignore.end(); ++i) { - AuraList const& mCanNotBeDodge = GetAurasByType(SPELL_AURA_IGNORE_COMBAT_RESULT); - for(AuraList::const_iterator i = mCanNotBeDodge.begin(); i != mCanNotBeDodge.end(); ++i) + if (!(*i)->isAffectedOnSpell(spellInfo)) + continue; + switch((*i)->GetModifier()->m_miscvalue) { - // can't be dodged rogue finishing move - if((*i)->GetModifier()->m_miscvalue == VICTIMSTATE_DODGE) - { - if(spellInfo->SpellFamilyName==SPELLFAMILY_ROGUE && (spellInfo->SpellFamilyFlags & SPELLFAMILYFLAG_ROGUE__FINISHING_MOVE)) - { - dodge_chance = 0.0f; - break; - } - } + case MELEE_HIT_DODGE: dodge_chance = 0.0f; break; + case MELEE_HIT_BLOCK: block_chance = 0.0f; break; + case MELEE_HIT_PARRY: parry_chance = 0.0f; break; + default: + DEBUG_LOG("Spell %u SPELL_AURA_IGNORE_COMBAT_RESULT have unhandled state %d", (*i)->GetId(), (*i)->GetModifier()->m_miscvalue); + break; } } } @@ -4682,6 +4684,22 @@ void Unit::RemoveAllAuras() } } +void Unit::RemoveArenaAuras(bool onleave) +{ + // in join, remove positive buffs, on end, remove negative + // used to remove positive visible auras in arenas + for(AuraMap::iterator iter = m_Auras.begin(); iter != m_Auras.end();) + { + if ( !(iter->second->GetSpellProto()->AttributesEx4 & (1<<21)) // don't remove stances, shadowform, pally/hunter auras + && !iter->second->IsPassive() // don't remove passive auras + && (!(iter->second->GetSpellProto()->Attributes & SPELL_ATTR_UNAFFECTED_BY_INVULNERABILITY) || !(iter->second->GetSpellProto()->Attributes & SPELL_ATTR_UNK8)) // not unaffected by invulnerability auras or not having that unknown flag (that seemed the most probable) + && (iter->second->IsPositive() ^ onleave)) // remove positive buffs on enter, negative buffs on leave + RemoveAura(iter); + else + ++iter; + } +} + void Unit::RemoveAllAurasOnDeath() { // used just after dieing to remove all visible auras @@ -4704,7 +4722,7 @@ void Unit::DelayAura(uint32 spellId, uint32 effindex, int32 delaytime) iter->second->SetAuraDuration(0); else iter->second->SetAuraDuration(iter->second->GetAuraDuration() - delaytime); - iter->second->UpdateAuraDuration(); + iter->second->SendAuraUpdate(false); sLog.outDebug("Aura %u partially interrupted on unit %u, new duration: %u ms",iter->second->GetModifier()->m_auraname, GetGUIDLow(), iter->second->GetAuraDuration()); } } @@ -4896,6 +4914,7 @@ void Unit::SendSpellNonMeleeDamageLog(Unit *target,uint32 SpellID,uint32 Damage, data.append(GetPackGUID()); data << uint32(SpellID); data << uint32(Damage-AbsorbedDamage-Resist-Blocked); + data << uint32(0); // wotlk data << uint8(damageSchoolMask); // spell school data << uint32(AbsorbedDamage); // AbsorbedDamage data << uint32(Resist); // resist @@ -4960,31 +4979,66 @@ void Unit::SendAttackStateUpdate(uint32 HitInfo, Unit *target, uint8 SwingType, sLog.outDebug("WORLD: Sending SMSG_ATTACKERSTATEUPDATE"); WorldPacket data(SMSG_ATTACKERSTATEUPDATE, (16+45)); // we guess size - data << (uint32)HitInfo; + data << uint32(HitInfo); // flags data.append(GetPackGUID()); data.append(target->GetPackGUID()); - data << (uint32)(Damage-AbsorbDamage-Resist-BlockedAmount); + data << uint32(Damage-AbsorbDamage-Resist-BlockedAmount);// damage + data << uint32(0); // overkill value data << (uint8)SwingType; // count? // for(i = 0; i < SwingType; ++i) data << (uint32)damageSchoolMask; data << (float)(Damage-AbsorbDamage-Resist-BlockedAmount); - // still need to double check damage data << (uint32)(Damage-AbsorbDamage-Resist-BlockedAmount); - data << (uint32)AbsorbDamage; - data << (uint32)Resist; // end loop - data << (uint32)TargetState; + if(HitInfo & (HITINFO_ABSORB | HITINFO_ABSORB2)) + { + // for(i = 0; i < SwingType; ++i) + data << uint32(AbsorbDamage); + // end loop + } - if( AbsorbDamage == 0 ) //also 0x3E8 = 0x3E8, check when that happens - data << (uint32)0; - else - data << (uint32)-1; + if(HitInfo & (HITINFO_RESIST | HITINFO_RESIST2)) + { + // for(i = 0; i < SwingType; ++i) + data << uint32(Resist); + // end loop + } + data << (uint8)TargetState; data << (uint32)0; - data << (uint32)BlockedAmount; + data << (uint32)0; + + if(HitInfo & HITINFO_BLOCK) + { + data << uint32(BlockedAmount); + } + + if(HitInfo & HITINFO_UNK3) + { + data << uint32(0); + } + + if(HitInfo & HITINFO_UNK1) + { + data << uint32(0); + data << float(0); + data << float(0); + data << float(0); + data << float(0); + data << float(0); + data << float(0); + data << float(0); + data << float(0); + for(uint8 i = 0; i < 5; ++i) + { + data << float(0); + data << float(0); + } + data << uint32(0); + } SendMessageToSet( &data, true ); } @@ -5205,7 +5259,7 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, Aura* triggeredByAu { switch (dummySpell->Id) { - // Eye of Eye + // Eye for an Eye case 9799: case 25988: { @@ -5820,7 +5874,7 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, Aura* triggeredByAu triggered_spell_id = 39373; break; } - // Vestments of Faith (Priest Tier 3) - 4 pieces bonus + // Greater Heal (Vestments of Faith (Priest Tier 3) - 4 pieces bonus) case 28809: { triggered_spell_id = 28810; @@ -5957,6 +6011,7 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, Aura* triggeredByAu } case SPELLFAMILY_PALADIN: { + // TODO: spell list, formula change in 3.0.3 // Seal of Righteousness - melee proc dummy if (dummySpell->SpellFamilyFlags&0x000000008000000LL && triggeredByAura->GetEffIndex()==0) { @@ -6053,7 +6108,8 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, Aura* triggeredByAu } break; } - //Seal of Vengeance + // TODO: fix basepoint calculation (changed in 3.0.3) + // Seal of Vengeance case 31801: { if(effIndex != 0) // effect 1,2 used by seal unleashing code @@ -6062,7 +6118,7 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, Aura* triggeredByAu triggered_spell_id = 31803; break; } - // Spiritual Att. + // Spiritual Attunement case 31785: case 33776: { @@ -6246,7 +6302,7 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, Aura* triggeredByAu } // Earth Shield - if(dummySpell->SpellFamilyFlags==0x40000000000LL) + if(dummySpell->SpellFamilyFlags & 0x0000040000000000LL) { if(GetTypeId() != TYPEID_PLAYER) return false; @@ -6284,6 +6340,8 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, Aura* triggeredByAu case 15208: spellId = 45294; break; // Rank 10 case 25448: spellId = 45295; break; // Rank 11 case 25449: spellId = 45296; break; // Rank 12 + case 49237: spellId = 49239; break; // Rank 13 + case 49238: spellId = 49240; break; // Rank 14 // Chain Lightning case 421: spellId = 45297; break; // Rank 1 case 930: spellId = 45298; break; // Rank 2 @@ -6291,6 +6349,8 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, Aura* triggeredByAu case 10605: spellId = 45300; break; // Rank 4 case 25439: spellId = 45301; break; // Rank 5 case 25442: spellId = 45302; break; // Rank 6 + case 49268: spellId = 49270; break; // Rank 7 + case 49269: spellId = 49271; break; // Rank 8 default: sLog.outError("Unit::HandleDummyAuraProc: non handled spell id: %u (LO)", procSpell->Id); return false; @@ -6301,21 +6361,14 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, Aura* triggeredByAu mod->value = -100; mod->type = SPELLMOD_PCT; mod->spellId = dummySpell->Id; - mod->effectId = 0; - mod->lastAffected = NULL; mod->mask = 0x0000000000000003LL; - mod->charges = 0; + mod->mask2= 0LL; ((Player*)this)->AddSpellMod(mod, true); // Remove cooldown (Chain Lightning - have Category Recovery time) if (procSpell->SpellFamilyFlags & 0x0000000000000002LL) ((Player*)this)->RemoveSpellCooldown(spellId); - // Hmmm.. in most case spells already set half basepoints but... - // Lightning Bolt (2-10 rank) have full basepoint and half bonus from level - // As on wiki: - // BUG: Rank 2 to 10 (and maybe 11) of Lightning Bolt will proc another Bolt with FULL damage (not halved). This bug is known and will probably be fixed soon. - // So - no add changes :) CastSpell(pVictim, spellId, true, castItem, triggeredByAura); ((Player*)this)->AddSpellMod(mod, false); @@ -6588,7 +6641,7 @@ bool Unit::HandleProcTriggerSpell(Unit *pVictim, uint32 damage, Aura* triggeredB break; } // Shadowguard - if((auraSpellInfo->SpellFamilyFlags & 0x80000000LL) && auraSpellInfo->SpellVisual==7958) + if((auraSpellInfo->SpellFamilyFlags & 0x80000000LL) && auraSpellInfo->SpellVisual[0]==7958) { switch(triggeredByAura->GetSpellProto()->Id) { @@ -6945,14 +6998,14 @@ bool Unit::HandleProcTriggerSpell(Unit *pVictim, uint32 damage, Aura* triggeredB } // Water Shield (we can't set cooldown for main spell - it's player casted spell - if((auraSpellInfo->SpellFamilyFlags & 0x0000002000000000LL) && auraSpellInfo->SpellVisual==7358) + if((auraSpellInfo->SpellFamilyFlags & 0x0000002000000000LL) && auraSpellInfo->SpellVisual[0]==7358) { target = this; break; } // Lightning Shield - if((auraSpellInfo->SpellFamilyFlags & 0x00000400) && auraSpellInfo->SpellVisual==37) + if((auraSpellInfo->SpellFamilyFlags & 0x00000400) && auraSpellInfo->SpellVisual[0]==37) { // overwrite non existing triggered spell call in spell.dbc switch(triggeredByAura->GetSpellProto()->Id) @@ -7688,21 +7741,21 @@ bool Unit::HandleOverrideClassScriptAuraProc(Unit *pVictim, Aura *triggeredByAur { case 836: // Improved Blizzard (Rank 1) { - if (!procSpell || procSpell->SpellVisual!=9487) + if (!procSpell || procSpell->SpellVisual[0]!=9487) return false; triggered_spell_id = 12484; break; } case 988: // Improved Blizzard (Rank 2) { - if (!procSpell || procSpell->SpellVisual!=9487) + if (!procSpell || procSpell->SpellVisual[0]!=9487) return false; triggered_spell_id = 12485; break; } case 989: // Improved Blizzard (Rank 3) { - if (!procSpell || procSpell->SpellVisual!=9487) + if (!procSpell || procSpell->SpellVisual[0]!=9487) return false; triggered_spell_id = 12486; break; @@ -8358,6 +8411,9 @@ void Unit::SetPet(Pet* pet) void Unit::SetCharm(Unit* pet) { SetUInt64Value(UNIT_FIELD_CHARM, pet ? pet->GetGUID() : 0); + + if(GetTypeId() == TYPEID_PLAYER) + ((Player*)this)->m_mover = pet ? pet : this; } void Unit::UnsummonAllTotems() @@ -8381,6 +8437,7 @@ void Unit::SendHealSpellLog(Unit *pVictim, uint32 SpellID, uint32 Damage, bool c data.append(GetPackGUID()); data << uint32(SpellID); data << uint32(Damage); + data << uint32(0); // over healing? data << uint8(critical ? 1 : 0); data << uint8(0); // unused in client? SendMessageToSet(&data, true); @@ -8807,14 +8864,8 @@ int32 Unit::SpellBaseDamageBonus(SpellSchoolMask schoolMask) { if((*i)->GetModifier()->m_miscvalue & schoolMask) { - SpellEntry const* iSpellProto = (*i)->GetSpellProto(); - uint8 eff = (*i)->GetEffIndex(); - - // stat used dependent from next effect aura SPELL_AURA_MOD_SPELL_HEALING presence and misc value (stat index) - Stats usedStat = STAT_INTELLECT; - if(eff < 2 && iSpellProto->EffectApplyAuraName[eff+1]==SPELL_AURA_MOD_SPELL_HEALING_OF_STAT_PERCENT) - usedStat = Stats(iSpellProto->EffectMiscValue[eff+1]); - + // stat used stored in miscValueB for this aura + Stats usedStat = Stats((*i)->GetMiscBValue()); DoneAdvertisedBenefit += int32(GetStat(usedStat) * (*i)->GetModifier()->m_amount / 100.0f); } } @@ -8984,7 +9035,7 @@ uint32 Unit::SpellHealingBonus(SpellEntry const *spellProto, uint32 healamount, AuraList const& mDummyAuras = pVictim->GetAurasByType(SPELL_AURA_DUMMY); for(AuraList::const_iterator i = mDummyAuras.begin();i != mDummyAuras.end(); ++i) { - if((*i)->GetSpellProto()->SpellVisual == 9180) + if((*i)->GetSpellProto()->SpellVisual[0] == 9180) { // Flash of Light if ((spellProto->SpellFamilyFlags & 0x0000000040000000LL) && (*i)->GetEffIndex() == 1) @@ -10070,38 +10121,37 @@ void Unit::SetSpeed(UnitMoveType mtype, float rate, bool forced) propagateSpeedChange(); - // Send speed change packet only for player - if (GetTypeId()!=TYPEID_PLAYER) - return; - WorldPacket data; if(!forced) { switch(mtype) { case MOVE_WALK: - data.Initialize(MSG_MOVE_SET_WALK_SPEED, 8+4+1+4+4+4+4+4+4+4); + data.Initialize(MSG_MOVE_SET_WALK_SPEED, 8+4+2+4+4+4+4+4+4+4); break; case MOVE_RUN: - data.Initialize(MSG_MOVE_SET_RUN_SPEED, 8+4+1+4+4+4+4+4+4+4); + data.Initialize(MSG_MOVE_SET_RUN_SPEED, 8+4+2+4+4+4+4+4+4+4); break; case MOVE_RUN_BACK: - data.Initialize(MSG_MOVE_SET_RUN_BACK_SPEED, 8+4+1+4+4+4+4+4+4+4); + data.Initialize(MSG_MOVE_SET_RUN_BACK_SPEED, 8+4+2+4+4+4+4+4+4+4); break; case MOVE_SWIM: - data.Initialize(MSG_MOVE_SET_SWIM_SPEED, 8+4+1+4+4+4+4+4+4+4); + data.Initialize(MSG_MOVE_SET_SWIM_SPEED, 8+4+2+4+4+4+4+4+4+4); break; case MOVE_SWIM_BACK: - data.Initialize(MSG_MOVE_SET_SWIM_BACK_SPEED, 8+4+1+4+4+4+4+4+4+4); + data.Initialize(MSG_MOVE_SET_SWIM_BACK_SPEED, 8+4+2+4+4+4+4+4+4+4); break; case MOVE_TURN_RATE: - data.Initialize(MSG_MOVE_SET_TURN_RATE, 8+4+1+4+4+4+4+4+4+4); + data.Initialize(MSG_MOVE_SET_TURN_RATE, 8+4+2+4+4+4+4+4+4+4); break; case MOVE_FLIGHT: - data.Initialize(MSG_MOVE_SET_FLIGHT_SPEED, 8+4+1+4+4+4+4+4+4+4); + data.Initialize(MSG_MOVE_SET_FLIGHT_SPEED, 8+4+2+4+4+4+4+4+4+4); break; case MOVE_FLIGHT_BACK: - data.Initialize(MSG_MOVE_SET_FLIGHT_BACK_SPEED, 8+4+1+4+4+4+4+4+4+4); + data.Initialize(MSG_MOVE_SET_FLIGHT_BACK_SPEED, 8+4+2+4+4+4+4+4+4+4); + break; + case MOVE_PITCH_RATE: + data.Initialize(MSG_MOVE_SET_PITCH_RATE, 8+4+2+4+4+4+4+4+4+4); break; default: sLog.outError("Unit::SetSpeed: Unsupported move type (%d), data not sent to client.",mtype); @@ -10109,22 +10159,26 @@ void Unit::SetSpeed(UnitMoveType mtype, float rate, bool forced) } data.append(GetPackGUID()); - data << uint32(0); //movement flags - data << uint8(0); //unk + data << uint32(0); // movement flags + data << uint16(0); // unk flags data << uint32(getMSTime()); data << float(GetPositionX()); data << float(GetPositionY()); data << float(GetPositionZ()); data << float(GetOrientation()); - data << uint32(0); //flag unk + data << uint32(0); // fall time data << float(GetSpeed(mtype)); SendMessageToSet( &data, true ); } else { - // register forced speed changes for WorldSession::HandleForceSpeedChangeAck - // and do it only for real sent packets and use run for run/mounted as client expected - ++((Player*)this)->m_forced_speed_changes[mtype]; + if(GetTypeId() == TYPEID_PLAYER) + { + // register forced speed changes for WorldSession::HandleForceSpeedChangeAck + // and do it only for real sent packets and use run for run/mounted as client expected + ++((Player*)this)->m_forced_speed_changes[mtype]; + } + switch(mtype) { case MOVE_WALK: @@ -10151,6 +10205,9 @@ void Unit::SetSpeed(UnitMoveType mtype, float rate, bool forced) case MOVE_FLIGHT_BACK: data.Initialize(SMSG_FORCE_FLIGHT_BACK_SPEED_CHANGE, 16); break; + case MOVE_PITCH_RATE: + data.Initialize(SMSG_FORCE_PITCH_RATE_CHANGE, 16); + break; default: sLog.outError("Unit::SetSpeed: Unsupported move type (%d), data not sent to client.",mtype); return; @@ -10224,8 +10281,16 @@ bool Unit::CanHaveThreatList() const if( !isAlive() ) return false; - // pets and totems can not have threat list - if( ((Creature*)this)->isPet() || ((Creature*)this)->isTotem() ) + // totems can not have threat list + if( ((Creature*)this)->isTotem() ) + return false; + + // vehicles can not have threat list + if( ((Creature*)this)->isVehicle() ) + return false; + + // pets can not have a threat list, unless they are controlled by a creature + if( ((Creature*)this)->isPet() && IS_PLAYER_GUID(((Pet*)this)->GetOwnerGUID()) ) return false; return true; @@ -10380,9 +10445,12 @@ int32 Unit::CalculateSpellDamage(SpellEntry const* spellProto, uint8 effect_inde uint8 comboPoints = unitPlayer ? unitPlayer->GetComboPoints() : 0; - int32 level = int32(getLevel()) - int32(spellProto->spellLevel); - if (level > spellProto->maxLevel && spellProto->maxLevel > 0) - level = spellProto->maxLevel; + int32 level = int32(getLevel()); + if (level > (int32)spellProto->maxLevel && spellProto->maxLevel > 0) + level = (int32)spellProto->maxLevel; + else if (level < (int32)spellProto->baseLevel) + level = (int32)spellProto->baseLevel; + level-= (int32)spellProto->spellLevel; float basePointsPerLevel = spellProto->EffectRealPointsPerLevel[effect_index]; float randomPointsPerLevel = spellProto->EffectDicePerLevel[effect_index]; @@ -10443,6 +10511,8 @@ int32 Unit::CalculateSpellDuration(SpellEntry const* spellProto, uint8 effect_in int32 mechanic = GetEffectMechanic(spellProto, effect_index); // Find total mod value (negative bonus) int32 durationMod_always = target->GetTotalAuraModifierByMiscValue(SPELL_AURA_MECHANIC_DURATION_MOD, mechanic); + // Modify from SPELL_AURA_MOD_DURATION_OF_EFFECTS_BY_DISPEL aura (stack always ?) + durationMod_always+=target->GetTotalAuraModifierByMiscValue(SPELL_AURA_MOD_DURATION_OF_EFFECTS_BY_DISPEL, spellProto->Dispel); // Find max mod (negative bonus) int32 durationMod_not_stack = target->GetMaxNegativeAuraModifierByMiscValue(SPELL_AURA_MECHANIC_DURATION_MOD_NOT_STACK, mechanic); @@ -10644,7 +10714,9 @@ bool Unit::HandleStatModifier(UnitMods unitMod, UnitModifierType modifierType, f case UNIT_MOD_RAGE: case UNIT_MOD_FOCUS: case UNIT_MOD_ENERGY: - case UNIT_MOD_HAPPINESS: UpdateMaxPower(GetPowerTypeByAuraGroup(unitMod)); break; + case UNIT_MOD_HAPPINESS: + case UNIT_MOD_RUNE: + case UNIT_MOD_RUNIC_POWER: UpdateMaxPower(GetPowerTypeByAuraGroup(unitMod)); break; case UNIT_MOD_RESISTANCE_HOLY: case UNIT_MOD_RESISTANCE_FIRE: @@ -10757,21 +10829,18 @@ Stats Unit::GetStatByAuraGroup(UnitMods unitMod) const Powers Unit::GetPowerTypeByAuraGroup(UnitMods unitMod) const { - Powers power = POWER_MANA; - switch(unitMod) { - case UNIT_MOD_MANA: power = POWER_MANA; break; - case UNIT_MOD_RAGE: power = POWER_RAGE; break; - case UNIT_MOD_FOCUS: power = POWER_FOCUS; break; - case UNIT_MOD_ENERGY: power = POWER_ENERGY; break; - case UNIT_MOD_HAPPINESS: power = POWER_HAPPINESS; break; - - default: - break; + case UNIT_MOD_MANA: return POWER_MANA; + case UNIT_MOD_RAGE: return POWER_RAGE; + case UNIT_MOD_FOCUS: return POWER_FOCUS; + case UNIT_MOD_ENERGY: return POWER_ENERGY; + case UNIT_MOD_HAPPINESS: return POWER_HAPPINESS; + case UNIT_MOD_RUNE: return POWER_RUNE; + case UNIT_MOD_RUNIC_POWER:return POWER_RUNIC_POWER; } - return power; + return POWER_MANA; } float Unit::GetTotalAttackPowerValue(WeaponAttackType attType) const @@ -10865,6 +10934,12 @@ void Unit::SetPower(Powers power, uint32 val) SetStatInt32Value(UNIT_FIELD_POWER1 + power, val); + WorldPacket data(SMSG_POWER_UPDATE); + data.append(GetPackGUID()); + data << uint8(power); + data << uint32(val); + SendMessageToSet(&data, GetTypeId() == TYPEID_PLAYER ? true : false); + // group update if(GetTypeId() == TYPEID_PLAYER) { @@ -10978,6 +11053,7 @@ uint32 Unit::GetCreatePowers( Powers power ) const case POWER_FOCUS: return (GetTypeId()==TYPEID_PLAYER || !((Creature const*)this)->isPet() || ((Pet const*)this)->getPetType()!=HUNTER_PET ? 0 : 100); case POWER_ENERGY: return 100; case POWER_HAPPINESS: return (GetTypeId()==TYPEID_PLAYER || !((Creature const*)this)->isPet() || ((Pet const*)this)->getPetType()!=HUNTER_PET ? 0 : 1050000); + case POWER_RUNIC_POWER: return 1000; } return 0; @@ -11056,7 +11132,7 @@ void CharmInfo::InitEmptyActionBar() { for(uint32 x = 1; x < 10; ++x) { - PetActionBar[x].Type = ACT_CAST; + PetActionBar[x].Type = ACT_PASSIVE; PetActionBar[x].SpellOrAction = 0; } PetActionBar[0].Type = ACT_COMMAND; @@ -11075,7 +11151,7 @@ void CharmInfo::InitPossessCreateSpells() if (IsPassiveSpell(((Creature*)m_unit)->m_spells[x])) m_unit->CastSpell(m_unit, ((Creature*)m_unit)->m_spells[x], true); else - AddSpellToAB(0, ((Creature*)m_unit)->m_spells[x], ACT_CAST); + AddSpellToAB(0, ((Creature*)m_unit)->m_spells[x], ACT_PASSIVE); } } @@ -11118,7 +11194,7 @@ void CharmInfo::InitCharmCreateSpells() if(onlyselfcast || !IsPositiveSpell(spellId)) //only self cast and spells versus enemies are autocastable newstate = ACT_DISABLED; else - newstate = ACT_CAST; + newstate = ACT_PASSIVE; AddSpellToAB(0, spellId, newstate); } @@ -11129,7 +11205,7 @@ bool CharmInfo::AddSpellToAB(uint32 oldid, uint32 newid, ActiveStates newstate) { for(uint8 i = 0; i < 10; i++) { - if((PetActionBar[i].Type == ACT_DISABLED || PetActionBar[i].Type == ACT_ENABLED || PetActionBar[i].Type == ACT_CAST) && PetActionBar[i].SpellOrAction == oldid) + if((PetActionBar[i].Type == ACT_DISABLED || PetActionBar[i].Type == ACT_ENABLED || PetActionBar[i].Type == ACT_PASSIVE) && PetActionBar[i].SpellOrAction == oldid) { PetActionBar[i].SpellOrAction = newid; if(!oldid) @@ -11744,8 +11820,11 @@ void Unit::SendPetCastFail(uint32 spellid, uint8 msg) return; WorldPacket data(SMSG_PET_CAST_FAILED, (4+1)); + data << uint8(0); // cast count? data << uint32(spellid); data << uint8(msg); + // uint32 for some reason + // uint32 for some reason ((Player*)owner)->GetSession()->SendPacket(&data); } @@ -12309,7 +12388,10 @@ Pet* Unit::CreateTamedPetFrom(Creature* creatureTarget,uint32 spell_id) pet->SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE, getFaction()); pet->SetUInt32Value(UNIT_CREATED_BY_SPELL, spell_id); - if(!pet->InitStatsForLevel(creatureTarget->getLevel())) + uint32 level = (creatureTarget->getLevel() < (getLevel() - 5)) ? (getLevel() - 5) : creatureTarget->getLevel(); + pet->SetFreeTalentPoints(pet->GetMaxTalentPointsForLevel(level)); + + if(!pet->InitStatsForLevel(level)) { sLog.outError("ERROR: Pet::InitStatsForLevel() failed for creature (Entry: %u)!",creatureTarget->GetEntry()); delete pet; @@ -12440,10 +12522,8 @@ bool Unit::HandleMeandingAuraProc( Aura* triggeredByAura ) mod->value = jumps-5; // negative mod->type = SPELLMOD_FLAT; mod->spellId = spellProto->Id; - mod->effectId = effIdx; - mod->lastAffected = NULL; - mod->mask = spellProto->SpellFamilyFlags; - mod->charges = 0; + mod->mask = spellProto->SpellFamilyFlags; + mod->mask2 = spellProto->SpellFamilyFlags2; caster->AddSpellMod(mod, true); CastCustomSpell(target,spellProto->Id,&heal,NULL,NULL,true,NULL,triggeredByAura,caster->GetGUID()); diff --git a/src/game/Unit.h b/src/game/Unit.h index 32931597f..ce1253e16 100644 --- a/src/game/Unit.h +++ b/src/game/Unit.h @@ -144,6 +144,7 @@ enum ShapeshiftForm FORM_BERSERKERSTANCE = 0x13, FORM_TEST = 0x14, FORM_ZOMBIE = 0x15, + FORM_METAMORPHOSIS = 0x16, FORM_FLIGHT_EPIC = 0x1B, FORM_SHADOW = 0x1C, FORM_FLIGHT = 0x1D, @@ -163,14 +164,14 @@ enum SheathState // byte (1 from 0..3) of UNIT_FIELD_BYTES_2 enum UnitBytes2_Flags { - UNIT_BYTE2_FLAG_UNK0 = 0x01, - UNIT_BYTE2_FLAG_UNK1 = 0x02, - UNIT_BYTE2_FLAG_UNK2 = 0x04, - UNIT_BYTE2_FLAG_UNK3 = 0x08, - UNIT_BYTE2_FLAG_AURAS = 0x10, // show possitive auras as positive, and allow its dispel - UNIT_BYTE2_FLAG_UNK5 = 0x20, - UNIT_BYTE2_FLAG_UNK6 = 0x40, - UNIT_BYTE2_FLAG_UNK7 = 0x80 + UNIT_BYTE2_FLAG_PVP = 0x01, + UNIT_BYTE2_FLAG_UNK1 = 0x02, + UNIT_BYTE2_FLAG_FFA_PVP = 0x04, + UNIT_BYTE2_FLAG_SANCTUARY = 0x08, + UNIT_BYTE2_FLAG_UNK4 = 0x10, + UNIT_BYTE2_FLAG_UNK5 = 0x20, + UNIT_BYTE2_FLAG_UNK6 = 0x40, + UNIT_BYTE2_FLAG_UNK7 = 0x80 }; // byte (2 from 0..3) of UNIT_FIELD_BYTES_2 @@ -208,16 +209,27 @@ enum HitInfo HITINFO_UNK1 = 0x00000001, // req correct packet structure HITINFO_NORMALSWING2 = 0x00000002, HITINFO_LEFTSWING = 0x00000004, + HITINFO_UNK2 = 0x00000008, HITINFO_MISS = 0x00000010, - HITINFO_ABSORB = 0x00000020, // plays absorb sound - HITINFO_RESIST = 0x00000040, // resisted atleast some damage - HITINFO_CRITICALHIT = 0x00000080, - HITINFO_UNK2 = 0x00000100, // wotlk? - HITINFO_UNK3 = 0x00002000, // wotlk? - HITINFO_GLANCING = 0x00004000, - HITINFO_CRUSHING = 0x00008000, - HITINFO_NOACTION = 0x00010000, - HITINFO_SWINGNOHITSOUND = 0x00080000 + HITINFO_ABSORB = 0x00000020, // absorbed damage + HITINFO_ABSORB2 = 0x00000040, // absorbed damage + HITINFO_RESIST = 0x00000080, // resisted atleast some damage + HITINFO_RESIST2 = 0x00000100, // resisted atleast some damage + HITINFO_CRITICALHIT = 0x00000200, // critical hit + // 0x00000400 + // 0x00000800 + // 0x00001000 + HITINFO_BLOCK = 0x00002000, // blocked damage + // 0x00004000 + // 0x00008000 + HITINFO_GLANCING = 0x00010000, + HITINFO_CRUSHING = 0x00020000, + HITINFO_NOACTION = 0x00040000, // guessed + // 0x00080000 + // 0x00100000 + HITINFO_SWINGNOHITSOUND = 0x00200000, // guessed + // 0x00400000 + HITINFO_UNK3 = 0x00800000 }; //i would like to remove this: (it is defined in item.h @@ -289,11 +301,13 @@ enum UnitMods UNIT_MOD_STAT_INTELLECT, UNIT_MOD_STAT_SPIRIT, UNIT_MOD_HEALTH, - UNIT_MOD_MANA, // UNIT_MOD_MANA..UNIT_MOD_HAPPINESS must be in existed order, it's accessed by index values of Powers enum. + UNIT_MOD_MANA, // UNIT_MOD_MANA..UNIT_MOD_RUNIC_POWER must be in existed order, it's accessed by index values of Powers enum. UNIT_MOD_RAGE, UNIT_MOD_FOCUS, UNIT_MOD_ENERGY, UNIT_MOD_HAPPINESS, + UNIT_MOD_RUNE, + UNIT_MOD_RUNIC_POWER, UNIT_MOD_ARMOR, // UNIT_MOD_ARMOR..UNIT_MOD_RESISTANCE_ARCANE must be in existed order, it's accessed by index values of SpellSchools enum. UNIT_MOD_RESISTANCE_HOLY, UNIT_MOD_RESISTANCE_FIRE, @@ -313,7 +327,7 @@ enum UnitMods UNIT_MOD_RESISTANCE_START = UNIT_MOD_ARMOR, UNIT_MOD_RESISTANCE_END = UNIT_MOD_RESISTANCE_ARCANE + 1, UNIT_MOD_POWER_START = UNIT_MOD_MANA, - UNIT_MOD_POWER_END = UNIT_MOD_HAPPINESS + 1 + UNIT_MOD_POWER_END = UNIT_MOD_RUNIC_POWER + 1 }; enum BaseModGroup @@ -374,9 +388,10 @@ enum UnitMoveType MOVE_TURN_RATE = 5, MOVE_FLIGHT = 6, MOVE_FLIGHT_BACK = 7, + MOVE_PITCH_RATE = 8 }; -#define MAX_MOVE_TYPE 8 +#define MAX_MOVE_TYPE 9 extern float baseMoveSpeed[MAX_MOVE_TYPE]; @@ -414,10 +429,11 @@ enum CombatRating CR_WEAPON_SKILL_MAINHAND = 20, CR_WEAPON_SKILL_OFFHAND = 21, CR_WEAPON_SKILL_RANGED = 22, - CR_EXPERTISE = 23 + CR_EXPERTISE = 23, + CR_ARMOR_PENETRATION = 24 }; -#define MAX_COMBAT_RATING 24 +#define MAX_COMBAT_RATING 25 enum DamageEffectType { @@ -451,19 +467,19 @@ enum UnitFlags UNIT_FLAG_UNKNOWN9 = 0x00000040, UNIT_FLAG_NOT_ATTACKABLE_1 = 0x00000080, // ?? (UNIT_FLAG_PVP_ATTACKABLE | UNIT_FLAG_NOT_ATTACKABLE_1) is NON_PVP_ATTACKABLE UNIT_FLAG_UNKNOWN2 = 0x00000100, // 2.0.8 - UNIT_FLAG_UNKNOWN11 = 0x00000200, + UNIT_FLAG_UNKNOWN11 = 0x00000200, // 3.0.3 - makes you unable to attack everything UNIT_FLAG_LOOTING = 0x00000400, // loot animation UNIT_FLAG_PET_IN_COMBAT = 0x00000800, // in combat?, 2.0.8 - UNIT_FLAG_PVP = 0x00001000, + UNIT_FLAG_PVP = 0x00001000, // changed in 3.0.3 UNIT_FLAG_SILENCED = 0x00002000, // silenced, 2.1.1 UNIT_FLAG_UNKNOWN4 = 0x00004000, // 2.0.8 UNIT_FLAG_UNKNOWN13 = 0x00008000, UNIT_FLAG_UNKNOWN14 = 0x00010000, - UNIT_FLAG_PACIFIED = 0x00020000, - UNIT_FLAG_DISABLE_ROTATE = 0x00040000, // stunned, 2.1.1 + UNIT_FLAG_PACIFIED = 0x00020000, // 3.0.3 ok + UNIT_FLAG_STUNNED = 0x00040000, // 3.0.3 ok UNIT_FLAG_IN_COMBAT = 0x00080000, UNIT_FLAG_TAXI_FLIGHT = 0x00100000, // disable casting at client side spell not allowed by taxi flight (mounted?), probably used with 0x4 flag - UNIT_FLAG_DISARMED = 0x00200000, // disable melee spells casting..., "Required melee weapon" added to melee spells tooltip. + UNIT_FLAG_DISARMED = 0x00200000, // 3.0.3, disable melee spells casting..., "Required melee weapon" added to melee spells tooltip. UNIT_FLAG_CONFUSED = 0x00400000, UNIT_FLAG_FLEEING = 0x00800000, UNIT_FLAG_UNKNOWN5 = 0x01000000, // used in spell Eyes of the Beast for pet... @@ -478,9 +494,10 @@ enum UnitFlags // Value masks for UNIT_FIELD_FLAGS_2 enum UnitFlags2 { - UNIT_FLAG2_FEIGN_DEATH = 0x00000001, - UNIT_FLAG2_COMPREHEND_LANG= 0x00000008, - UNIT_FLAG2_FORCE_MOVE = 0x00000040 + UNIT_FLAG2_FEIGN_DEATH = 0x00000001, + UNIT_FLAG2_COMPREHEND_LANG = 0x00000008, + UNIT_FLAG2_FORCE_MOVE = 0x00000040, + UNIT_FLAG2_REGENERATE_POWER = 0x00000800 }; /// Non Player Character flags @@ -625,8 +642,18 @@ uint32 createProcExtendMask(SpellNonMeleeDamage *damageInfo, SpellMissInfo missC struct UnitActionBarEntry { - uint32 Type; - uint32 SpellOrAction; + union + { + struct + { + uint16 SpellOrAction; + uint16 Type; + }; + struct + { + uint32 Raw; + }; + }; }; #define MAX_DECLINED_NAME_CASES 5 @@ -648,13 +675,12 @@ enum CurrentSpellTypes enum ActiveStates { - ACT_ENABLED = 0xC100, - ACT_DISABLED = 0x8100, - ACT_COMMAND = 0x0700, - ACT_REACTION = 0x0600, - ACT_CAST = 0x0100, - ACT_PASSIVE = 0x0000, - ACT_DECIDE = 0x0001 + ACT_PASSIVE = 0x0100, // 0x0100 - passive + ACT_DISABLED = 0x8100, // 0x8000 - castable + ACT_ENABLED = 0xC100, // 0x4000 | 0x8000 - auto cast + castable + ACT_COMMAND = 0x0700, // 0x0100 | 0x0200 | 0x0400 + ACT_REACTION = 0x0600, // 0x0200 | 0x0400 + ACT_DECIDE = 0x0001 // what is it? }; enum ReactStates @@ -741,6 +767,7 @@ class MANGOS_DLL_SPEC Unit : public WorldObject typedef std::list Diminishing; typedef std::set AuraTypeSet; typedef std::set ComboPointHolderSet; + typedef std::map VisibleAuraMap; virtual ~Unit ( ); @@ -860,8 +887,14 @@ class MANGOS_DLL_SPEC Unit : public WorldObject return false; } - bool IsPvP() const { return HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PVP); } - void SetPvP(bool state) { if(state) SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PVP); else RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PVP); } + bool IsPvP() const { return HasByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_PVP); } + void SetPvP(bool state) + { + if(state) + SetByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_PVP); + else + RemoveByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_PVP); + } uint32 GetCreatureType() const; uint32 GetCreatureTypeMask() const { @@ -1068,6 +1101,7 @@ class MANGOS_DLL_SPEC Unit : public WorldObject void RemoveAurasWithDispelType( DispelType type ); void RemoveAllAuras(); + void RemoveArenaAuras(bool onleave = false); void RemoveAllAurasOnDeath(); void DelayAura(uint32 spellId, uint32 effindex, int32 delaytime); @@ -1189,6 +1223,30 @@ class MANGOS_DLL_SPEC Unit : public WorldObject void removeHatedBy(HostilReference* /*pHostilReference*/ ) { /* nothing to do yet */ } HostilRefManager& getHostilRefManager() { return m_HostilRefManager; } + uint32 GetVisibleAura(uint8 slot) + { + VisibleAuraMap::iterator itr = m_visibleAuras.find(slot); + if(itr != m_visibleAuras.end()) + return itr->second; + return 0; + } + void SetVisibleAura(uint8 slot, uint32 spellid) + { + if(spellid == 0) + { + VisibleAuraMap::iterator itr = m_visibleAuras.find(slot); + if(itr != m_visibleAuras.end()) + { + m_visibleAuras.erase(itr); + return; + } + } + else + m_visibleAuras[slot] = spellid; + } + VisibleAuraMap const *GetVisibleAuras() { return &m_visibleAuras; } + uint8 GetVisibleAurasCount() { return m_visibleAuras.size(); } + Aura* GetAura(uint32 spellId, uint32 effindex); AuraMap & GetAuras() { return m_Auras; } AuraMap const& GetAuras() const { return m_Auras; } @@ -1362,6 +1420,7 @@ class MANGOS_DLL_SPEC Unit : public WorldObject float m_weaponDamage[MAX_ATTACK][2]; bool m_canModifyStats; //std::list< spellEffectPair > AuraSpells[TOTAL_AURAS]; // TODO: use this if ok for mem + VisibleAuraMap m_visibleAuras; float m_speed_rate[MAX_MOVE_TYPE]; @@ -1373,6 +1432,7 @@ class MANGOS_DLL_SPEC Unit : public WorldObject uint32 m_unit_movement_flags; uint32 m_reactiveTimer[MAX_REACTIVE]; + uint32 m_regenTimer; private: void SendAttackStop(Unit* victim); // only from AttackStop(Unit*) diff --git a/src/game/UpdateData.cpp b/src/game/UpdateData.cpp index 6e1fc3030..6113f64b1 100644 --- a/src/game/UpdateData.cpp +++ b/src/game/UpdateData.cpp @@ -106,7 +106,7 @@ bool UpdateData::BuildPacket(WorldPacket *packet, bool hasTransport) ByteBuffer buf(m_data.size() + 10 + m_outOfRangeGUIDs.size()*8); buf << (uint32) (!m_outOfRangeGUIDs.empty() ? m_blockCount + 1 : m_blockCount); - buf << (uint8) (hasTransport ? 1 : 0); + //buf << (uint8) (hasTransport ? 1 : 0); if(!m_outOfRangeGUIDs.empty()) { diff --git a/src/game/UpdateData.h b/src/game/UpdateData.h index 54ef734dc..aff6d47e5 100644 --- a/src/game/UpdateData.h +++ b/src/game/UpdateData.h @@ -36,11 +36,12 @@ enum OBJECT_UPDATE_FLAGS UPDATEFLAG_NONE = 0x00, UPDATEFLAG_SELF = 0x01, UPDATEFLAG_TRANSPORT = 0x02, - UPDATEFLAG_FULLGUID = 0x04, + UPDATEFLAG_HAS_TARGET = 0x04, UPDATEFLAG_LOWGUID = 0x08, UPDATEFLAG_HIGHGUID = 0x10, UPDATEFLAG_LIVING = 0x20, - UPDATEFLAG_HASPOSITION = 0x40 + UPDATEFLAG_HAS_POSITION = 0x40, + UPDATEFLAG_VEHICLE = 0x80 }; class UpdateData diff --git a/src/game/UpdateFields.h b/src/game/UpdateFields.h index 1fba2467c..09953bea5 100644 --- a/src/game/UpdateFields.h +++ b/src/game/UpdateFields.h @@ -19,7 +19,7 @@ #ifndef _UPDATEFIELDS_AUTO_H #define _UPDATEFIELDS_AUTO_H -// Auto generated for version 2, 4, 3, 8606 +// Auto generated for version 3, 0, 3, 9183 enum EObjectFields { @@ -41,13 +41,37 @@ enum EItemFields ITEM_FIELD_DURATION = OBJECT_END + 0x0009, // Size: 1, Type: INT, Flags: OWNER_ONLY, UNK2 ITEM_FIELD_SPELL_CHARGES = OBJECT_END + 0x000A, // Size: 5, Type: INT, Flags: OWNER_ONLY, UNK2 ITEM_FIELD_FLAGS = OBJECT_END + 0x000F, // Size: 1, Type: INT, Flags: PUBLIC - ITEM_FIELD_ENCHANTMENT = OBJECT_END + 0x0010, // Size: 33, Type: INT, Flags: PUBLIC - ITEM_FIELD_PROPERTY_SEED = OBJECT_END + 0x0031, // Size: 1, Type: INT, Flags: PUBLIC - ITEM_FIELD_RANDOM_PROPERTIES_ID = OBJECT_END + 0x0032, // Size: 1, Type: INT, Flags: PUBLIC - ITEM_FIELD_ITEM_TEXT_ID = OBJECT_END + 0x0033, // Size: 1, Type: INT, Flags: OWNER_ONLY - ITEM_FIELD_DURABILITY = OBJECT_END + 0x0034, // Size: 1, Type: INT, Flags: OWNER_ONLY, UNK2 - ITEM_FIELD_MAXDURABILITY = OBJECT_END + 0x0035, // Size: 1, Type: INT, Flags: OWNER_ONLY, UNK2 - ITEM_END = OBJECT_END + 0x0036, + ITEM_FIELD_ENCHANTMENT_1_1 = OBJECT_END + 0x0010, // Size: 2, Type: INT, Flags: PUBLIC + ITEM_FIELD_ENCHANTMENT_1_3 = OBJECT_END + 0x0012, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC + ITEM_FIELD_ENCHANTMENT_2_1 = OBJECT_END + 0x0013, // Size: 2, Type: INT, Flags: PUBLIC + ITEM_FIELD_ENCHANTMENT_2_3 = OBJECT_END + 0x0015, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC + ITEM_FIELD_ENCHANTMENT_3_1 = OBJECT_END + 0x0016, // Size: 2, Type: INT, Flags: PUBLIC + ITEM_FIELD_ENCHANTMENT_3_3 = OBJECT_END + 0x0018, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC + ITEM_FIELD_ENCHANTMENT_4_1 = OBJECT_END + 0x0019, // Size: 2, Type: INT, Flags: PUBLIC + ITEM_FIELD_ENCHANTMENT_4_3 = OBJECT_END + 0x001B, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC + ITEM_FIELD_ENCHANTMENT_5_1 = OBJECT_END + 0x001C, // Size: 2, Type: INT, Flags: PUBLIC + ITEM_FIELD_ENCHANTMENT_5_3 = OBJECT_END + 0x001E, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC + ITEM_FIELD_ENCHANTMENT_6_1 = OBJECT_END + 0x001F, // Size: 2, Type: INT, Flags: PUBLIC + ITEM_FIELD_ENCHANTMENT_6_3 = OBJECT_END + 0x0021, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC + ITEM_FIELD_ENCHANTMENT_7_1 = OBJECT_END + 0x0022, // Size: 2, Type: INT, Flags: PUBLIC + ITEM_FIELD_ENCHANTMENT_7_3 = OBJECT_END + 0x0024, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC + ITEM_FIELD_ENCHANTMENT_8_1 = OBJECT_END + 0x0025, // Size: 2, Type: INT, Flags: PUBLIC + ITEM_FIELD_ENCHANTMENT_8_3 = OBJECT_END + 0x0027, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC + ITEM_FIELD_ENCHANTMENT_9_1 = OBJECT_END + 0x0028, // Size: 2, Type: INT, Flags: PUBLIC + ITEM_FIELD_ENCHANTMENT_9_3 = OBJECT_END + 0x002A, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC + ITEM_FIELD_ENCHANTMENT_10_1 = OBJECT_END + 0x002B, // Size: 2, Type: INT, Flags: PUBLIC + ITEM_FIELD_ENCHANTMENT_10_3 = OBJECT_END + 0x002D, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC + ITEM_FIELD_ENCHANTMENT_11_1 = OBJECT_END + 0x002E, // Size: 2, Type: INT, Flags: PUBLIC + ITEM_FIELD_ENCHANTMENT_11_3 = OBJECT_END + 0x0030, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC + ITEM_FIELD_ENCHANTMENT_12_1 = OBJECT_END + 0x0031, // Size: 2, Type: INT, Flags: PUBLIC + ITEM_FIELD_ENCHANTMENT_12_3 = OBJECT_END + 0x0033, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC + ITEM_FIELD_PROPERTY_SEED = OBJECT_END + 0x0034, // Size: 1, Type: INT, Flags: PUBLIC + ITEM_FIELD_RANDOM_PROPERTIES_ID = OBJECT_END + 0x0035, // Size: 1, Type: INT, Flags: PUBLIC + ITEM_FIELD_ITEM_TEXT_ID = OBJECT_END + 0x0036, // Size: 1, Type: INT, Flags: OWNER_ONLY + ITEM_FIELD_DURABILITY = OBJECT_END + 0x0037, // Size: 1, Type: INT, Flags: OWNER_ONLY, UNK2 + ITEM_FIELD_MAXDURABILITY = OBJECT_END + 0x0038, // Size: 1, Type: INT, Flags: OWNER_ONLY, UNK2 + ITEM_FIELD_PAD = OBJECT_END + 0x0039, // Size: 1, Type: INT, Flags: NONE + ITEM_END = OBJECT_END + 0x003A, }; enum EContainerFields @@ -62,93 +86,94 @@ enum EUnitFields { UNIT_FIELD_CHARM = OBJECT_END + 0x0000, // Size: 2, Type: LONG, Flags: PUBLIC UNIT_FIELD_SUMMON = OBJECT_END + 0x0002, // Size: 2, Type: LONG, Flags: PUBLIC - UNIT_FIELD_CHARMEDBY = OBJECT_END + 0x0004, // Size: 2, Type: LONG, Flags: PUBLIC - UNIT_FIELD_SUMMONEDBY = OBJECT_END + 0x0006, // Size: 2, Type: LONG, Flags: PUBLIC - UNIT_FIELD_CREATEDBY = OBJECT_END + 0x0008, // Size: 2, Type: LONG, Flags: PUBLIC - UNIT_FIELD_TARGET = OBJECT_END + 0x000A, // Size: 2, Type: LONG, Flags: PUBLIC - UNIT_FIELD_PERSUADED = OBJECT_END + 0x000C, // Size: 2, Type: LONG, Flags: PUBLIC + UNIT_FIELD_CRITTER = OBJECT_END + 0x0004, // Size: 2, Type: LONG, Flags: PRIVATE + UNIT_FIELD_CHARMEDBY = OBJECT_END + 0x0006, // Size: 2, Type: LONG, Flags: PUBLIC + UNIT_FIELD_SUMMONEDBY = OBJECT_END + 0x0008, // Size: 2, Type: LONG, Flags: PUBLIC + UNIT_FIELD_CREATEDBY = OBJECT_END + 0x000A, // Size: 2, Type: LONG, Flags: PUBLIC + UNIT_FIELD_TARGET = OBJECT_END + 0x000C, // Size: 2, Type: LONG, Flags: PUBLIC UNIT_FIELD_CHANNEL_OBJECT = OBJECT_END + 0x000E, // Size: 2, Type: LONG, Flags: PUBLIC - UNIT_FIELD_HEALTH = OBJECT_END + 0x0010, // Size: 1, Type: INT, Flags: DYNAMIC - UNIT_FIELD_POWER1 = OBJECT_END + 0x0011, // Size: 1, Type: INT, Flags: PUBLIC - UNIT_FIELD_POWER2 = OBJECT_END + 0x0012, // Size: 1, Type: INT, Flags: PUBLIC - UNIT_FIELD_POWER3 = OBJECT_END + 0x0013, // Size: 1, Type: INT, Flags: PUBLIC - UNIT_FIELD_POWER4 = OBJECT_END + 0x0014, // Size: 1, Type: INT, Flags: PUBLIC - UNIT_FIELD_POWER5 = OBJECT_END + 0x0015, // Size: 1, Type: INT, Flags: PUBLIC - UNIT_FIELD_MAXHEALTH = OBJECT_END + 0x0016, // Size: 1, Type: INT, Flags: DYNAMIC - UNIT_FIELD_MAXPOWER1 = OBJECT_END + 0x0017, // Size: 1, Type: INT, Flags: PUBLIC - UNIT_FIELD_MAXPOWER2 = OBJECT_END + 0x0018, // Size: 1, Type: INT, Flags: PUBLIC - UNIT_FIELD_MAXPOWER3 = OBJECT_END + 0x0019, // Size: 1, Type: INT, Flags: PUBLIC - UNIT_FIELD_MAXPOWER4 = OBJECT_END + 0x001A, // Size: 1, Type: INT, Flags: PUBLIC - UNIT_FIELD_MAXPOWER5 = OBJECT_END + 0x001B, // Size: 1, Type: INT, Flags: PUBLIC - UNIT_FIELD_LEVEL = OBJECT_END + 0x001C, // Size: 1, Type: INT, Flags: PUBLIC - UNIT_FIELD_FACTIONTEMPLATE = OBJECT_END + 0x001D, // Size: 1, Type: INT, Flags: PUBLIC - UNIT_FIELD_BYTES_0 = OBJECT_END + 0x001E, // Size: 1, Type: BYTES, Flags: PUBLIC - UNIT_VIRTUAL_ITEM_SLOT_DISPLAY = OBJECT_END + 0x001F, // Size: 3, Type: INT, Flags: PUBLIC - UNIT_VIRTUAL_ITEM_INFO = OBJECT_END + 0x0022, // Size: 6, Type: BYTES, Flags: PUBLIC - UNIT_FIELD_FLAGS = OBJECT_END + 0x0028, // Size: 1, Type: INT, Flags: PUBLIC - UNIT_FIELD_FLAGS_2 = OBJECT_END + 0x0029, // Size: 1, Type: INT, Flags: PUBLIC - UNIT_FIELD_AURA = OBJECT_END + 0x002A, // Size: 56, Type: INT, Flags: PUBLIC - UNIT_FIELD_AURAFLAGS = OBJECT_END + 0x0062, // Size: 14, Type: BYTES, Flags: PUBLIC - UNIT_FIELD_AURALEVELS = OBJECT_END + 0x0070, // Size: 14, Type: BYTES, Flags: PUBLIC - UNIT_FIELD_AURAAPPLICATIONS = OBJECT_END + 0x007E, // Size: 14, Type: BYTES, Flags: PUBLIC - UNIT_FIELD_AURASTATE = OBJECT_END + 0x008C, // Size: 1, Type: INT, Flags: PUBLIC - UNIT_FIELD_BASEATTACKTIME = OBJECT_END + 0x008D, // Size: 2, Type: INT, Flags: PUBLIC - UNIT_FIELD_RANGEDATTACKTIME = OBJECT_END + 0x008F, // Size: 1, Type: INT, Flags: PRIVATE - UNIT_FIELD_BOUNDINGRADIUS = OBJECT_END + 0x0090, // Size: 1, Type: FLOAT, Flags: PUBLIC - UNIT_FIELD_COMBATREACH = OBJECT_END + 0x0091, // Size: 1, Type: FLOAT, Flags: PUBLIC - UNIT_FIELD_DISPLAYID = OBJECT_END + 0x0092, // Size: 1, Type: INT, Flags: PUBLIC - UNIT_FIELD_NATIVEDISPLAYID = OBJECT_END + 0x0093, // Size: 1, Type: INT, Flags: PUBLIC - UNIT_FIELD_MOUNTDISPLAYID = OBJECT_END + 0x0094, // Size: 1, Type: INT, Flags: PUBLIC - UNIT_FIELD_MINDAMAGE = OBJECT_END + 0x0095, // Size: 1, Type: FLOAT, Flags: PRIVATE, OWNER_ONLY, UNK3 - UNIT_FIELD_MAXDAMAGE = OBJECT_END + 0x0096, // Size: 1, Type: FLOAT, Flags: PRIVATE, OWNER_ONLY, UNK3 - UNIT_FIELD_MINOFFHANDDAMAGE = OBJECT_END + 0x0097, // Size: 1, Type: FLOAT, Flags: PRIVATE, OWNER_ONLY, UNK3 - UNIT_FIELD_MAXOFFHANDDAMAGE = OBJECT_END + 0x0098, // Size: 1, Type: FLOAT, Flags: PRIVATE, OWNER_ONLY, UNK3 - UNIT_FIELD_BYTES_1 = OBJECT_END + 0x0099, // Size: 1, Type: BYTES, Flags: PUBLIC - UNIT_FIELD_PETNUMBER = OBJECT_END + 0x009A, // Size: 1, Type: INT, Flags: PUBLIC - UNIT_FIELD_PET_NAME_TIMESTAMP = OBJECT_END + 0x009B, // Size: 1, Type: INT, Flags: PUBLIC - UNIT_FIELD_PETEXPERIENCE = OBJECT_END + 0x009C, // Size: 1, Type: INT, Flags: OWNER_ONLY - UNIT_FIELD_PETNEXTLEVELEXP = OBJECT_END + 0x009D, // Size: 1, Type: INT, Flags: OWNER_ONLY - UNIT_DYNAMIC_FLAGS = OBJECT_END + 0x009E, // Size: 1, Type: INT, Flags: DYNAMIC - UNIT_CHANNEL_SPELL = OBJECT_END + 0x009F, // Size: 1, Type: INT, Flags: PUBLIC - UNIT_MOD_CAST_SPEED = OBJECT_END + 0x00A0, // Size: 1, Type: FLOAT, Flags: PUBLIC - UNIT_CREATED_BY_SPELL = OBJECT_END + 0x00A1, // Size: 1, Type: INT, Flags: PUBLIC - UNIT_NPC_FLAGS = OBJECT_END + 0x00A2, // Size: 1, Type: INT, Flags: DYNAMIC - UNIT_NPC_EMOTESTATE = OBJECT_END + 0x00A3, // Size: 1, Type: INT, Flags: PUBLIC - UNIT_TRAINING_POINTS = OBJECT_END + 0x00A4, // Size: 1, Type: TWO_SHORT, Flags: OWNER_ONLY - UNIT_FIELD_STAT0 = OBJECT_END + 0x00A5, // Size: 1, Type: INT, Flags: PRIVATE, OWNER_ONLY - UNIT_FIELD_STAT1 = OBJECT_END + 0x00A6, // Size: 1, Type: INT, Flags: PRIVATE, OWNER_ONLY - UNIT_FIELD_STAT2 = OBJECT_END + 0x00A7, // Size: 1, Type: INT, Flags: PRIVATE, OWNER_ONLY - UNIT_FIELD_STAT3 = OBJECT_END + 0x00A8, // Size: 1, Type: INT, Flags: PRIVATE, OWNER_ONLY - UNIT_FIELD_STAT4 = OBJECT_END + 0x00A9, // Size: 1, Type: INT, Flags: PRIVATE, OWNER_ONLY - UNIT_FIELD_POSSTAT0 = OBJECT_END + 0x00AA, // Size: 1, Type: INT, Flags: PRIVATE, OWNER_ONLY - UNIT_FIELD_POSSTAT1 = OBJECT_END + 0x00AB, // Size: 1, Type: INT, Flags: PRIVATE, OWNER_ONLY - UNIT_FIELD_POSSTAT2 = OBJECT_END + 0x00AC, // Size: 1, Type: INT, Flags: PRIVATE, OWNER_ONLY - UNIT_FIELD_POSSTAT3 = OBJECT_END + 0x00AD, // Size: 1, Type: INT, Flags: PRIVATE, OWNER_ONLY - UNIT_FIELD_POSSTAT4 = OBJECT_END + 0x00AE, // Size: 1, Type: INT, Flags: PRIVATE, OWNER_ONLY - UNIT_FIELD_NEGSTAT0 = OBJECT_END + 0x00AF, // Size: 1, Type: INT, Flags: PRIVATE, OWNER_ONLY - UNIT_FIELD_NEGSTAT1 = OBJECT_END + 0x00B0, // Size: 1, Type: INT, Flags: PRIVATE, OWNER_ONLY - UNIT_FIELD_NEGSTAT2 = OBJECT_END + 0x00B1, // Size: 1, Type: INT, Flags: PRIVATE, OWNER_ONLY - UNIT_FIELD_NEGSTAT3 = OBJECT_END + 0x00B2, // Size: 1, Type: INT, Flags: PRIVATE, OWNER_ONLY - UNIT_FIELD_NEGSTAT4 = OBJECT_END + 0x00B3, // Size: 1, Type: INT, Flags: PRIVATE, OWNER_ONLY - UNIT_FIELD_RESISTANCES = OBJECT_END + 0x00B4, // Size: 7, Type: INT, Flags: PRIVATE, OWNER_ONLY, UNK3 - UNIT_FIELD_RESISTANCEBUFFMODSPOSITIVE = OBJECT_END + 0x00BB, // Size: 7, Type: INT, Flags: PRIVATE, OWNER_ONLY - UNIT_FIELD_RESISTANCEBUFFMODSNEGATIVE = OBJECT_END + 0x00C2, // Size: 7, Type: INT, Flags: PRIVATE, OWNER_ONLY - UNIT_FIELD_BASE_MANA = OBJECT_END + 0x00C9, // Size: 1, Type: INT, Flags: PUBLIC - UNIT_FIELD_BASE_HEALTH = OBJECT_END + 0x00CA, // Size: 1, Type: INT, Flags: PRIVATE, OWNER_ONLY - UNIT_FIELD_BYTES_2 = OBJECT_END + 0x00CB, // Size: 1, Type: BYTES, Flags: PUBLIC - UNIT_FIELD_ATTACK_POWER = OBJECT_END + 0x00CC, // Size: 1, Type: INT, Flags: PRIVATE, OWNER_ONLY - UNIT_FIELD_ATTACK_POWER_MODS = OBJECT_END + 0x00CD, // Size: 1, Type: TWO_SHORT, Flags: PRIVATE, OWNER_ONLY - UNIT_FIELD_ATTACK_POWER_MULTIPLIER = OBJECT_END + 0x00CE, // Size: 1, Type: FLOAT, Flags: PRIVATE, OWNER_ONLY - UNIT_FIELD_RANGED_ATTACK_POWER = OBJECT_END + 0x00CF, // Size: 1, Type: INT, Flags: PRIVATE, OWNER_ONLY - UNIT_FIELD_RANGED_ATTACK_POWER_MODS = OBJECT_END + 0x00D0, // Size: 1, Type: TWO_SHORT, Flags: PRIVATE, OWNER_ONLY - UNIT_FIELD_RANGED_ATTACK_POWER_MULTIPLIER = OBJECT_END + 0x00D1, // Size: 1, Type: FLOAT, Flags: PRIVATE, OWNER_ONLY - UNIT_FIELD_MINRANGEDDAMAGE = OBJECT_END + 0x00D2, // Size: 1, Type: FLOAT, Flags: PRIVATE, OWNER_ONLY - UNIT_FIELD_MAXRANGEDDAMAGE = OBJECT_END + 0x00D3, // Size: 1, Type: FLOAT, Flags: PRIVATE, OWNER_ONLY - UNIT_FIELD_POWER_COST_MODIFIER = OBJECT_END + 0x00D4, // Size: 7, Type: INT, Flags: PRIVATE, OWNER_ONLY - UNIT_FIELD_POWER_COST_MULTIPLIER = OBJECT_END + 0x00DB, // Size: 7, Type: FLOAT, Flags: PRIVATE, OWNER_ONLY - UNIT_FIELD_MAXHEALTHMODIFIER = OBJECT_END + 0x00E2, // Size: 1, Type: FLOAT, Flags: PRIVATE, OWNER_ONLY - UNIT_FIELD_PADDING = OBJECT_END + 0x00E3, // Size: 1, Type: INT, Flags: NONE - UNIT_END = OBJECT_END + 0x00E4, + UNIT_FIELD_BYTES_0 = OBJECT_END + 0x0010, // Size: 1, Type: BYTES, Flags: PUBLIC + UNIT_FIELD_HEALTH = OBJECT_END + 0x0011, // Size: 1, Type: INT, Flags: PUBLIC + UNIT_FIELD_POWER1 = OBJECT_END + 0x0012, // Size: 1, Type: INT, Flags: PUBLIC + UNIT_FIELD_POWER2 = OBJECT_END + 0x0013, // Size: 1, Type: INT, Flags: PUBLIC + UNIT_FIELD_POWER3 = OBJECT_END + 0x0014, // Size: 1, Type: INT, Flags: PUBLIC + UNIT_FIELD_POWER4 = OBJECT_END + 0x0015, // Size: 1, Type: INT, Flags: PUBLIC + UNIT_FIELD_POWER5 = OBJECT_END + 0x0016, // Size: 1, Type: INT, Flags: PUBLIC + UNIT_FIELD_POWER6 = OBJECT_END + 0x0017, // Size: 1, Type: INT, Flags: PUBLIC + UNIT_FIELD_POWER7 = OBJECT_END + 0x0018, // Size: 1, Type: INT, Flags: PUBLIC + UNIT_FIELD_MAXHEALTH = OBJECT_END + 0x0019, // Size: 1, Type: INT, Flags: PUBLIC + UNIT_FIELD_MAXPOWER1 = OBJECT_END + 0x001A, // Size: 1, Type: INT, Flags: PUBLIC + UNIT_FIELD_MAXPOWER2 = OBJECT_END + 0x001B, // Size: 1, Type: INT, Flags: PUBLIC + UNIT_FIELD_MAXPOWER3 = OBJECT_END + 0x001C, // Size: 1, Type: INT, Flags: PUBLIC + UNIT_FIELD_MAXPOWER4 = OBJECT_END + 0x001D, // Size: 1, Type: INT, Flags: PUBLIC + UNIT_FIELD_MAXPOWER5 = OBJECT_END + 0x001E, // Size: 1, Type: INT, Flags: PUBLIC + UNIT_FIELD_MAXPOWER6 = OBJECT_END + 0x001F, // Size: 1, Type: INT, Flags: PUBLIC + UNIT_FIELD_MAXPOWER7 = OBJECT_END + 0x0020, // Size: 1, Type: INT, Flags: PUBLIC + UNIT_FIELD_POWER_REGEN_FLAT_MODIFIER = OBJECT_END + 0x0021, // Size: 7, Type: FLOAT, Flags: PRIVATE, OWNER_ONLY + UNIT_FIELD_POWER_REGEN_INTERRUPTED_FLAT_MODIFIER = OBJECT_END + 0x0028, // Size: 7, Type: FLOAT, Flags: PRIVATE, OWNER_ONLY + UNIT_FIELD_LEVEL = OBJECT_END + 0x002F, // Size: 1, Type: INT, Flags: PUBLIC + UNIT_FIELD_FACTIONTEMPLATE = OBJECT_END + 0x0030, // Size: 1, Type: INT, Flags: PUBLIC + UNIT_VIRTUAL_ITEM_SLOT_ID = OBJECT_END + 0x0031, // Size: 3, Type: INT, Flags: PUBLIC + UNIT_FIELD_FLAGS = OBJECT_END + 0x0034, // Size: 1, Type: INT, Flags: PUBLIC + UNIT_FIELD_FLAGS_2 = OBJECT_END + 0x0035, // Size: 1, Type: INT, Flags: PUBLIC + UNIT_FIELD_AURASTATE = OBJECT_END + 0x0036, // Size: 1, Type: INT, Flags: PUBLIC + UNIT_FIELD_BASEATTACKTIME = OBJECT_END + 0x0037, // Size: 2, Type: INT, Flags: PUBLIC + UNIT_FIELD_RANGEDATTACKTIME = OBJECT_END + 0x0039, // Size: 1, Type: INT, Flags: PRIVATE + UNIT_FIELD_BOUNDINGRADIUS = OBJECT_END + 0x003A, // Size: 1, Type: FLOAT, Flags: PUBLIC + UNIT_FIELD_COMBATREACH = OBJECT_END + 0x003B, // Size: 1, Type: FLOAT, Flags: PUBLIC + UNIT_FIELD_DISPLAYID = OBJECT_END + 0x003C, // Size: 1, Type: INT, Flags: PUBLIC + UNIT_FIELD_NATIVEDISPLAYID = OBJECT_END + 0x003D, // Size: 1, Type: INT, Flags: PUBLIC + UNIT_FIELD_MOUNTDISPLAYID = OBJECT_END + 0x003E, // Size: 1, Type: INT, Flags: PUBLIC + UNIT_FIELD_MINDAMAGE = OBJECT_END + 0x003F, // Size: 1, Type: FLOAT, Flags: PRIVATE, OWNER_ONLY, UNK3 + UNIT_FIELD_MAXDAMAGE = OBJECT_END + 0x0040, // Size: 1, Type: FLOAT, Flags: PRIVATE, OWNER_ONLY, UNK3 + UNIT_FIELD_MINOFFHANDDAMAGE = OBJECT_END + 0x0041, // Size: 1, Type: FLOAT, Flags: PRIVATE, OWNER_ONLY, UNK3 + UNIT_FIELD_MAXOFFHANDDAMAGE = OBJECT_END + 0x0042, // Size: 1, Type: FLOAT, Flags: PRIVATE, OWNER_ONLY, UNK3 + UNIT_FIELD_BYTES_1 = OBJECT_END + 0x0043, // Size: 1, Type: BYTES, Flags: PUBLIC + UNIT_FIELD_PETNUMBER = OBJECT_END + 0x0044, // Size: 1, Type: INT, Flags: PUBLIC + UNIT_FIELD_PET_NAME_TIMESTAMP = OBJECT_END + 0x0045, // Size: 1, Type: INT, Flags: PUBLIC + UNIT_FIELD_PETEXPERIENCE = OBJECT_END + 0x0046, // Size: 1, Type: INT, Flags: OWNER_ONLY + UNIT_FIELD_PETNEXTLEVELEXP = OBJECT_END + 0x0047, // Size: 1, Type: INT, Flags: OWNER_ONLY + UNIT_DYNAMIC_FLAGS = OBJECT_END + 0x0048, // Size: 1, Type: INT, Flags: DYNAMIC + UNIT_CHANNEL_SPELL = OBJECT_END + 0x0049, // Size: 1, Type: INT, Flags: PUBLIC + UNIT_MOD_CAST_SPEED = OBJECT_END + 0x004A, // Size: 1, Type: FLOAT, Flags: PUBLIC + UNIT_CREATED_BY_SPELL = OBJECT_END + 0x004B, // Size: 1, Type: INT, Flags: PUBLIC + UNIT_NPC_FLAGS = OBJECT_END + 0x004C, // Size: 1, Type: INT, Flags: DYNAMIC + UNIT_NPC_EMOTESTATE = OBJECT_END + 0x004D, // Size: 1, Type: INT, Flags: PUBLIC + UNIT_FIELD_STAT0 = OBJECT_END + 0x004E, // Size: 1, Type: INT, Flags: PRIVATE, OWNER_ONLY + UNIT_FIELD_STAT1 = OBJECT_END + 0x004F, // Size: 1, Type: INT, Flags: PRIVATE, OWNER_ONLY + UNIT_FIELD_STAT2 = OBJECT_END + 0x0050, // Size: 1, Type: INT, Flags: PRIVATE, OWNER_ONLY + UNIT_FIELD_STAT3 = OBJECT_END + 0x0051, // Size: 1, Type: INT, Flags: PRIVATE, OWNER_ONLY + UNIT_FIELD_STAT4 = OBJECT_END + 0x0052, // Size: 1, Type: INT, Flags: PRIVATE, OWNER_ONLY + UNIT_FIELD_POSSTAT0 = OBJECT_END + 0x0053, // Size: 1, Type: INT, Flags: PRIVATE, OWNER_ONLY + UNIT_FIELD_POSSTAT1 = OBJECT_END + 0x0054, // Size: 1, Type: INT, Flags: PRIVATE, OWNER_ONLY + UNIT_FIELD_POSSTAT2 = OBJECT_END + 0x0055, // Size: 1, Type: INT, Flags: PRIVATE, OWNER_ONLY + UNIT_FIELD_POSSTAT3 = OBJECT_END + 0x0056, // Size: 1, Type: INT, Flags: PRIVATE, OWNER_ONLY + UNIT_FIELD_POSSTAT4 = OBJECT_END + 0x0057, // Size: 1, Type: INT, Flags: PRIVATE, OWNER_ONLY + UNIT_FIELD_NEGSTAT0 = OBJECT_END + 0x0058, // Size: 1, Type: INT, Flags: PRIVATE, OWNER_ONLY + UNIT_FIELD_NEGSTAT1 = OBJECT_END + 0x0059, // Size: 1, Type: INT, Flags: PRIVATE, OWNER_ONLY + UNIT_FIELD_NEGSTAT2 = OBJECT_END + 0x005A, // Size: 1, Type: INT, Flags: PRIVATE, OWNER_ONLY + UNIT_FIELD_NEGSTAT3 = OBJECT_END + 0x005B, // Size: 1, Type: INT, Flags: PRIVATE, OWNER_ONLY + UNIT_FIELD_NEGSTAT4 = OBJECT_END + 0x005C, // Size: 1, Type: INT, Flags: PRIVATE, OWNER_ONLY + UNIT_FIELD_RESISTANCES = OBJECT_END + 0x005D, // Size: 7, Type: INT, Flags: PRIVATE, OWNER_ONLY, UNK3 + UNIT_FIELD_RESISTANCEBUFFMODSPOSITIVE = OBJECT_END + 0x0064, // Size: 7, Type: INT, Flags: PRIVATE, OWNER_ONLY + UNIT_FIELD_RESISTANCEBUFFMODSNEGATIVE = OBJECT_END + 0x006B, // Size: 7, Type: INT, Flags: PRIVATE, OWNER_ONLY + UNIT_FIELD_BASE_MANA = OBJECT_END + 0x0072, // Size: 1, Type: INT, Flags: PUBLIC + UNIT_FIELD_BASE_HEALTH = OBJECT_END + 0x0073, // Size: 1, Type: INT, Flags: PRIVATE, OWNER_ONLY + UNIT_FIELD_BYTES_2 = OBJECT_END + 0x0074, // Size: 1, Type: BYTES, Flags: PUBLIC + UNIT_FIELD_ATTACK_POWER = OBJECT_END + 0x0075, // Size: 1, Type: INT, Flags: PRIVATE, OWNER_ONLY + UNIT_FIELD_ATTACK_POWER_MODS = OBJECT_END + 0x0076, // Size: 1, Type: TWO_SHORT, Flags: PRIVATE, OWNER_ONLY + UNIT_FIELD_ATTACK_POWER_MULTIPLIER = OBJECT_END + 0x0077, // Size: 1, Type: FLOAT, Flags: PRIVATE, OWNER_ONLY + UNIT_FIELD_RANGED_ATTACK_POWER = OBJECT_END + 0x0078, // Size: 1, Type: INT, Flags: PRIVATE, OWNER_ONLY + UNIT_FIELD_RANGED_ATTACK_POWER_MODS = OBJECT_END + 0x0079, // Size: 1, Type: TWO_SHORT, Flags: PRIVATE, OWNER_ONLY + UNIT_FIELD_RANGED_ATTACK_POWER_MULTIPLIER = OBJECT_END + 0x007A, // Size: 1, Type: FLOAT, Flags: PRIVATE, OWNER_ONLY + UNIT_FIELD_MINRANGEDDAMAGE = OBJECT_END + 0x007B, // Size: 1, Type: FLOAT, Flags: PRIVATE, OWNER_ONLY + UNIT_FIELD_MAXRANGEDDAMAGE = OBJECT_END + 0x007C, // Size: 1, Type: FLOAT, Flags: PRIVATE, OWNER_ONLY + UNIT_FIELD_POWER_COST_MODIFIER = OBJECT_END + 0x007D, // Size: 7, Type: INT, Flags: PRIVATE, OWNER_ONLY + UNIT_FIELD_POWER_COST_MULTIPLIER = OBJECT_END + 0x0084, // Size: 7, Type: FLOAT, Flags: PRIVATE, OWNER_ONLY + UNIT_FIELD_MAXHEALTHMODIFIER = OBJECT_END + 0x008B, // Size: 1, Type: FLOAT, Flags: PRIVATE, OWNER_ONLY + UNIT_FIELD_HOVERHEIGHT = OBJECT_END + 0x008C, // Size: 1, Type: FLOAT, Flags: PUBLIC + UNIT_FIELD_PADDING = OBJECT_END + 0x008D, // Size: 1, Type: INT, Flags: NONE + UNIT_END = OBJECT_END + 0x008E, PLAYER_DUEL_ARBITER = UNIT_END + 0x0000, // Size: 2, Type: LONG, Flags: PUBLIC PLAYER_FLAGS = UNIT_END + 0x0002, // Size: 1, Type: INT, Flags: PUBLIC @@ -260,160 +285,184 @@ enum EUnitFields PLAYER_QUEST_LOG_25_3 = UNIT_END + 0x006C, // Size: 1, Type: BYTES, Flags: PRIVATE PLAYER_QUEST_LOG_25_4 = UNIT_END + 0x006D, // Size: 1, Type: INT, Flags: PRIVATE PLAYER_VISIBLE_ITEM_1_CREATOR = UNIT_END + 0x006E, // Size: 2, Type: LONG, Flags: PUBLIC - PLAYER_VISIBLE_ITEM_1_0 = UNIT_END + 0x0070, // Size: 12, Type: INT, Flags: PUBLIC - PLAYER_VISIBLE_ITEM_1_PROPERTIES = UNIT_END + 0x007C, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC - PLAYER_VISIBLE_ITEM_1_PAD = UNIT_END + 0x007D, // Size: 1, Type: INT, Flags: PUBLIC - PLAYER_VISIBLE_ITEM_2_CREATOR = UNIT_END + 0x007E, // Size: 2, Type: LONG, Flags: PUBLIC - PLAYER_VISIBLE_ITEM_2_0 = UNIT_END + 0x0080, // Size: 12, Type: INT, Flags: PUBLIC - PLAYER_VISIBLE_ITEM_2_PROPERTIES = UNIT_END + 0x008C, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC - PLAYER_VISIBLE_ITEM_2_PAD = UNIT_END + 0x008D, // Size: 1, Type: INT, Flags: PUBLIC - PLAYER_VISIBLE_ITEM_3_CREATOR = UNIT_END + 0x008E, // Size: 2, Type: LONG, Flags: PUBLIC - PLAYER_VISIBLE_ITEM_3_0 = UNIT_END + 0x0090, // Size: 12, Type: INT, Flags: PUBLIC - PLAYER_VISIBLE_ITEM_3_PROPERTIES = UNIT_END + 0x009C, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC - PLAYER_VISIBLE_ITEM_3_PAD = UNIT_END + 0x009D, // Size: 1, Type: INT, Flags: PUBLIC - PLAYER_VISIBLE_ITEM_4_CREATOR = UNIT_END + 0x009E, // Size: 2, Type: LONG, Flags: PUBLIC - PLAYER_VISIBLE_ITEM_4_0 = UNIT_END + 0x00A0, // Size: 12, Type: INT, Flags: PUBLIC - PLAYER_VISIBLE_ITEM_4_PROPERTIES = UNIT_END + 0x00AC, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC - PLAYER_VISIBLE_ITEM_4_PAD = UNIT_END + 0x00AD, // Size: 1, Type: INT, Flags: PUBLIC - PLAYER_VISIBLE_ITEM_5_CREATOR = UNIT_END + 0x00AE, // Size: 2, Type: LONG, Flags: PUBLIC - PLAYER_VISIBLE_ITEM_5_0 = UNIT_END + 0x00B0, // Size: 12, Type: INT, Flags: PUBLIC - PLAYER_VISIBLE_ITEM_5_PROPERTIES = UNIT_END + 0x00BC, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC - PLAYER_VISIBLE_ITEM_5_PAD = UNIT_END + 0x00BD, // Size: 1, Type: INT, Flags: PUBLIC - PLAYER_VISIBLE_ITEM_6_CREATOR = UNIT_END + 0x00BE, // Size: 2, Type: LONG, Flags: PUBLIC - PLAYER_VISIBLE_ITEM_6_0 = UNIT_END + 0x00C0, // Size: 12, Type: INT, Flags: PUBLIC - PLAYER_VISIBLE_ITEM_6_PROPERTIES = UNIT_END + 0x00CC, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC - PLAYER_VISIBLE_ITEM_6_PAD = UNIT_END + 0x00CD, // Size: 1, Type: INT, Flags: PUBLIC - PLAYER_VISIBLE_ITEM_7_CREATOR = UNIT_END + 0x00CE, // Size: 2, Type: LONG, Flags: PUBLIC - PLAYER_VISIBLE_ITEM_7_0 = UNIT_END + 0x00D0, // Size: 12, Type: INT, Flags: PUBLIC - PLAYER_VISIBLE_ITEM_7_PROPERTIES = UNIT_END + 0x00DC, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC - PLAYER_VISIBLE_ITEM_7_PAD = UNIT_END + 0x00DD, // Size: 1, Type: INT, Flags: PUBLIC - PLAYER_VISIBLE_ITEM_8_CREATOR = UNIT_END + 0x00DE, // Size: 2, Type: LONG, Flags: PUBLIC - PLAYER_VISIBLE_ITEM_8_0 = UNIT_END + 0x00E0, // Size: 12, Type: INT, Flags: PUBLIC - PLAYER_VISIBLE_ITEM_8_PROPERTIES = UNIT_END + 0x00EC, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC - PLAYER_VISIBLE_ITEM_8_PAD = UNIT_END + 0x00ED, // Size: 1, Type: INT, Flags: PUBLIC - PLAYER_VISIBLE_ITEM_9_CREATOR = UNIT_END + 0x00EE, // Size: 2, Type: LONG, Flags: PUBLIC - PLAYER_VISIBLE_ITEM_9_0 = UNIT_END + 0x00F0, // Size: 12, Type: INT, Flags: PUBLIC - PLAYER_VISIBLE_ITEM_9_PROPERTIES = UNIT_END + 0x00FC, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC - PLAYER_VISIBLE_ITEM_9_PAD = UNIT_END + 0x00FD, // Size: 1, Type: INT, Flags: PUBLIC - PLAYER_VISIBLE_ITEM_10_CREATOR = UNIT_END + 0x00FE, // Size: 2, Type: LONG, Flags: PUBLIC - PLAYER_VISIBLE_ITEM_10_0 = UNIT_END + 0x0100, // Size: 12, Type: INT, Flags: PUBLIC - PLAYER_VISIBLE_ITEM_10_PROPERTIES = UNIT_END + 0x010C, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC - PLAYER_VISIBLE_ITEM_10_PAD = UNIT_END + 0x010D, // Size: 1, Type: INT, Flags: PUBLIC - PLAYER_VISIBLE_ITEM_11_CREATOR = UNIT_END + 0x010E, // Size: 2, Type: LONG, Flags: PUBLIC - PLAYER_VISIBLE_ITEM_11_0 = UNIT_END + 0x0110, // Size: 12, Type: INT, Flags: PUBLIC - PLAYER_VISIBLE_ITEM_11_PROPERTIES = UNIT_END + 0x011C, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC - PLAYER_VISIBLE_ITEM_11_PAD = UNIT_END + 0x011D, // Size: 1, Type: INT, Flags: PUBLIC - PLAYER_VISIBLE_ITEM_12_CREATOR = UNIT_END + 0x011E, // Size: 2, Type: LONG, Flags: PUBLIC - PLAYER_VISIBLE_ITEM_12_0 = UNIT_END + 0x0120, // Size: 12, Type: INT, Flags: PUBLIC - PLAYER_VISIBLE_ITEM_12_PROPERTIES = UNIT_END + 0x012C, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC - PLAYER_VISIBLE_ITEM_12_PAD = UNIT_END + 0x012D, // Size: 1, Type: INT, Flags: PUBLIC - PLAYER_VISIBLE_ITEM_13_CREATOR = UNIT_END + 0x012E, // Size: 2, Type: LONG, Flags: PUBLIC - PLAYER_VISIBLE_ITEM_13_0 = UNIT_END + 0x0130, // Size: 12, Type: INT, Flags: PUBLIC - PLAYER_VISIBLE_ITEM_13_PROPERTIES = UNIT_END + 0x013C, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC - PLAYER_VISIBLE_ITEM_13_PAD = UNIT_END + 0x013D, // Size: 1, Type: INT, Flags: PUBLIC - PLAYER_VISIBLE_ITEM_14_CREATOR = UNIT_END + 0x013E, // Size: 2, Type: LONG, Flags: PUBLIC - PLAYER_VISIBLE_ITEM_14_0 = UNIT_END + 0x0140, // Size: 12, Type: INT, Flags: PUBLIC - PLAYER_VISIBLE_ITEM_14_PROPERTIES = UNIT_END + 0x014C, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC - PLAYER_VISIBLE_ITEM_14_PAD = UNIT_END + 0x014D, // Size: 1, Type: INT, Flags: PUBLIC - PLAYER_VISIBLE_ITEM_15_CREATOR = UNIT_END + 0x014E, // Size: 2, Type: LONG, Flags: PUBLIC - PLAYER_VISIBLE_ITEM_15_0 = UNIT_END + 0x0150, // Size: 12, Type: INT, Flags: PUBLIC - PLAYER_VISIBLE_ITEM_15_PROPERTIES = UNIT_END + 0x015C, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC - PLAYER_VISIBLE_ITEM_15_PAD = UNIT_END + 0x015D, // Size: 1, Type: INT, Flags: PUBLIC - PLAYER_VISIBLE_ITEM_16_CREATOR = UNIT_END + 0x015E, // Size: 2, Type: LONG, Flags: PUBLIC - PLAYER_VISIBLE_ITEM_16_0 = UNIT_END + 0x0160, // Size: 12, Type: INT, Flags: PUBLIC - PLAYER_VISIBLE_ITEM_16_PROPERTIES = UNIT_END + 0x016C, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC - PLAYER_VISIBLE_ITEM_16_PAD = UNIT_END + 0x016D, // Size: 1, Type: INT, Flags: PUBLIC - PLAYER_VISIBLE_ITEM_17_CREATOR = UNIT_END + 0x016E, // Size: 2, Type: LONG, Flags: PUBLIC - PLAYER_VISIBLE_ITEM_17_0 = UNIT_END + 0x0170, // Size: 12, Type: INT, Flags: PUBLIC - PLAYER_VISIBLE_ITEM_17_PROPERTIES = UNIT_END + 0x017C, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC - PLAYER_VISIBLE_ITEM_17_PAD = UNIT_END + 0x017D, // Size: 1, Type: INT, Flags: PUBLIC - PLAYER_VISIBLE_ITEM_18_CREATOR = UNIT_END + 0x017E, // Size: 2, Type: LONG, Flags: PUBLIC - PLAYER_VISIBLE_ITEM_18_0 = UNIT_END + 0x0180, // Size: 12, Type: INT, Flags: PUBLIC - PLAYER_VISIBLE_ITEM_18_PROPERTIES = UNIT_END + 0x018C, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC - PLAYER_VISIBLE_ITEM_18_PAD = UNIT_END + 0x018D, // Size: 1, Type: INT, Flags: PUBLIC - PLAYER_VISIBLE_ITEM_19_CREATOR = UNIT_END + 0x018E, // Size: 2, Type: LONG, Flags: PUBLIC - PLAYER_VISIBLE_ITEM_19_0 = UNIT_END + 0x0190, // Size: 12, Type: INT, Flags: PUBLIC - PLAYER_VISIBLE_ITEM_19_PROPERTIES = UNIT_END + 0x019C, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC - PLAYER_VISIBLE_ITEM_19_PAD = UNIT_END + 0x019D, // Size: 1, Type: INT, Flags: PUBLIC - PLAYER_CHOSEN_TITLE = UNIT_END + 0x019E, // Size: 1, Type: INT, Flags: PUBLIC - PLAYER_FIELD_PAD_0 = UNIT_END + 0x019F, // Size: 1, Type: INT, Flags: NONE - PLAYER_FIELD_INV_SLOT_HEAD = UNIT_END + 0x01A0, // Size: 46, Type: LONG, Flags: PRIVATE - PLAYER_FIELD_PACK_SLOT_1 = UNIT_END + 0x01CE, // Size: 32, Type: LONG, Flags: PRIVATE - PLAYER_FIELD_BANK_SLOT_1 = UNIT_END + 0x01EE, // Size: 56, Type: LONG, Flags: PRIVATE - PLAYER_FIELD_BANKBAG_SLOT_1 = UNIT_END + 0x0226, // Size: 14, Type: LONG, Flags: PRIVATE - PLAYER_FIELD_VENDORBUYBACK_SLOT_1 = UNIT_END + 0x0234, // Size: 24, Type: LONG, Flags: PRIVATE - PLAYER_FIELD_KEYRING_SLOT_1 = UNIT_END + 0x024C, // Size: 64, Type: LONG, Flags: PRIVATE - PLAYER_FIELD_VANITYPET_SLOT_1 = UNIT_END + 0x028C, // Size: 36, Type: LONG, Flags: PRIVATE - PLAYER_FARSIGHT = UNIT_END + 0x02B0, // Size: 2, Type: LONG, Flags: PRIVATE - PLAYER__FIELD_KNOWN_TITLES = UNIT_END + 0x02B2, // Size: 2, Type: LONG, Flags: PRIVATE - PLAYER_XP = UNIT_END + 0x02B4, // Size: 1, Type: INT, Flags: PRIVATE - PLAYER_NEXT_LEVEL_XP = UNIT_END + 0x02B5, // Size: 1, Type: INT, Flags: PRIVATE - PLAYER_SKILL_INFO_1_1 = UNIT_END + 0x02B6, // Size: 384, Type: TWO_SHORT, Flags: PRIVATE - PLAYER_CHARACTER_POINTS1 = UNIT_END + 0x0436, // Size: 1, Type: INT, Flags: PRIVATE - PLAYER_CHARACTER_POINTS2 = UNIT_END + 0x0437, // Size: 1, Type: INT, Flags: PRIVATE - PLAYER_TRACK_CREATURES = UNIT_END + 0x0438, // Size: 1, Type: INT, Flags: PRIVATE - PLAYER_TRACK_RESOURCES = UNIT_END + 0x0439, // Size: 1, Type: INT, Flags: PRIVATE - PLAYER_BLOCK_PERCENTAGE = UNIT_END + 0x043A, // Size: 1, Type: FLOAT, Flags: PRIVATE - PLAYER_DODGE_PERCENTAGE = UNIT_END + 0x043B, // Size: 1, Type: FLOAT, Flags: PRIVATE - PLAYER_PARRY_PERCENTAGE = UNIT_END + 0x043C, // Size: 1, Type: FLOAT, Flags: PRIVATE - PLAYER_EXPERTISE = UNIT_END + 0x043D, // Size: 1, Type: INT, Flags: PRIVATE - PLAYER_OFFHAND_EXPERTISE = UNIT_END + 0x043E, // Size: 1, Type: INT, Flags: PRIVATE - PLAYER_CRIT_PERCENTAGE = UNIT_END + 0x043F, // Size: 1, Type: FLOAT, Flags: PRIVATE - PLAYER_RANGED_CRIT_PERCENTAGE = UNIT_END + 0x0440, // Size: 1, Type: FLOAT, Flags: PRIVATE - PLAYER_OFFHAND_CRIT_PERCENTAGE = UNIT_END + 0x0441, // Size: 1, Type: FLOAT, Flags: PRIVATE - PLAYER_SPELL_CRIT_PERCENTAGE1 = UNIT_END + 0x0442, // Size: 7, Type: FLOAT, Flags: PRIVATE - PLAYER_SHIELD_BLOCK = UNIT_END + 0x0449, // Size: 1, Type: INT, Flags: PRIVATE - PLAYER_EXPLORED_ZONES_1 = UNIT_END + 0x044A, // Size: 128, Type: BYTES, Flags: PRIVATE - PLAYER_REST_STATE_EXPERIENCE = UNIT_END + 0x04CA, // Size: 1, Type: INT, Flags: PRIVATE - PLAYER_FIELD_COINAGE = UNIT_END + 0x04CB, // Size: 1, Type: INT, Flags: PRIVATE - PLAYER_FIELD_MOD_DAMAGE_DONE_POS = UNIT_END + 0x04CC, // Size: 7, Type: INT, Flags: PRIVATE - PLAYER_FIELD_MOD_DAMAGE_DONE_NEG = UNIT_END + 0x04D3, // Size: 7, Type: INT, Flags: PRIVATE - PLAYER_FIELD_MOD_DAMAGE_DONE_PCT = UNIT_END + 0x04DA, // Size: 7, Type: INT, Flags: PRIVATE - PLAYER_FIELD_MOD_HEALING_DONE_POS = UNIT_END + 0x04E1, // Size: 1, Type: INT, Flags: PRIVATE - PLAYER_FIELD_MOD_TARGET_RESISTANCE = UNIT_END + 0x04E2, // Size: 1, Type: INT, Flags: PRIVATE - PLAYER_FIELD_MOD_TARGET_PHYSICAL_RESISTANCE = UNIT_END + 0x04E3, // Size: 1, Type: INT, Flags: PRIVATE - PLAYER_FIELD_BYTES = UNIT_END + 0x04E4, // Size: 1, Type: BYTES, Flags: PRIVATE - PLAYER_AMMO_ID = UNIT_END + 0x04E5, // Size: 1, Type: INT, Flags: PRIVATE - PLAYER_SELF_RES_SPELL = UNIT_END + 0x04E6, // Size: 1, Type: INT, Flags: PRIVATE - PLAYER_FIELD_PVP_MEDALS = UNIT_END + 0x04E7, // Size: 1, Type: INT, Flags: PRIVATE - PLAYER_FIELD_BUYBACK_PRICE_1 = UNIT_END + 0x04E8, // Size: 12, Type: INT, Flags: PRIVATE - PLAYER_FIELD_BUYBACK_TIMESTAMP_1 = UNIT_END + 0x04F4, // Size: 12, Type: INT, Flags: PRIVATE - PLAYER_FIELD_KILLS = UNIT_END + 0x0500, // Size: 1, Type: TWO_SHORT, Flags: PRIVATE - PLAYER_FIELD_TODAY_CONTRIBUTION = UNIT_END + 0x0501, // Size: 1, Type: INT, Flags: PRIVATE - PLAYER_FIELD_YESTERDAY_CONTRIBUTION = UNIT_END + 0x0502, // Size: 1, Type: INT, Flags: PRIVATE - PLAYER_FIELD_LIFETIME_HONORBALE_KILLS = UNIT_END + 0x0503, // Size: 1, Type: INT, Flags: PRIVATE - PLAYER_FIELD_BYTES2 = UNIT_END + 0x0504, // Size: 1, Type: BYTES, Flags: PRIVATE - PLAYER_FIELD_WATCHED_FACTION_INDEX = UNIT_END + 0x0505, // Size: 1, Type: INT, Flags: PRIVATE - PLAYER_FIELD_COMBAT_RATING_1 = UNIT_END + 0x0506, // Size: 24, Type: INT, Flags: PRIVATE - PLAYER_FIELD_ARENA_TEAM_INFO_1_1 = UNIT_END + 0x051E, // Size: 18, Type: INT, Flags: PRIVATE - PLAYER_FIELD_HONOR_CURRENCY = UNIT_END + 0x0530, // Size: 1, Type: INT, Flags: PRIVATE - PLAYER_FIELD_ARENA_CURRENCY = UNIT_END + 0x0531, // Size: 1, Type: INT, Flags: PRIVATE - PLAYER_FIELD_MOD_MANA_REGEN = UNIT_END + 0x0532, // Size: 1, Type: FLOAT, Flags: PRIVATE - PLAYER_FIELD_MOD_MANA_REGEN_INTERRUPT = UNIT_END + 0x0533, // Size: 1, Type: FLOAT, Flags: PRIVATE - PLAYER_FIELD_MAX_LEVEL = UNIT_END + 0x0534, // Size: 1, Type: INT, Flags: PRIVATE - PLAYER_FIELD_DAILY_QUESTS_1 = UNIT_END + 0x0535, // Size: 25, Type: INT, Flags: PRIVATE - PLAYER_END = UNIT_END + 0x054E, + PLAYER_VISIBLE_ITEM_1_0 = UNIT_END + 0x0070, // Size: 13, Type: INT, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_1_PROPERTIES = UNIT_END + 0x007D, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_1_SEED = UNIT_END + 0x007E, // Size: 1, Type: INT, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_1_PAD = UNIT_END + 0x007F, // Size: 1, Type: INT, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_2_CREATOR = UNIT_END + 0x0080, // Size: 2, Type: LONG, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_2_0 = UNIT_END + 0x0082, // Size: 13, Type: INT, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_2_PROPERTIES = UNIT_END + 0x008F, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_2_SEED = UNIT_END + 0x0090, // Size: 1, Type: INT, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_2_PAD = UNIT_END + 0x0091, // Size: 1, Type: INT, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_3_CREATOR = UNIT_END + 0x0092, // Size: 2, Type: LONG, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_3_0 = UNIT_END + 0x0094, // Size: 13, Type: INT, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_3_PROPERTIES = UNIT_END + 0x00A1, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_3_SEED = UNIT_END + 0x00A2, // Size: 1, Type: INT, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_3_PAD = UNIT_END + 0x00A3, // Size: 1, Type: INT, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_4_CREATOR = UNIT_END + 0x00A4, // Size: 2, Type: LONG, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_4_0 = UNIT_END + 0x00A6, // Size: 13, Type: INT, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_4_PROPERTIES = UNIT_END + 0x00B3, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_4_SEED = UNIT_END + 0x00B4, // Size: 1, Type: INT, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_4_PAD = UNIT_END + 0x00B5, // Size: 1, Type: INT, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_5_CREATOR = UNIT_END + 0x00B6, // Size: 2, Type: LONG, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_5_0 = UNIT_END + 0x00B8, // Size: 13, Type: INT, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_5_PROPERTIES = UNIT_END + 0x00C5, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_5_SEED = UNIT_END + 0x00C6, // Size: 1, Type: INT, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_5_PAD = UNIT_END + 0x00C7, // Size: 1, Type: INT, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_6_CREATOR = UNIT_END + 0x00C8, // Size: 2, Type: LONG, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_6_0 = UNIT_END + 0x00CA, // Size: 13, Type: INT, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_6_PROPERTIES = UNIT_END + 0x00D7, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_6_SEED = UNIT_END + 0x00D8, // Size: 1, Type: INT, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_6_PAD = UNIT_END + 0x00D9, // Size: 1, Type: INT, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_7_CREATOR = UNIT_END + 0x00DA, // Size: 2, Type: LONG, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_7_0 = UNIT_END + 0x00DC, // Size: 13, Type: INT, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_7_PROPERTIES = UNIT_END + 0x00E9, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_7_SEED = UNIT_END + 0x00EA, // Size: 1, Type: INT, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_7_PAD = UNIT_END + 0x00EB, // Size: 1, Type: INT, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_8_CREATOR = UNIT_END + 0x00EC, // Size: 2, Type: LONG, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_8_0 = UNIT_END + 0x00EE, // Size: 13, Type: INT, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_8_PROPERTIES = UNIT_END + 0x00FB, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_8_SEED = UNIT_END + 0x00FC, // Size: 1, Type: INT, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_8_PAD = UNIT_END + 0x00FD, // Size: 1, Type: INT, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_9_CREATOR = UNIT_END + 0x00FE, // Size: 2, Type: LONG, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_9_0 = UNIT_END + 0x0100, // Size: 13, Type: INT, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_9_PROPERTIES = UNIT_END + 0x010D, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_9_SEED = UNIT_END + 0x010E, // Size: 1, Type: INT, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_9_PAD = UNIT_END + 0x010F, // Size: 1, Type: INT, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_10_CREATOR = UNIT_END + 0x0110, // Size: 2, Type: LONG, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_10_0 = UNIT_END + 0x0112, // Size: 13, Type: INT, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_10_PROPERTIES = UNIT_END + 0x011F, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_10_SEED = UNIT_END + 0x0120, // Size: 1, Type: INT, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_10_PAD = UNIT_END + 0x0121, // Size: 1, Type: INT, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_11_CREATOR = UNIT_END + 0x0122, // Size: 2, Type: LONG, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_11_0 = UNIT_END + 0x0124, // Size: 13, Type: INT, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_11_PROPERTIES = UNIT_END + 0x0131, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_11_SEED = UNIT_END + 0x0132, // Size: 1, Type: INT, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_11_PAD = UNIT_END + 0x0133, // Size: 1, Type: INT, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_12_CREATOR = UNIT_END + 0x0134, // Size: 2, Type: LONG, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_12_0 = UNIT_END + 0x0136, // Size: 13, Type: INT, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_12_PROPERTIES = UNIT_END + 0x0143, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_12_SEED = UNIT_END + 0x0144, // Size: 1, Type: INT, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_12_PAD = UNIT_END + 0x0145, // Size: 1, Type: INT, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_13_CREATOR = UNIT_END + 0x0146, // Size: 2, Type: LONG, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_13_0 = UNIT_END + 0x0148, // Size: 13, Type: INT, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_13_PROPERTIES = UNIT_END + 0x0155, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_13_SEED = UNIT_END + 0x0156, // Size: 1, Type: INT, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_13_PAD = UNIT_END + 0x0157, // Size: 1, Type: INT, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_14_CREATOR = UNIT_END + 0x0158, // Size: 2, Type: LONG, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_14_0 = UNIT_END + 0x015A, // Size: 13, Type: INT, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_14_PROPERTIES = UNIT_END + 0x0167, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_14_SEED = UNIT_END + 0x0168, // Size: 1, Type: INT, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_14_PAD = UNIT_END + 0x0169, // Size: 1, Type: INT, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_15_CREATOR = UNIT_END + 0x016A, // Size: 2, Type: LONG, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_15_0 = UNIT_END + 0x016C, // Size: 13, Type: INT, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_15_PROPERTIES = UNIT_END + 0x0179, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_15_SEED = UNIT_END + 0x017A, // Size: 1, Type: INT, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_15_PAD = UNIT_END + 0x017B, // Size: 1, Type: INT, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_16_CREATOR = UNIT_END + 0x017C, // Size: 2, Type: LONG, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_16_0 = UNIT_END + 0x017E, // Size: 13, Type: INT, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_16_PROPERTIES = UNIT_END + 0x018B, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_16_SEED = UNIT_END + 0x018C, // Size: 1, Type: INT, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_16_PAD = UNIT_END + 0x018D, // Size: 1, Type: INT, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_17_CREATOR = UNIT_END + 0x018E, // Size: 2, Type: LONG, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_17_0 = UNIT_END + 0x0190, // Size: 13, Type: INT, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_17_PROPERTIES = UNIT_END + 0x019D, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_17_SEED = UNIT_END + 0x019E, // Size: 1, Type: INT, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_17_PAD = UNIT_END + 0x019F, // Size: 1, Type: INT, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_18_CREATOR = UNIT_END + 0x01A0, // Size: 2, Type: LONG, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_18_0 = UNIT_END + 0x01A2, // Size: 13, Type: INT, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_18_PROPERTIES = UNIT_END + 0x01AF, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_18_SEED = UNIT_END + 0x01B0, // Size: 1, Type: INT, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_18_PAD = UNIT_END + 0x01B1, // Size: 1, Type: INT, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_19_CREATOR = UNIT_END + 0x01B2, // Size: 2, Type: LONG, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_19_0 = UNIT_END + 0x01B4, // Size: 13, Type: INT, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_19_PROPERTIES = UNIT_END + 0x01C1, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_19_SEED = UNIT_END + 0x01C2, // Size: 1, Type: INT, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_19_PAD = UNIT_END + 0x01C3, // Size: 1, Type: INT, Flags: PUBLIC + PLAYER_CHOSEN_TITLE = UNIT_END + 0x01C4, // Size: 1, Type: INT, Flags: PUBLIC + PLAYER_FIELD_PAD_0 = UNIT_END + 0x01C5, // Size: 1, Type: INT, Flags: NONE + PLAYER_FIELD_INV_SLOT_HEAD = UNIT_END + 0x01C6, // Size: 46, Type: LONG, Flags: PRIVATE + PLAYER_FIELD_PACK_SLOT_1 = UNIT_END + 0x01F4, // Size: 32, Type: LONG, Flags: PRIVATE + PLAYER_FIELD_BANK_SLOT_1 = UNIT_END + 0x0214, // Size: 56, Type: LONG, Flags: PRIVATE + PLAYER_FIELD_BANKBAG_SLOT_1 = UNIT_END + 0x024C, // Size: 14, Type: LONG, Flags: PRIVATE + PLAYER_FIELD_VENDORBUYBACK_SLOT_1 = UNIT_END + 0x025A, // Size: 24, Type: LONG, Flags: PRIVATE + PLAYER_FIELD_KEYRING_SLOT_1 = UNIT_END + 0x0272, // Size: 64, Type: LONG, Flags: PRIVATE + PLAYER_FIELD_VANITYPET_SLOT_1 = UNIT_END + 0x02B2, // Size: 36, Type: LONG, Flags: PRIVATE + PLAYER_FIELD_CURRENCYTOKEN_SLOT_1 = UNIT_END + 0x02D6, // Size: 64, Type: LONG, Flags: PRIVATE + PLAYER_FIELD_QUESTBAG_SLOT_1 = UNIT_END + 0x0316, // Size: 64, Type: LONG, Flags: PRIVATE + PLAYER_FARSIGHT = UNIT_END + 0x0356, // Size: 2, Type: LONG, Flags: PRIVATE + PLAYER__FIELD_KNOWN_TITLES = UNIT_END + 0x0358, // Size: 2, Type: LONG, Flags: PRIVATE + PLAYER__FIELD_KNOWN_TITLES1 = UNIT_END + 0x035A, // Size: 2, Type: LONG, Flags: PRIVATE + PLAYER_FIELD_KNOWN_CURRENCIES = UNIT_END + 0x035C, // Size: 2, Type: LONG, Flags: PRIVATE + PLAYER_XP = UNIT_END + 0x035E, // Size: 1, Type: INT, Flags: PRIVATE + PLAYER_NEXT_LEVEL_XP = UNIT_END + 0x035F, // Size: 1, Type: INT, Flags: PRIVATE + PLAYER_SKILL_INFO_1_1 = UNIT_END + 0x0360, // Size: 384, Type: TWO_SHORT, Flags: PRIVATE + PLAYER_CHARACTER_POINTS1 = UNIT_END + 0x04E0, // Size: 1, Type: INT, Flags: PRIVATE + PLAYER_CHARACTER_POINTS2 = UNIT_END + 0x04E1, // Size: 1, Type: INT, Flags: PRIVATE + PLAYER_TRACK_CREATURES = UNIT_END + 0x04E2, // Size: 1, Type: INT, Flags: PRIVATE + PLAYER_TRACK_RESOURCES = UNIT_END + 0x04E3, // Size: 1, Type: INT, Flags: PRIVATE + PLAYER_BLOCK_PERCENTAGE = UNIT_END + 0x04E4, // Size: 1, Type: FLOAT, Flags: PRIVATE + PLAYER_DODGE_PERCENTAGE = UNIT_END + 0x04E5, // Size: 1, Type: FLOAT, Flags: PRIVATE + PLAYER_PARRY_PERCENTAGE = UNIT_END + 0x04E6, // Size: 1, Type: FLOAT, Flags: PRIVATE + PLAYER_EXPERTISE = UNIT_END + 0x04E7, // Size: 1, Type: INT, Flags: PRIVATE + PLAYER_OFFHAND_EXPERTISE = UNIT_END + 0x04E8, // Size: 1, Type: INT, Flags: PRIVATE + PLAYER_CRIT_PERCENTAGE = UNIT_END + 0x04E9, // Size: 1, Type: FLOAT, Flags: PRIVATE + PLAYER_RANGED_CRIT_PERCENTAGE = UNIT_END + 0x04EA, // Size: 1, Type: FLOAT, Flags: PRIVATE + PLAYER_OFFHAND_CRIT_PERCENTAGE = UNIT_END + 0x04EB, // Size: 1, Type: FLOAT, Flags: PRIVATE + PLAYER_SPELL_CRIT_PERCENTAGE1 = UNIT_END + 0x04EC, // Size: 7, Type: FLOAT, Flags: PRIVATE + PLAYER_SHIELD_BLOCK = UNIT_END + 0x04F3, // Size: 1, Type: INT, Flags: PRIVATE + PLAYER_SHIELD_BLOCK_CRIT_PERCENTAGE = UNIT_END + 0x04F4, // Size: 1, Type: FLOAT, Flags: PRIVATE + PLAYER_EXPLORED_ZONES_1 = UNIT_END + 0x04F5, // Size: 128, Type: BYTES, Flags: PRIVATE + PLAYER_REST_STATE_EXPERIENCE = UNIT_END + 0x0575, // Size: 1, Type: INT, Flags: PRIVATE + PLAYER_FIELD_COINAGE = UNIT_END + 0x0576, // Size: 1, Type: INT, Flags: PRIVATE + PLAYER_FIELD_MOD_DAMAGE_DONE_POS = UNIT_END + 0x0577, // Size: 7, Type: INT, Flags: PRIVATE + PLAYER_FIELD_MOD_DAMAGE_DONE_NEG = UNIT_END + 0x057E, // Size: 7, Type: INT, Flags: PRIVATE + PLAYER_FIELD_MOD_DAMAGE_DONE_PCT = UNIT_END + 0x0585, // Size: 7, Type: INT, Flags: PRIVATE + PLAYER_FIELD_MOD_HEALING_DONE_POS = UNIT_END + 0x058C, // Size: 1, Type: INT, Flags: PRIVATE + PLAYER_FIELD_MOD_TARGET_RESISTANCE = UNIT_END + 0x058D, // Size: 1, Type: INT, Flags: PRIVATE + PLAYER_FIELD_MOD_TARGET_PHYSICAL_RESISTANCE = UNIT_END + 0x058E, // Size: 1, Type: INT, Flags: PRIVATE + PLAYER_FIELD_BYTES = UNIT_END + 0x058F, // Size: 1, Type: BYTES, Flags: PRIVATE + PLAYER_AMMO_ID = UNIT_END + 0x0590, // Size: 1, Type: INT, Flags: PRIVATE + PLAYER_SELF_RES_SPELL = UNIT_END + 0x0591, // Size: 1, Type: INT, Flags: PRIVATE + PLAYER_FIELD_PVP_MEDALS = UNIT_END + 0x0592, // Size: 1, Type: INT, Flags: PRIVATE + PLAYER_FIELD_BUYBACK_PRICE_1 = UNIT_END + 0x0593, // Size: 12, Type: INT, Flags: PRIVATE + PLAYER_FIELD_BUYBACK_TIMESTAMP_1 = UNIT_END + 0x059F, // Size: 12, Type: INT, Flags: PRIVATE + PLAYER_FIELD_KILLS = UNIT_END + 0x05AB, // Size: 1, Type: TWO_SHORT, Flags: PRIVATE + PLAYER_FIELD_TODAY_CONTRIBUTION = UNIT_END + 0x05AC, // Size: 1, Type: INT, Flags: PRIVATE + PLAYER_FIELD_YESTERDAY_CONTRIBUTION = UNIT_END + 0x05AD, // Size: 1, Type: INT, Flags: PRIVATE + PLAYER_FIELD_LIFETIME_HONORBALE_KILLS = UNIT_END + 0x05AE, // Size: 1, Type: INT, Flags: PRIVATE + PLAYER_FIELD_BYTES2 = UNIT_END + 0x05AF, // Size: 1, Type: BYTES, Flags: PRIVATE + PLAYER_FIELD_WATCHED_FACTION_INDEX = UNIT_END + 0x05B0, // Size: 1, Type: INT, Flags: PRIVATE + PLAYER_FIELD_COMBAT_RATING_1 = UNIT_END + 0x05B1, // Size: 25, Type: INT, Flags: PRIVATE + PLAYER_FIELD_ARENA_TEAM_INFO_1_1 = UNIT_END + 0x05CA, // Size: 18, Type: INT, Flags: PRIVATE + PLAYER_FIELD_HONOR_CURRENCY = UNIT_END + 0x05DC, // Size: 1, Type: INT, Flags: PRIVATE + PLAYER_FIELD_ARENA_CURRENCY = UNIT_END + 0x05DD, // Size: 1, Type: INT, Flags: PRIVATE + PLAYER_FIELD_MAX_LEVEL = UNIT_END + 0x05DE, // Size: 1, Type: INT, Flags: PRIVATE + PLAYER_FIELD_DAILY_QUESTS_1 = UNIT_END + 0x05DF, // Size: 25, Type: INT, Flags: PRIVATE + PLAYER_RUNE_REGEN_1 = UNIT_END + 0x05F8, // Size: 4, Type: FLOAT, Flags: PRIVATE + PLAYER_NO_REAGENT_COST_1 = UNIT_END + 0x05FC, // Size: 3, Type: INT, Flags: PRIVATE + PLAYER_FIELD_GLYPH_SLOTS_1 = UNIT_END + 0x05FF, // Size: 8, Type: INT, Flags: PRIVATE + PLAYER_FIELD_GLYPHS_1 = UNIT_END + 0x0607, // Size: 8, Type: INT, Flags: PRIVATE + PLAYER_GLYPHS_ENABLED = UNIT_END + 0x060F, // Size: 1, Type: INT, Flags: PRIVATE + PLAYER_END = UNIT_END + 0x0610, }; enum EGameObjectFields { OBJECT_FIELD_CREATED_BY = OBJECT_END + 0x0000, // Size: 2, Type: LONG, Flags: PUBLIC GAMEOBJECT_DISPLAYID = OBJECT_END + 0x0002, // Size: 1, Type: INT, Flags: PUBLIC - GAMEOBJECT_FLAGS = OBJECT_END + 0x0003, // Size: 1, Type: INT, Flags: PUBLIC - GAMEOBJECT_ROTATION = OBJECT_END + 0x0004, // Size: 4, Type: FLOAT, Flags: PUBLIC - GAMEOBJECT_STATE = OBJECT_END + 0x0008, // Size: 1, Type: INT, Flags: PUBLIC - GAMEOBJECT_POS_X = OBJECT_END + 0x0009, // Size: 1, Type: FLOAT, Flags: PUBLIC - GAMEOBJECT_POS_Y = OBJECT_END + 0x000A, // Size: 1, Type: FLOAT, Flags: PUBLIC - GAMEOBJECT_POS_Z = OBJECT_END + 0x000B, // Size: 1, Type: FLOAT, Flags: PUBLIC - GAMEOBJECT_FACING = OBJECT_END + 0x000C, // Size: 1, Type: FLOAT, Flags: PUBLIC - GAMEOBJECT_DYN_FLAGS = OBJECT_END + 0x000D, // Size: 1, Type: INT, Flags: DYNAMIC - GAMEOBJECT_FACTION = OBJECT_END + 0x000E, // Size: 1, Type: INT, Flags: PUBLIC - GAMEOBJECT_TYPE_ID = OBJECT_END + 0x000F, // Size: 1, Type: INT, Flags: PUBLIC + GAMEOBJECT_FLAGS = OBJECT_END + 0x0003, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC + GAMEOBJECT_ROTATION = OBJECT_END + 0x0004, // Size: 2, Type: LONG, Flags: PUBLIC + GAMEOBJECT_PARENTROTATION = OBJECT_END + 0x0006, // Size: 4, Type: FLOAT, Flags: PUBLIC + GAMEOBJECT_POS_X = OBJECT_END + 0x000A, // Size: 1, Type: FLOAT, Flags: PUBLIC + GAMEOBJECT_POS_Y = OBJECT_END + 0x000B, // Size: 1, Type: FLOAT, Flags: PUBLIC + GAMEOBJECT_POS_Z = OBJECT_END + 0x000C, // Size: 1, Type: FLOAT, Flags: PUBLIC + GAMEOBJECT_FACING = OBJECT_END + 0x000D, // Size: 1, Type: FLOAT, Flags: PUBLIC + GAMEOBJECT_DYNAMIC = OBJECT_END + 0x000E, // Size: 1, Type: TWO_SHORT, Flags: DYNAMIC + GAMEOBJECT_FACTION = OBJECT_END + 0x000F, // Size: 1, Type: INT, Flags: PUBLIC GAMEOBJECT_LEVEL = OBJECT_END + 0x0010, // Size: 1, Type: INT, Flags: PUBLIC - GAMEOBJECT_ARTKIT = OBJECT_END + 0x0011, // Size: 1, Type: INT, Flags: PUBLIC - GAMEOBJECT_ANIMPROGRESS = OBJECT_END + 0x0012, // Size: 1, Type: INT, Flags: DYNAMIC - GAMEOBJECT_PADDING = OBJECT_END + 0x0013, // Size: 1, Type: INT, Flags: NONE - GAMEOBJECT_END = OBJECT_END + 0x0014, + GAMEOBJECT_BYTES_1 = OBJECT_END + 0x0011, // Size: 1, Type: BYTES, Flags: PUBLIC + GAMEOBJECT_END = OBJECT_END + 0x0012, }; enum EDynamicObjectFields diff --git a/src/game/Vehicle.cpp b/src/game/Vehicle.cpp new file mode 100644 index 000000000..4e1153a16 --- /dev/null +++ b/src/game/Vehicle.cpp @@ -0,0 +1,102 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "Common.h" +#include "Log.h" +#include "WorldSession.h" +#include "WorldPacket.h" +#include "ObjectMgr.h" +#include "SpellMgr.h" +#include "Vehicle.h" +#include "MapManager.h" +#include "SpellAuras.h" +#include "Unit.h" +#include "Util.h" + +Vehicle::Vehicle() : Creature(), m_vehicleId(0) +{ + m_isVehicle = true; + m_updateFlag = (UPDATEFLAG_LOWGUID | UPDATEFLAG_HIGHGUID | UPDATEFLAG_LIVING | UPDATEFLAG_HAS_POSITION | UPDATEFLAG_VEHICLE); +} + +Vehicle::~Vehicle() +{ + if(m_uint32Values) // only for fully created Object + ObjectAccessor::Instance().RemoveObject(this); +} + +void Vehicle::AddToWorld() +{ + ///- Register the vehicle for guid lookup + if(!IsInWorld()) ObjectAccessor::Instance().AddObject(this); + Unit::AddToWorld(); +} + +void Vehicle::RemoveFromWorld() +{ + ///- Remove the vehicle from the accessor + if(IsInWorld()) ObjectAccessor::Instance().RemoveObject(this); + ///- Don't call the function for Creature, normal mobs + totems go in a different storage + Unit::RemoveFromWorld(); +} + +void Vehicle::setDeathState(DeathState s) // overwrite virtual Creature::setDeathState and Unit::setDeathState +{ + Creature::setDeathState(s); +} + +void Vehicle::Update(uint32 diff) +{ + Creature::Update(diff); +} + +bool Vehicle::Create(uint32 guidlow, Map *map, uint32 Entry, uint32 vehicleId, uint32 team) +{ + SetMapId(map->GetId()); + SetInstanceId(map->GetInstanceId()); + + Object::_Create(guidlow, Entry, HIGHGUID_VEHICLE); + + if(!InitEntry(Entry, team)) + return false; + + m_defaultMovementType = IDLE_MOTION_TYPE; + + AIM_Initialize(); + + SetVehicleId(vehicleId); + + SetUInt32Value(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_SPELLCLICK); + SetFloatValue(UNIT_FIELD_HOVERHEIGHT, 1.0f); + + CreatureInfo const *ci = GetCreatureInfo(); + setFaction(team == ALLIANCE ? ci->faction_A : ci->faction_H); + SetMaxHealth(ci->maxhealth); + SelectLevel(ci); + SetHealth(GetMaxHealth()); + + return true; +} + +void Vehicle::Dismiss() +{ + SendObjectDeSpawnAnim(GetGUID()); + CombatStop(); + CleanupsBeforeDelete(); + AddObjectToRemoveList(); +} diff --git a/src/game/Vehicle.h b/src/game/Vehicle.h new file mode 100644 index 000000000..7fd8b60c4 --- /dev/null +++ b/src/game/Vehicle.h @@ -0,0 +1,58 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef MANGOSSERVER_VEHICLE_H +#define MANGOSSERVER_VEHICLE_H + +#include "ObjectDefines.h" +#include "Creature.h" +#include "Unit.h" + +class Vehicle : public Creature +{ + public: + explicit Vehicle(); + virtual ~Vehicle(); + + void AddToWorld(); + void RemoveFromWorld(); + + bool Create (uint32 guidlow, Map *map, uint32 Entry, uint32 vehicleId, uint32 team); + + void setDeathState(DeathState s); // overwrite virtual Creature::setDeathState and Unit::setDeathState + void Update(uint32 diff); // overwrite virtual Creature::Update and Unit::Update + + uint32 GetVehicleId() { return m_vehicleId; } + void SetVehicleId(uint32 vehicleid) { m_vehicleId = vehicleid; } + + void Dismiss(); + + protected: + uint32 m_vehicleId; + + private: + void SaveToDB(uint32, uint8) // overwrited of Creature::SaveToDB - don't must be called + { + assert(false); + } + void DeleteFromDB() // overwrited of Creature::DeleteFromDB - don't must be called + { + assert(false); + } +}; +#endif diff --git a/src/game/World.cpp b/src/game/World.cpp index 2c2e87a3d..6fa9a3088 100644 --- a/src/game/World.cpp +++ b/src/game/World.cpp @@ -226,7 +226,7 @@ World::AddSession_ (WorldSession* s) uint32 Sessions = GetActiveAndQueuedSessionCount (); uint32 pLimit = GetPlayerAmountLimit (); - uint32 QueueSize = GetQueueSize (); //number of players in the queue + uint32 QueueSize = GetQueueSize (); //number of players in the queue //so we don't count the user trying to //login as a session and queue the socket that we are using @@ -243,10 +243,10 @@ World::AddSession_ (WorldSession* s) WorldPacket packet(SMSG_AUTH_RESPONSE, 1 + 4 + 1 + 4 + 1); packet << uint8 (AUTH_OK); - packet << uint32 (0); // unknown random value... - packet << uint8 (0); - packet << uint32 (0); - packet << uint8 (s->Expansion()); // 0 - normal, 1 - TBC, must be set in database manually for each account + packet << uint32 (0); // BillingTimeRemaining + packet << uint8 (0); // BillingPlanFlags + packet << uint32 (0); // BillingTimeRested + packet << uint8 (s->Expansion()); // 0 - normal, 1 - TBC, must be set in database manually for each account s->SendPacket (&packet); UpdateMaxSessionCounters (); @@ -254,7 +254,7 @@ World::AddSession_ (WorldSession* s) // Updates the population if (pLimit > 0) { - float popu = GetActiveSessionCount (); //updated number of users on the server + float popu = GetActiveSessionCount (); //updated number of users on the server popu /= pLimit; popu *= 2; loginDatabase.PExecute ("UPDATE realmlist SET population = '%f' WHERE id = '%d'", popu, realmID); @@ -281,10 +281,10 @@ void World::AddQueuedPlayer(WorldSession* sess) // The 1st SMSG_AUTH_RESPONSE needs to contain other info too. WorldPacket packet (SMSG_AUTH_RESPONSE, 1 + 4 + 1 + 4 + 1); packet << uint8 (AUTH_WAIT_QUEUE); - packet << uint32 (0); // unknown random value... - packet << uint8 (0); - packet << uint32 (0); - packet << uint8 (sess->Expansion()); // 0 - normal, 1 - TBC, must be set in database manually for each account + packet << uint32 (0); // BillingTimeRemaining + packet << uint8 (0); // BillingPlanFlags + packet << uint32 (0); // BillingTimeRested + packet << uint8 (sess->Expansion()); // 0 - normal, 1 - TBC, must be set in database manually for each account packet << uint32(GetQueuePos (sess)); sess->SendPacket (&packet); @@ -426,24 +426,30 @@ void World::LoadConfigSettings(bool reload) rate_values[RATE_HEALTH] = sConfig.GetFloatDefault("Rate.Health", 1); if(rate_values[RATE_HEALTH] < 0) { - sLog.outError("Rate.Health (%f) mustbe > 0. Using 1 instead.",rate_values[RATE_HEALTH]); + sLog.outError("Rate.Health (%f) must be > 0. Using 1 instead.",rate_values[RATE_HEALTH]); rate_values[RATE_HEALTH] = 1; } rate_values[RATE_POWER_MANA] = sConfig.GetFloatDefault("Rate.Mana", 1); if(rate_values[RATE_POWER_MANA] < 0) { - sLog.outError("Rate.Mana (%f) mustbe > 0. Using 1 instead.",rate_values[RATE_POWER_MANA]); + sLog.outError("Rate.Mana (%f) must be > 0. Using 1 instead.",rate_values[RATE_POWER_MANA]); rate_values[RATE_POWER_MANA] = 1; } rate_values[RATE_POWER_RAGE_INCOME] = sConfig.GetFloatDefault("Rate.Rage.Income", 1); rate_values[RATE_POWER_RAGE_LOSS] = sConfig.GetFloatDefault("Rate.Rage.Loss", 1); if(rate_values[RATE_POWER_RAGE_LOSS] < 0) { - sLog.outError("Rate.Rage.Loss (%f) mustbe > 0. Using 1 instead.",rate_values[RATE_POWER_RAGE_LOSS]); + sLog.outError("Rate.Rage.Loss (%f) must be > 0. Using 1 instead.",rate_values[RATE_POWER_RAGE_LOSS]); rate_values[RATE_POWER_RAGE_LOSS] = 1; } + rate_values[RATE_POWER_RUNICPOWER_INCOME] = sConfig.GetFloatDefault("Rate.RunicPower.Income", 1); + rate_values[RATE_POWER_RUNICPOWER_LOSS] = sConfig.GetFloatDefault("Rate.RunicPower.Loss", 1); + if(rate_values[RATE_POWER_RUNICPOWER_LOSS] < 0) + { + sLog.outError("Rate.RunicPower.Loss (%f) must be > 0. Using 1 instead.",rate_values[RATE_POWER_RUNICPOWER_LOSS]); + rate_values[RATE_POWER_RUNICPOWER_LOSS] = 1; + } rate_values[RATE_POWER_FOCUS] = sConfig.GetFloatDefault("Rate.Focus", 1.0f); - rate_values[RATE_LOYALTY] = sConfig.GetFloatDefault("Rate.Loyalty", 1.0f); rate_values[RATE_SKILL_DISCOVERY] = sConfig.GetFloatDefault("Rate.Skill.Discovery", 1.0f); rate_values[RATE_DROP_ITEM_POOR] = sConfig.GetFloatDefault("Rate.Drop.Item.Poor", 1.0f); rate_values[RATE_DROP_ITEM_NORMAL] = sConfig.GetFloatDefault("Rate.Drop.Item.Normal", 1.0f); @@ -627,6 +633,13 @@ void World::LoadConfigSettings(bool reload) m_configs[CONFIG_CHARACTERS_PER_REALM] = 10; } + m_configs[CONFIG_HEROIC_CHARACTERS_PER_REALM] = sConfig.GetIntDefault("HeroicCharactersPerRealm", 1); + if(m_configs[CONFIG_HEROIC_CHARACTERS_PER_REALM] < 0 || m_configs[CONFIG_HEROIC_CHARACTERS_PER_REALM] > 10) + { + sLog.outError("HeroicCharactersPerRealm (%i) must be in range 0..10. Set to 1.",m_configs[CONFIG_HEROIC_CHARACTERS_PER_REALM]); + m_configs[CONFIG_HEROIC_CHARACTERS_PER_REALM] = 1; + } + // must be after CONFIG_CHARACTERS_PER_REALM m_configs[CONFIG_CHARACTERS_PER_ACCOUNT] = sConfig.GetIntDefault("CharactersPerAccount", 50); if(m_configs[CONFIG_CHARACTERS_PER_ACCOUNT] < m_configs[CONFIG_CHARACTERS_PER_REALM]) @@ -650,10 +663,11 @@ void World::LoadConfigSettings(bool reload) } else m_configs[CONFIG_MAX_PLAYER_LEVEL] = sConfig.GetIntDefault("MaxPlayerLevel", 60); - if(m_configs[CONFIG_MAX_PLAYER_LEVEL] > 255) + + if(m_configs[CONFIG_MAX_PLAYER_LEVEL] > MAX_LEVEL) { - sLog.outError("MaxPlayerLevel (%i) must be in range 1..255. Set to 255.",m_configs[CONFIG_MAX_PLAYER_LEVEL]); - m_configs[CONFIG_MAX_PLAYER_LEVEL] = 255; + sLog.outError("MaxPlayerLevel (%i) must be in range 1..%u. Set to %u.",m_configs[CONFIG_MAX_PLAYER_LEVEL],MAX_LEVEL,MAX_LEVEL); + m_configs[CONFIG_MAX_PLAYER_LEVEL] = MAX_LEVEL; } m_configs[CONFIG_START_PLAYER_LEVEL] = sConfig.GetIntDefault("StartPlayerLevel", 1); @@ -668,6 +682,20 @@ void World::LoadConfigSettings(bool reload) m_configs[CONFIG_START_PLAYER_LEVEL] = m_configs[CONFIG_MAX_PLAYER_LEVEL]; } + m_configs[CONFIG_START_HEROIC_PLAYER_LEVEL] = sConfig.GetIntDefault("StartHeroicPlayerLevel", 55); + if(m_configs[CONFIG_START_HEROIC_PLAYER_LEVEL] < 1) + { + sLog.outError("StartHeroicPlayerLevel (%i) must be in range 1..MaxPlayerLevel(%u). Set to 55.", + m_configs[CONFIG_START_HEROIC_PLAYER_LEVEL],m_configs[CONFIG_MAX_PLAYER_LEVEL]); + m_configs[CONFIG_START_HEROIC_PLAYER_LEVEL] = 55; + } + else if(m_configs[CONFIG_START_HEROIC_PLAYER_LEVEL] > m_configs[CONFIG_MAX_PLAYER_LEVEL]) + { + sLog.outError("StartHeroicPlayerLevel (%i) must be in range 1..MaxPlayerLevel(%u). Set to %u.", + m_configs[CONFIG_START_HEROIC_PLAYER_LEVEL],m_configs[CONFIG_MAX_PLAYER_LEVEL],m_configs[CONFIG_MAX_PLAYER_LEVEL]); + m_configs[CONFIG_START_HEROIC_PLAYER_LEVEL] = m_configs[CONFIG_MAX_PLAYER_LEVEL]; + } + m_configs[CONFIG_START_PLAYER_MONEY] = sConfig.GetIntDefault("StartPlayerMoney", 0); if(m_configs[CONFIG_START_PLAYER_MONEY] < 0) { @@ -740,30 +768,30 @@ void World::LoadConfigSettings(bool reload) m_configs[CONFIG_MIN_PETITION_SIGNS] = sConfig.GetIntDefault("MinPetitionSigns", 9); if(m_configs[CONFIG_MIN_PETITION_SIGNS] > 9) { - sLog.outError("MinPetitionSigns (%i) must be in range 0..9. Set to 9.",m_configs[CONFIG_MIN_PETITION_SIGNS]); + sLog.outError("MinPetitionSigns (%i) must be in range 0..9. Set to 9.", m_configs[CONFIG_MIN_PETITION_SIGNS]); m_configs[CONFIG_MIN_PETITION_SIGNS] = 9; } - m_configs[CONFIG_GM_LOGIN_STATE] = sConfig.GetIntDefault("GM.LoginState",2); - m_configs[CONFIG_GM_ACCEPT_TICKETS] = sConfig.GetIntDefault("GM.AcceptTickets",2); - m_configs[CONFIG_GM_CHAT] = sConfig.GetIntDefault("GM.Chat",2); - m_configs[CONFIG_GM_WISPERING_TO] = sConfig.GetIntDefault("GM.WhisperingTo",2); + m_configs[CONFIG_GM_LOGIN_STATE] = sConfig.GetIntDefault("GM.LoginState", 2); + m_configs[CONFIG_GM_ACCEPT_TICKETS] = sConfig.GetIntDefault("GM.AcceptTickets", 2); + m_configs[CONFIG_GM_CHAT] = sConfig.GetIntDefault("GM.Chat", 2); + m_configs[CONFIG_GM_WISPERING_TO] = sConfig.GetIntDefault("GM.WhisperingTo", 2); - m_configs[CONFIG_GM_IN_GM_LIST] = sConfig.GetBoolDefault("GM.InGMList",false); - m_configs[CONFIG_GM_IN_WHO_LIST] = sConfig.GetBoolDefault("GM.InWhoList",false); + m_configs[CONFIG_GM_IN_GM_LIST] = sConfig.GetBoolDefault("GM.InGMList", false); + m_configs[CONFIG_GM_IN_WHO_LIST] = sConfig.GetBoolDefault("GM.InWhoList", false); m_configs[CONFIG_GM_LOG_TRADE] = sConfig.GetBoolDefault("GM.LogTrade", false); m_configs[CONFIG_START_GM_LEVEL] = sConfig.GetIntDefault("GM.StartLevel", 1); if(m_configs[CONFIG_START_GM_LEVEL] < m_configs[CONFIG_START_PLAYER_LEVEL]) { - sLog.outError("GM.StartLevel (%i) must be in range StartPlayerLevel(%u)..255. Set to %u.", - m_configs[CONFIG_START_GM_LEVEL],m_configs[CONFIG_START_PLAYER_LEVEL],m_configs[CONFIG_START_PLAYER_LEVEL]); + sLog.outError("GM.StartLevel (%i) must be in range StartPlayerLevel(%u)..%u. Set to %u.", + m_configs[CONFIG_START_GM_LEVEL],m_configs[CONFIG_START_PLAYER_LEVEL], MAX_LEVEL, m_configs[CONFIG_START_PLAYER_LEVEL]); m_configs[CONFIG_START_GM_LEVEL] = m_configs[CONFIG_START_PLAYER_LEVEL]; } - else if(m_configs[CONFIG_START_GM_LEVEL] > 255) + else if(m_configs[CONFIG_START_GM_LEVEL] > MAX_LEVEL) { - sLog.outError("GM.StartLevel (%i) must be in range 1..255. Set to %u.",m_configs[CONFIG_START_GM_LEVEL],255); - m_configs[CONFIG_START_GM_LEVEL] = 255; + sLog.outError("GM.StartLevel (%i) must be in range 1..%u. Set to %u.", m_configs[CONFIG_START_GM_LEVEL], MAX_LEVEL, MAX_LEVEL); + m_configs[CONFIG_START_GM_LEVEL] = MAX_LEVEL; } m_configs[CONFIG_GROUP_VISIBILITY] = sConfig.GetIntDefault("Visibility.GroupMode",0); @@ -791,6 +819,7 @@ void World::LoadConfigSettings(bool reload) m_configs[CONFIG_SKILL_CHANCE_SKINNING_STEPS] = sConfig.GetIntDefault("SkillChance.SkinningSteps",75); m_configs[CONFIG_SKILL_PROSPECTING] = sConfig.GetBoolDefault("SkillChance.Prospecting",false); + m_configs[CONFIG_SKILL_MILLING] = sConfig.GetBoolDefault("SkillChance.Milling",false); m_configs[CONFIG_SKILL_GAIN_CRAFTING] = sConfig.GetIntDefault("SkillGain.Crafting", 1); if(m_configs[CONFIG_SKILL_GAIN_CRAFTING] < 0) @@ -854,13 +883,13 @@ void World::LoadConfigSettings(bool reload) m_configs[CONFIG_WORLD_BOSS_LEVEL_DIFF] = sConfig.GetIntDefault("WorldBossLevelDiff",3); - // note: disable value (-1) will assigned as 0xFFFFFFF, to prevent overflow at calculations limit it to max possible player level (255) - m_configs[CONFIG_QUEST_LOW_LEVEL_HIDE_DIFF] = sConfig.GetIntDefault("Quests.LowLevelHideDiff",4); - if(m_configs[CONFIG_QUEST_LOW_LEVEL_HIDE_DIFF] > 255) - m_configs[CONFIG_QUEST_LOW_LEVEL_HIDE_DIFF] = 255; - m_configs[CONFIG_QUEST_HIGH_LEVEL_HIDE_DIFF] = sConfig.GetIntDefault("Quests.HighLevelHideDiff",7); - if(m_configs[CONFIG_QUEST_HIGH_LEVEL_HIDE_DIFF] > 255) - m_configs[CONFIG_QUEST_HIGH_LEVEL_HIDE_DIFF] = 255; + // note: disable value (-1) will assigned as 0xFFFFFFF, to prevent overflow at calculations limit it to max possible player level MAX_LEVEL(100) + m_configs[CONFIG_QUEST_LOW_LEVEL_HIDE_DIFF] = sConfig.GetIntDefault("Quests.LowLevelHideDiff", 4); + if(m_configs[CONFIG_QUEST_LOW_LEVEL_HIDE_DIFF] > MAX_LEVEL) + m_configs[CONFIG_QUEST_LOW_LEVEL_HIDE_DIFF] = MAX_LEVEL; + m_configs[CONFIG_QUEST_HIGH_LEVEL_HIDE_DIFF] = sConfig.GetIntDefault("Quests.HighLevelHideDiff", 7); + if(m_configs[CONFIG_QUEST_HIGH_LEVEL_HIDE_DIFF] > MAX_LEVEL) + m_configs[CONFIG_QUEST_HIGH_LEVEL_HIDE_DIFF] = MAX_LEVEL; m_configs[CONFIG_DETECT_POS_COLLISION] = sConfig.GetBoolDefault("DetectPosCollision", true); @@ -890,6 +919,12 @@ void World::LoadConfigSettings(bool reload) m_configs[CONFIG_LISTEN_RANGE_TEXTEMOTE] = sConfig.GetIntDefault("ListenRange.TextEmote", 25); m_configs[CONFIG_LISTEN_RANGE_YELL] = sConfig.GetIntDefault("ListenRange.Yell", 300); + m_configs[CONFIG_ARENA_MAX_RATING_DIFFERENCE] = sConfig.GetIntDefault("Arena.MaxRatingDifference", 0); + m_configs[CONFIG_ARENA_RATING_DISCARD_TIMER] = sConfig.GetIntDefault("Arena.RatingDiscardTimer",300000); + m_configs[CONFIG_ARENA_AUTO_DISTRIBUTE_POINTS] = sConfig.GetBoolDefault("Arena.AutoDistributePoints", false); + m_configs[CONFIG_ARENA_AUTO_DISTRIBUTE_INTERVAL_DAYS] = sConfig.GetIntDefault("Arena.AutoDistributeInterval", 7); + + m_configs[CONFIG_BATTLEGROUND_PREMATURE_FINISH_TIMER] = sConfig.GetIntDefault("BattleGround.PrematureFinishTimer", 0); m_configs[CONFIG_INSTANT_LOGOUT] = sConfig.GetIntDefault("InstantLogout", SEC_MODERATOR); m_VisibleUnitGreyDistance = sConfig.GetFloatDefault("Visibility.Distance.Grey.Unit", 1); @@ -1029,12 +1064,18 @@ void World::SetInitialWorldSettings() sLog.outString( "Loading InstanceTemplate" ); objmgr.LoadInstanceTemplate(); + sLog.outString( "Loading AchievementCriteriaList..." ); + objmgr.LoadAchievementCriteriaList(); + + sLog.outString( "Loading completed achievements..." ); + objmgr.LoadCompletedAchievements(); + sLog.outString( "Loading SkillLineAbilityMultiMap Data..." ); spellmgr.LoadSkillLineAbilityMap(); ///- Clean up and pack instances sLog.outString( "Cleaning up instances..." ); - sInstanceSaveManager.CleanupInstances(); // must be called before `creature_respawn`/`gameobject_respawn` tables + sInstanceSaveManager.CleanupInstances(); // must be called before `creature_respawn`/`gameobject_respawn` tables sLog.outString( "Packing instances..." ); sInstanceSaveManager.PackInstances(); @@ -1154,6 +1195,9 @@ void World::SetInitialWorldSettings() sLog.outString( "Loading spell pet auras..." ); spellmgr.LoadSpellPetAuras(); + sLog.outString( "Loading pet levelup spells..." ); + spellmgr.LoadPetLevelupSpellMap(); + sLog.outString( "Loading player Create Info & Level Stats..." ); objmgr.LoadPlayerInfo(); @@ -1291,6 +1335,7 @@ void World::SetInitialWorldSettings() ///- Initialize Battlegrounds sLog.outString( "Starting BattleGround System" ); sBattleGroundMgr.CreateInitialBattleGrounds(); + sBattleGroundMgr.InitAutomaticArenaPointDistribution(); //Not sure if this can be moved up in the sequence (with static data loading) as it uses MapManager sLog.outString( "Loading Transports..." ); @@ -1606,6 +1651,9 @@ void World::ScriptsProcess() case HIGHGUID_PET: source = HashMapHolder::Find(step.sourceGUID); break; + case HIGHGUID_VEHICLE: + source = HashMapHolder::Find(step.sourceGUID); + break; case HIGHGUID_PLAYER: source = HashMapHolder::Find(step.sourceGUID); break; @@ -1635,6 +1683,9 @@ void World::ScriptsProcess() case HIGHGUID_PET: target = HashMapHolder::Find(step.targetGUID); break; + case HIGHGUID_VEHICLE: + target = HashMapHolder::Find(step.targetGUID); + break; case HIGHGUID_PLAYER: // empty GUID case also target = HashMapHolder::Find(step.targetGUID); break; @@ -2168,7 +2219,7 @@ void World::ScriptsProcess() void World::SendGlobalMessage(WorldPacket *packet, WorldSession *self, uint32 team) { SessionMap::iterator itr; - for (itr = m_sessions.begin(); itr != m_sessions.end(); itr++) + for (itr = m_sessions.begin(); itr != m_sessions.end(); ++itr) { if (itr->second && itr->second->GetPlayer() && @@ -2235,11 +2286,29 @@ void World::SendWorldText(int32 string_id, ...) delete data_cache[i][j]; } +/// Send a System Message to all players (except self if mentioned) +void World::SendGlobalText(const char* text, WorldSession *self) +{ + WorldPacket data; + + // need copy to prevent corruption by strtok call in LineFromMessage original string + char* buf = strdup(text); + char* pos = buf; + + while(char* line = ChatHandler::LineFromMessage(pos)) + { + ChatHandler::FillMessageData(&data, NULL, CHAT_MSG_SYSTEM, LANG_UNIVERSAL, NULL, 0, line, NULL); + SendGlobalMessage(&data, self); + } + + free(buf); +} + /// Send a packet to all players (or players selected team) in the zone (except self if mentioned) void World::SendZoneMessage(uint32 zone, WorldPacket *packet, WorldSession *self, uint32 team) { SessionMap::iterator itr; - for (itr = m_sessions.begin(); itr != m_sessions.end(); itr++) + for (itr = m_sessions.begin(); itr != m_sessions.end(); ++itr) { if (itr->second && itr->second->GetPlayer() && @@ -2281,7 +2350,7 @@ void World::KickAllLess(AccountTypes sec) } /// Kick (and save) the designated player -bool World::KickPlayer(std::string playerName) +bool World::KickPlayer(const std::string& playerName) { SessionMap::iterator itr; diff --git a/src/game/World.h b/src/game/World.h index 2f3c0be57..57167bf83 100644 --- a/src/game/World.h +++ b/src/game/World.h @@ -100,9 +100,11 @@ enum WorldConfigs CONFIG_CHARACTERS_CREATING_DISABLED, CONFIG_CHARACTERS_PER_ACCOUNT, CONFIG_CHARACTERS_PER_REALM, + CONFIG_HEROIC_CHARACTERS_PER_REALM, CONFIG_SKIP_CINEMATICS, CONFIG_MAX_PLAYER_LEVEL, CONFIG_START_PLAYER_LEVEL, + CONFIG_START_HEROIC_PLAYER_LEVEL, CONFIG_START_PLAYER_MONEY, CONFIG_MAX_HONOR_POINTS, CONFIG_START_HONOR_POINTS, @@ -176,6 +178,12 @@ enum WorldConfigs CONFIG_LISTEN_RANGE_SAY, CONFIG_LISTEN_RANGE_TEXTEMOTE, CONFIG_LISTEN_RANGE_YELL, + CONFIG_ARENA_MAX_RATING_DIFFERENCE, + CONFIG_ARENA_RATING_DISCARD_TIMER, + CONFIG_ARENA_AUTO_DISTRIBUTE_POINTS, + CONFIG_ARENA_AUTO_DISTRIBUTE_INTERVAL_DAYS, + CONFIG_BATTLEGROUND_PREMATURE_FINISH_TIMER, + CONFIG_SKILL_MILLING, CONFIG_VALUE_COUNT }; @@ -186,6 +194,8 @@ enum Rates RATE_POWER_MANA, RATE_POWER_RAGE_INCOME, RATE_POWER_RAGE_LOSS, + RATE_POWER_RUNICPOWER_INCOME, + RATE_POWER_RUNICPOWER_LOSS, RATE_POWER_FOCUS, RATE_SKILL_DISCOVERY, RATE_DROP_ITEM_POOR, @@ -229,7 +239,6 @@ enum Rates RATE_MINING_AMOUNT, RATE_MINING_NEXT, RATE_TALENT, - RATE_LOYALTY, RATE_CORPSE_DECAY_LOOTED, RATE_INSTANCE_RESET_TIME, RATE_TARGET_POS_RECALCULATION_RANGE, @@ -396,6 +405,7 @@ class World void LoadConfigSettings(bool reload = false); void SendWorldText(int32 string_id, ...); + void SendGlobalText(const char* text, WorldSession *self); void SendGlobalMessage(WorldPacket *packet, WorldSession *self = 0, uint32 team = 0); void SendZoneMessage(uint32 zone, WorldPacket *packet, WorldSession *self = 0, uint32 team = 0); void SendZoneText(uint32 zone, const char *text, WorldSession *self = 0, uint32 team = 0); @@ -438,7 +448,7 @@ class World bool IsPvPRealm() { return (getConfig(CONFIG_GAME_TYPE) == REALM_TYPE_PVP || getConfig(CONFIG_GAME_TYPE) == REALM_TYPE_RPPVP || getConfig(CONFIG_GAME_TYPE) == REALM_TYPE_FFA_PVP); } bool IsFFAPvPRealm() { return getConfig(CONFIG_GAME_TYPE) == REALM_TYPE_FFA_PVP; } - bool KickPlayer(std::string playerName); + bool KickPlayer(const std::string& playerName); void KickAll(); void KickAllLess(AccountTypes sec); BanReturn BanAccount(BanMode mode, std::string nameOrIP, std::string duration, std::string reason, std::string author); diff --git a/src/game/WorldSession.cpp b/src/game/WorldSession.cpp index ffaa25e33..858f33717 100644 --- a/src/game/WorldSession.cpp +++ b/src/game/WorldSession.cpp @@ -513,3 +513,90 @@ void WorldSession::SendAuthWaitQue(uint32 position) SendPacket(&packet); } } + +void WorldSession::LoadAccountData() +{ + for (uint32 i = 0; i < NUM_ACCOUNT_DATA_TYPES; ++i) + { + AccountData data; + m_accountData[i] = data; + } + + QueryResult *result = CharacterDatabase.PQuery("SELECT type, time, data FROM account_data WHERE account='%u'", GetAccountId()); + + if(!result) + return; + + do + { + Field *fields = result->Fetch(); + + uint32 type = fields[0].GetUInt32(); + if(type < NUM_ACCOUNT_DATA_TYPES) + { + m_accountData[type].Time = fields[1].GetUInt32(); + m_accountData[type].Data = fields[2].GetCppString(); + } + } while (result->NextRow()); + + delete result; +} + +void WorldSession::SetAccountData(uint32 type, time_t time_, std::string data) +{ + m_accountData[type].Time = time_; + m_accountData[type].Data = data; + + uint32 acc = GetAccountId(); + CharacterDatabase.PExecute("DELETE FROM account_data WHERE account='%u' AND type='%u'", acc, type); + CharacterDatabase.escape_string(data); + CharacterDatabase.PExecute("INSERT INTO account_data VALUES ('%u','%u','%u','%s')", acc, type, (uint32)time_, data.c_str()); +} + +void WorldSession::ReadMovementInfo(WorldPacket &data, MovementInfo *mi) +{ + CHECK_PACKET_SIZE(data, data.rpos()+4+2+4+4+4+4+4); + data >> mi->flags; + data >> mi->unk1; + data >> mi->time; + data >> mi->x; + data >> mi->y; + data >> mi->z; + data >> mi->o; + + if(mi->flags & MOVEMENTFLAG_ONTRANSPORT) + { + CHECK_PACKET_SIZE(data, data.rpos()+8+4+4+4+4+4+1); + data >> mi->t_guid; + data >> mi->t_x; + data >> mi->t_y; + data >> mi->t_z; + data >> mi->t_o; + data >> mi->t_time; + data >> mi->t_seat; + } + + if((mi->flags & (MOVEMENTFLAG_SWIMMING | MOVEMENTFLAG_FLYING2)) || (mi->unk1 & 0x20)) + { + CHECK_PACKET_SIZE(data, data.rpos()+4); + data >> mi->s_pitch; + } + + CHECK_PACKET_SIZE(data, data.rpos()+4); + data >> mi->fallTime; + + if(mi->flags & MOVEMENTFLAG_JUMPING) + { + CHECK_PACKET_SIZE(data, data.rpos()+4+4+4+4); + data >> mi->j_unk; + data >> mi->j_sinAngle; + data >> mi->j_cosAngle; + data >> mi->j_xyspeed; + } + + if(mi->flags & MOVEMENTFLAG_SPLINE) + { + CHECK_PACKET_SIZE(data, data.rpos()+4); + data >> mi->u_unk1; + } +} diff --git a/src/game/WorldSession.h b/src/game/WorldSession.h index 6077d42b4..0fb31d75c 100644 --- a/src/game/WorldSession.h +++ b/src/game/WorldSession.h @@ -29,6 +29,7 @@ class MailItemsInfo; struct ItemPrototype; struct AuctionEntry; struct DeclinedName; +struct MovementInfo; class Creature; class Item; @@ -44,6 +45,16 @@ class CharacterHandler; #define CHECK_PACKET_SIZE(P,S) if((P).size() < (S)) return SizeError((P),(S)); +#define NUM_ACCOUNT_DATA_TYPES 8 + +struct AccountData +{ + AccountData() : Time(NULL), Data("") {} + + time_t Time; + std::string Data; +}; + enum PartyOperation { PARTY_OP_INVITE = 0, @@ -78,10 +89,12 @@ class MANGOS_DLL_SPEC WorldSession void SizeError(WorldPacket const& packet, uint32 size) const; + void ReadMovementInfo(WorldPacket &data, MovementInfo *mi); + void SendPacket(WorldPacket const* packet); void SendNotification(const char *format,...) ATTR_PRINTF(2,3); void SendNotification(int32 string_id,...); - void SendPetNameInvalid(uint32 error, std::string name, DeclinedName *declinedName); + void SendPetNameInvalid(uint32 error, const std::string& name, DeclinedName *declinedName); void SendLfgResult(uint32 type, uint32 entry, uint8 lfg_type); void SendPartyResult(PartyOperation operation, const std::string& member, PartyResult res); void SendAreaTriggerMessage(const char* Text, ...) ATTR_PRINTF(2,3); @@ -91,7 +104,7 @@ class MANGOS_DLL_SPEC WorldSession Player* GetPlayer() const { return _player; } char const* GetPlayerName() const; void SetSecurity(uint32 security) { _security = security; } - std::string& GetRemoteAddress() { return m_Address; } + std::string const& GetRemoteAddress() { return m_Address; } void SetPlayer(Player *plr) { _player = plr; } uint8 Expansion() const { return m_expansion; } @@ -128,7 +141,7 @@ class MANGOS_DLL_SPEC WorldSession static void SendNameQueryOpcodeFromDBCallBack(QueryResult *result, uint32 accountId); void SendTrainerList( uint64 guid ); - void SendTrainerList( uint64 guid,std::string strTitle ); + void SendTrainerList( uint64 guid, const std::string& strTitle ); void SendListInventory( uint64 guid ); void SendShowBank( uint64 guid ); void SendTabardVendorActivate( uint64 guid ); @@ -150,10 +163,15 @@ class MANGOS_DLL_SPEC WorldSession //pet void SendPetNameQuery(uint64 guid, uint32 petnumber); + // Account Data + AccountData *GetAccountData(uint32 type) { return &m_accountData[type]; } + void SetAccountData(uint32 type, time_t time_, std::string data); + void LoadAccountData(); + //mail //used with item_page table bool SendItemInfo( uint32 itemid, WorldPacket data ); - static void SendReturnToSender(uint8 messageType, uint32 sender_acc, uint32 sender_guid, uint32 receiver_guid, std::string subject, uint32 itemTextId, MailItemsInfo *mi, uint32 money, uint16 mailTemplateId = 0); + static void SendReturnToSender(uint8 messageType, uint32 sender_acc, uint32 sender_guid, uint32 receiver_guid, const std::string& subject, uint32 itemTextId, MailItemsInfo *mi, uint32 money, uint16 mailTemplateId = 0); static void SendMailTo(Player* receiver, uint8 messageType, uint8 stationery, uint32 sender_guidlow_or_entry, uint32 received_guidlow, std::string subject, uint32 itemTextId, MailItemsInfo* mi, uint32 money, uint32 COD, uint32 checked, uint32 deliver_delay = 0, uint16 mailTemplateId = 0); //auction @@ -176,12 +194,13 @@ class MANGOS_DLL_SPEC WorldSession bool SendLearnNewTaxiNode( Creature* unit ); // Guild/Arena Team - void SendGuildCommandResult(uint32 typecmd,std::string str,uint32 cmdresult); - void SendArenaTeamCommandResult(uint32 unk1, std::string str1, std::string str2, uint32 unk3); - void BuildArenaTeamEventPacket(WorldPacket *data, uint8 eventid, uint8 str_count, std::string str1, std::string str2, std::string str3); + void SendGuildCommandResult(uint32 typecmd, const std::string& str, uint32 cmdresult); + void SendArenaTeamCommandResult(uint32 team_action, const std::string& team, const std::string& player, uint32 error_id); + void BuildArenaTeamEventPacket(WorldPacket *data, uint8 eventid, uint8 str_count, const std::string& str1, const std::string& str2, const std::string& str3); void SendNotInArenaTeamPacket(uint8 type); void SendPetitionShowList( uint64 guid ); void SendSaveGuildEmblem( uint32 msg ); + void SendBattleGroundOrArenaJoinError(uint8 err); // Looking For Group // TRUE values set by client sending CMSG_LFG_SET_AUTOJOIN and CMSG_LFM_CLEAR_AUTOFILL before player login @@ -319,6 +338,8 @@ class MANGOS_DLL_SPEC WorldSession void HandleMovementOpcodes(WorldPacket& recvPacket); void HandleSetActiveMoverOpcode(WorldPacket &recv_data); + void HandleMoveNotActiveMover(WorldPacket &recv_data); + void HandleDismissControlledVehicle(WorldPacket &recv_data); void HandleMoveTimeSkippedOpcode(WorldPacket &recv_data); void HandleRequestRaidInfoOpcode( WorldPacket & recv_data ); @@ -379,7 +400,7 @@ class MANGOS_DLL_SPEC WorldSession void HandleGuildSaveEmblemOpcode(WorldPacket& recvPacket); void HandleTaxiNodeStatusQueryOpcode(WorldPacket& recvPacket); - void HandleTaxiQueryAvailableNodesOpcode(WorldPacket& recvPacket); + void HandleTaxiQueryAvailableNodes(WorldPacket& recvPacket); void HandleActivateTaxiOpcode(WorldPacket& recvPacket); void HandleActivateTaxiFarOpcode(WorldPacket& recvPacket); void HandleTaxiNextDestinationOpcode(WorldPacket& recvPacket); @@ -423,6 +444,7 @@ class MANGOS_DLL_SPEC WorldSession void HandleAuctionRemoveItem( WorldPacket & recv_data ); void HandleAuctionListOwnerItems( WorldPacket & recv_data ); void HandleAuctionPlaceBid( WorldPacket & recv_data ); + void HandleAuctionListPendingSales( WorldPacket & recv_data ); void HandleGetMail( WorldPacket & recv_data ); void HandleSendMail( WorldPacket & recv_data ); @@ -537,10 +559,12 @@ class MANGOS_DLL_SPEC WorldSession void HandlePetUnlearnOpcode( WorldPacket& recvPacket ); void HandlePetSpellAutocastOpcode( WorldPacket& recvPacket ); void HandlePetCastSpellOpcode( WorldPacket& recvPacket ); + void HandlePetLearnTalent( WorldPacket& recvPacket ); void HandleSetActionBar(WorldPacket& recv_data); void HandleChangePlayerNameOpcode(WorldPacket& recv_data); + static void HandleChangePlayerNameOpcodeCallBack(QueryResult *result, uint32 accountId, std::string newname); void HandleDeclinedPlayerNameOpcode(WorldPacket& recv_data); void HandleTotemDestroy(WorldPacket& recv_data); @@ -572,10 +596,9 @@ class MANGOS_DLL_SPEC WorldSession void HandleLfmSetNoneOpcode(WorldPacket& recv_data); void HandleLfmSetOpcode(WorldPacket& recv_data); void HandleLfgSetCommentOpcode(WorldPacket& recv_data); - void HandleNewUnknownOpcode(WorldPacket& recv_data); void HandleChooseTitleOpcode(WorldPacket& recv_data); void HandleRealmStateRequestOpcode(WorldPacket& recv_data); - void HandleAllowMoveAckOpcode(WorldPacket& recv_data); + void HandleTimeSyncResp(WorldPacket& recv_data); void HandleWhoisOpcode(WorldPacket& recv_data); void HandleResetInstancesOpcode(WorldPacket& recv_data); @@ -621,6 +644,29 @@ class MANGOS_DLL_SPEC WorldSession void HandleGuildBankBuyTab(WorldPacket& recv_data); void HandleGuildBankTabText(WorldPacket& recv_data); void HandleGuildBankSetTabText(WorldPacket& recv_data); + + // Calendar + void HandleCalendarGetCalendar(WorldPacket& recv_data); + void HandleCalendarGetEvent(WorldPacket& recv_data); + void HandleCalendarGuildFilter(WorldPacket& recv_data); + void HandleCalendarArenaTeam(WorldPacket& recv_data); + void HandleCalendarAddEvent(WorldPacket& recv_data); + void HandleCalendarUpdateEvent(WorldPacket& recv_data); + void HandleCalendarRemoveEvent(WorldPacket& recv_data); + void HandleCalendarCopyEvent(WorldPacket& recv_data); + void HandleCalendarEventInvite(WorldPacket& recv_data); + void HandleCalendarEventRsvp(WorldPacket& recv_data); + void HandleCalendarEventRemoveInvite(WorldPacket& recv_data); + void HandleCalendarEventStatus(WorldPacket& recv_data); + void HandleCalendarEventModeratorStatus(WorldPacket& recv_data); + void HandleCalendarComplain(WorldPacket& recv_data); + void HandleCalendarGetNumPending(WorldPacket& recv_data); + + void HandleSpellClick(WorldPacket& recv_data); + void HandleAlterAppearance(WorldPacket& recv_data); + void HandleRemoveGlyph(WorldPacket& recv_data); + void HandleCharCustomize(WorldPacket& recv_data); + void HandleInspectAchievements(WorldPacket& recv_data); private: // private trade methods void moveItems(Item* myItems[], Item* hisItems[]); @@ -644,6 +690,7 @@ class MANGOS_DLL_SPEC WorldSession LocaleConstant m_sessionDbcLocale; int m_sessionDbLocaleIndex; uint32 m_latency; + AccountData m_accountData[NUM_ACCOUNT_DATA_TYPES]; ZThread::LockedQueue _recvQueue; }; diff --git a/src/game/WorldSocket.cpp b/src/game/WorldSocket.cpp index d80cc2362..9d40d398b 100644 --- a/src/game/WorldSocket.cpp +++ b/src/game/WorldSocket.cpp @@ -52,8 +52,48 @@ struct ServerPktHeader { - uint16 size; - uint16 cmd; + /** + * size is the length of the payload _plus_ the length of the opcode + */ + ServerPktHeader(uint32 size, uint16 cmd) : size(size) + { + uint8 headerIndex=0; + if(isLargePacket()) + { + sLog.outDebug("initializing large server to client packet. Size: %u, cmd: %u", size, cmd); + header= new uint8[5]; + header[headerIndex++] = 0x80|(0xFF &(size>>16)); + } + else + { + header= new uint8[4]; + } + + header[headerIndex++] = 0xFF &(size>>8); + header[headerIndex++] = 0xFF &size; + + header[headerIndex++] = 0xFF & cmd; + header[headerIndex++] = 0xFF & (cmd>>8); + } + + ~ServerPktHeader() + { + delete[] header; + } + + uint8 getHeaderLength() + { + // cmd = 2 bytes, size= 2||3bytes + return 2+(isLargePacket()?3:2); + } + + bool isLargePacket() + { + return size > 0x7FFF; + } + + const uint32 size; + uint8 *header; }; struct ClientPktHeader @@ -637,7 +677,7 @@ int WorldSocket::HandleAuthSession (WorldPacket& recvPacket) // NOTE: ATM the socket is singlethread, have this in mind ... uint8 digest[20]; uint32 clientSeed; - uint32 unk2; + uint32 unk2, unk3; uint32 BuiltNumberClient; uint32 id, security; uint8 expansion = 0; @@ -659,6 +699,7 @@ int WorldSocket::HandleAuthSession (WorldPacket& recvPacket) recvPacket >> BuiltNumberClient; // for now no use recvPacket >> unk2; recvPacket >> account; + recvPacket >> unk3; if (recvPacket.size () < (4 + 4 + (account.size () + 1) + 4 + 20)) { @@ -874,6 +915,8 @@ int WorldSocket::HandleAuthSession (WorldPacket& recvPacket) m_Crypt.SetKey (&K); m_Crypt.Init (); + m_Session->LoadAccountData(); + // In case needed sometime the second arg is in microseconds 1 000 000 = 1 sec ACE_OS::sleep (ACE_Time_Value (0, 10000)); @@ -957,23 +1000,17 @@ int WorldSocket::HandlePing (WorldPacket& recvPacket) int WorldSocket::iSendPacket (const WorldPacket& pct) { - if (m_OutBuffer->space () < pct.size () + sizeof (ServerPktHeader)) + ServerPktHeader header(pct.size()+2, pct.GetOpcode()); + if (m_OutBuffer->space () < pct.size () + header.getHeaderLength()) { errno = ENOBUFS; return -1; } - ServerPktHeader header; - header.cmd = pct.GetOpcode (); - EndianConvert(header.cmd); + m_Crypt.EncryptSend ( header.header, header.getHeaderLength()); - header.size = (uint16) pct.size () + 2; - EndianConvertReverse(header.size); - - m_Crypt.EncryptSend ((uint8*) & header, sizeof (header)); - - if (m_OutBuffer->copy ((char*) & header, sizeof (header)) == -1) + if (m_OutBuffer->copy ((char*) header.header, header.getHeaderLength()) == -1) ACE_ASSERT (false); if (!pct.empty ()) diff --git a/src/game/debugcmds.cpp b/src/game/debugcmds.cpp index 298411fbd..a67ef3203 100644 --- a/src/game/debugcmds.cpp +++ b/src/game/debugcmds.cpp @@ -30,6 +30,7 @@ #include "GossipDef.h" #include "Language.h" #include "MapManager.h" +#include "BattleGroundMgr.h" #include #include "ObjectMgr.h" @@ -60,6 +61,7 @@ bool ChatHandler::HandleDebugSpellFailCommand(const char* args) uint8 failnum = (uint8)atoi(px); WorldPacket data(SMSG_CAST_FAILED, 5); + data << uint8(0); data << uint32(133); data << uint8(failnum); m_session->SendPacket(&data); @@ -518,3 +520,59 @@ bool ChatHandler::HandleGetItemState(const char* args) return true; } + +bool ChatHandler::HandleDebugArenaCommand(const char * /*args*/) +{ + sBattleGroundMgr.ToggleArenaTesting(); + return true; +} + +bool ChatHandler::HandleSpawnVehicle(const char* args) +{ + if(!args) + return false; + + char* e = strtok((char*)args, " "); + char* i = strtok(NULL, " "); + + if (!e || !i) + return false; + + uint32 entry = (uint32)atoi(e); + uint32 id = (uint32)atoi(i); + + CreatureInfo const *ci = objmgr.GetCreatureTemplate(entry); + + if(!ci) + return false; + + VehicleEntry const *ve = sVehicleStore.LookupEntry(id); + + if(!ve) + return false; + + Vehicle *v = new Vehicle; + Map *map = m_session->GetPlayer()->GetMap(); + if(!v->Create(objmgr.GenerateLowGuid(HIGHGUID_VEHICLE), map, entry, id, m_session->GetPlayer()->GetTeam())) + { + delete v; + return false; + } + + float px, py, pz; + m_session->GetPlayer()->GetClosePoint(px, py, pz, m_session->GetPlayer()->GetObjectSize()); + + v->Relocate(px, py, pz, m_session->GetPlayer()->GetOrientation()); + + if(!v->IsPositionValid()) + { + sLog.outError("ERROR: Vehicle (guidlow %d, entry %d) not created. Suggested coordinates isn't valid (X: %f Y: %f)", + v->GetGUIDLow(), v->GetEntry(), v->GetPositionX(), v->GetPositionY()); + delete v; + return false; + } + + map->Add((Creature*)v); + + return true; +} diff --git a/src/mangosd/Master.cpp b/src/mangosd/Master.cpp index 1b6929267..f5ef907bb 100644 --- a/src/mangosd/Master.cpp +++ b/src/mangosd/Master.cpp @@ -459,7 +459,7 @@ void Master::clearOnlineAccounts() "AND id IN (SELECT acctid FROM realmcharacters WHERE realmid = '%d')",realmID); - CharacterDatabase.Execute("UPDATE characters SET online = 0"); + CharacterDatabase.Execute("UPDATE characters SET online = 0 WHERE online<>0"); } /// Handle termination signals diff --git a/src/mangosd/mangosd.conf.dist.in b/src/mangosd/mangosd.conf.dist.in index a7c0be700..2056bf98b 100644 --- a/src/mangosd/mangosd.conf.dist.in +++ b/src/mangosd/mangosd.conf.dist.in @@ -408,6 +408,11 @@ LogColors = "" # Default: 10 (client limitation) # The number must be between 1 and 10 # +# HeroicCharactersPerRealm +# Limit numbers of heroic class characters for account at realm +# Default: 1 +# The number must be between 0 (not allowed) and 10 +# # SkipCinematics # Disable in-game script movie at first character's login(allows to prevent buggy intro in case of custom start location coordinates) # Default: 0 - show intro for each new characrer @@ -415,14 +420,18 @@ LogColors = "" # 2 - disable intro show in all cases # # MaxPlayerLevel -# Max level that can be reached by player for experience (in range from 1 to 255). +# Max level that can be reached by player for experience (in range from 1 to 100). # Change not recommended -# Default: 70 +# Default: 80 # # StartPlayerLevel # Staring level that have character at creating (in range 1 to MaxPlayerLevel) # Default: 1 # +# StartHeroicPlayerLevel +# Staring level that have character of heroic class at creating (in range 1 to MaxPlayerLevel) +# Default: 55 +# # StartPlayerMoney # Amount of money that new players will start with. # If you want to start with silver, use for example 100 (100 copper = 1 silver) @@ -536,7 +545,12 @@ LogColors = "" # Default: 3600 sec (1 hour) # # SkillChance.Prospecting -# For prospecting skillup not possible by default, but can be allowed as custom setting +# For prospecting skillup impossible by default, but can be allowed as custom setting +# Default: 0 - no skilups +# 1 - skilups possible +# +# SkillChance.Milling +# For milling skillup impossible by default, but can be allowed as custom setting # Default: 0 - no skilups # 1 - skilups possible # @@ -556,7 +570,7 @@ LogColors = "" GameType = 1 RealmZone = 1 -Expansion = 1 +Expansion = 2 DBC.Locale = 255 DeclinedNames = 0 StrictPlayerNames = 0 @@ -565,9 +579,11 @@ StrictPetNames = 0 CharactersCreatingDisabled = 0 CharactersPerAccount = 50 CharactersPerRealm = 10 +HeroicCharactersPerRealm = 1 SkipCinematics = 0 -MaxPlayerLevel = 70 +MaxPlayerLevel = 80 StartPlayerLevel = 1 +StartHeroicPlayerLevel = 55 StartPlayerMoney = 0 MaxHonorPoints = 75000 StartHonorPoints = 0 @@ -593,6 +609,7 @@ MinPetitionSigns = 9 MaxGroupXPDistance = 74 MailDeliveryDelay = 3600 SkillChance.Prospecting = 0 +SkillChance.Milling = 0 Event.Announce = 0 BeepAtStart = 1 Motd = "Welcome to the Massive Network Game Object Server." @@ -837,7 +854,7 @@ Channel.SilentlyGMJoin = 0 # 0 (not include) # # GM.StartLevel -# GM starting level (1-255) +# GM starting level (1-100) # Default: 1 # ################################################################################################################### @@ -905,8 +922,9 @@ Visibility.Distance.Grey.Object = 10 # Rate.Mana # Rate.Rage.Income # Rate.Rage.Loss +# Rate.RunicPower.Income +# Rate.RunicPower.Loss # Rate.Focus -# Rate.Loyalty # Health and power regeneration and rage income from damage. # Default: 1 # @@ -1027,8 +1045,9 @@ Rate.Health = 1 Rate.Mana = 1 Rate.Rage.Income = 1 Rate.Rage.Loss = 1 +Rate.RunicPower.Income = 1 +Rate.RunicPower.Loss = 1 Rate.Focus = 1 -Rate.Loyalty = 1 Rate.Skill.Discovery = 1 Rate.Drop.Item.Poor = 1 Rate.Drop.Item.Normal = 1 @@ -1074,6 +1093,48 @@ Death.SicknessLevel = 11 Death.CorpseReclaimDelay.PvP = 1 Death.CorpseReclaimDelay.PvE = 1 +################################################################################################################### +# +# Rated arena matches config +# +# MaxRatingDifference: the maximum rating difference between two groups in rated matches +# Default: 0 (disable, rating difference is discarded) +# +# RatingDiscardTimer: after the specified milliseconds has passed, +# rating information will be discarded when selecting teams for matches +# also initiates an update by this timer +# Default: 60000 +# +# AutoDistributePoints: set if arena points should be distributed automatically, or by GM command +# Default: 0 (disable) (recommended): use gm command or sql query to distribute the points +# 1 (enable): arena points are distributed automatically +# +# AutoDistributeInterval: how often should the distribution take place +# if automatic distribution is enabled +# in days +# Default: 7 (weekly) +# +################################################################################################################### + +Arena.MaxRatingDifference = 0 +Arena.RatingDiscardTimer = 60000 +Arena.AutoDistributePoints = 0 +Arena.AutoDistributeInterval = 7 + +################################################################################################################### +# +# Battleground config +# +# PrematureFinishTimer: the time to end the bg if there are less than minplayersperteam on one side +# in milliseconds +# Default: 300000 +# 0 - disable +# +################################################################################################################### + +BattleGround.PrematureFinishTimer = 300000 + + ################################################################################################################### # # NETWORK CONFIG diff --git a/src/realmd/AuthCodes.h b/src/realmd/AuthCodes.h index 99271dc29..68e10b25c 100644 --- a/src/realmd/AuthCodes.h +++ b/src/realmd/AuthCodes.h @@ -66,8 +66,8 @@ enum LoginResult // we need to stick to 1 version or half of the stuff will work for someone // others will not and opposite -// will only support WoW and WoW:TBC 2.4.3 client build 8606... +// will only support WoW, WoW:TBC and WoW:WotLK 3.0.3 client build 9183... -#define EXPECTED_MANGOS_CLIENT_BUILD {8606, 0} +#define EXPECTED_MANGOS_CLIENT_BUILD {9183, 0} #endif diff --git a/src/realmd/AuthSocket.cpp b/src/realmd/AuthSocket.cpp index 987e1d210..e1759e7e0 100644 --- a/src/realmd/AuthSocket.cpp +++ b/src/realmd/AuthSocket.cpp @@ -298,7 +298,7 @@ void AuthSocket::OnRead() } /// Make the SRP6 calculation from hash in dB -void AuthSocket::_SetVSFields(std::string rI) +void AuthSocket::_SetVSFields(const std::string& rI) { BigNumber I; I.SetHexStr(rI.c_str()); diff --git a/src/realmd/AuthSocket.h b/src/realmd/AuthSocket.h index b46e1d425..0ed37587b 100644 --- a/src/realmd/AuthSocket.h +++ b/src/realmd/AuthSocket.h @@ -56,7 +56,7 @@ class AuthSocket: public TcpSocket bool _HandleXferCancel(); bool _HandleXferAccept(); - void _SetVSFields(std::string rI); + void _SetVSFields(const std::string& rI); FILE *pPatch; ZThread::Mutex patcherLock; diff --git a/src/realmd/RealmList.cpp b/src/realmd/RealmList.cpp index 7f4dd3e15..a25e495b0 100644 --- a/src/realmd/RealmList.cpp +++ b/src/realmd/RealmList.cpp @@ -42,7 +42,7 @@ void RealmList::Initialize(uint32 updateInterval) UpdateRealms(true); } -void RealmList::UpdateRealm( uint32 ID, std::string name, std::string address, uint32 port, uint8 icon, uint8 color, uint8 timezone, AccountTypes allowedSecurityLevel, float popu) +void RealmList::UpdateRealm( uint32 ID, const std::string& name, const std::string& address, uint32 port, uint8 icon, uint8 color, uint8 timezone, AccountTypes allowedSecurityLevel, float popu) { ///- Create new if not exist or update existed Realm& realm = m_realms[name]; diff --git a/src/realmd/RealmList.h b/src/realmd/RealmList.h index 15095e8fa..f3e04c07d 100644 --- a/src/realmd/RealmList.h +++ b/src/realmd/RealmList.h @@ -56,7 +56,7 @@ class RealmList uint32 size() const { return m_realms.size(); } private: void UpdateRealms(bool init); - void UpdateRealm( uint32 ID, std::string name, std::string address, uint32 port, uint8 icon, uint8 color, uint8 timezone, AccountTypes allowedSecurityLevel, float popu); + void UpdateRealm( uint32 ID, const std::string& name, const std::string& address, uint32 port, uint8 icon, uint8 color, uint8 timezone, AccountTypes allowedSecurityLevel, float popu); private: RealmMap m_realms; ///< Internal map of realms uint32 m_UpdateInterval; diff --git a/src/shared/Auth/AuthCrypt.cpp b/src/shared/Auth/AuthCrypt.cpp index c6aae7026..27dce1d6d 100644 --- a/src/shared/Auth/AuthCrypt.cpp +++ b/src/shared/Auth/AuthCrypt.cpp @@ -48,9 +48,8 @@ void AuthCrypt::DecryptRecv(uint8 *data, size_t len) void AuthCrypt::EncryptSend(uint8 *data, size_t len) { if (!_initialized) return; - if (len < CRYPTED_SEND_LEN) return; - for (size_t t = 0; t < CRYPTED_SEND_LEN; t++) + for (size_t t = 0; t < len; t++) { _send_i %= _key.size(); uint8 x = (data[t] ^ _key[_send_i]) + _send_j; diff --git a/src/shared/Auth/AuthCrypt.h b/src/shared/Auth/AuthCrypt.h index 60f91b052..a14e4d900 100644 --- a/src/shared/Auth/AuthCrypt.h +++ b/src/shared/Auth/AuthCrypt.h @@ -30,7 +30,6 @@ class AuthCrypt AuthCrypt(); ~AuthCrypt(); - const static size_t CRYPTED_SEND_LEN = 4; const static size_t CRYPTED_RECV_LEN = 6; void Init(); diff --git a/src/shared/Common.cpp b/src/shared/Common.cpp index 952997d3b..e7224bc5e 100644 --- a/src/shared/Common.cpp +++ b/src/shared/Common.cpp @@ -30,7 +30,7 @@ char const* localeNames[MAX_LOCALE] = { "ruRU" }; -LocaleConstant GetLocaleByName(std::string name) +LocaleConstant GetLocaleByName(const std::string& name) { for(uint32 i = 0; i < MAX_LOCALE; ++i) if(name==localeNames[i]) diff --git a/src/shared/Common.h b/src/shared/Common.h index 5c938ea67..0fc544fc6 100644 --- a/src/shared/Common.h +++ b/src/shared/Common.h @@ -186,7 +186,7 @@ enum LocaleConstant extern char const* localeNames[MAX_LOCALE]; -LocaleConstant GetLocaleByName(std::string name); +LocaleConstant GetLocaleByName(const std::string& name); // we always use stdlibc++ std::max/std::min, undefine some not C++ standard defines (Win API and some pother platforms) #ifdef max diff --git a/src/shared/Config/ConfigEnv.h b/src/shared/Config/ConfigEnv.h index f2a0d5146..6c61aeb93 100644 --- a/src/shared/Config/ConfigEnv.h +++ b/src/shared/Config/ConfigEnv.h @@ -23,6 +23,5 @@ #include "Common.h" #include "dotconfpp/dotconfpp.h" #include "Config.h" -#include "Log.h" #endif diff --git a/src/shared/Database/DBCEnums.h b/src/shared/Database/DBCEnums.h index 6ad7fdb12..4f406c9cc 100644 --- a/src/shared/Database/DBCEnums.h +++ b/src/shared/Database/DBCEnums.h @@ -19,6 +19,14 @@ #ifndef DBCENUMS_H #define DBCENUMS_H +// client supported max level for player/pets/etc. Avoid overflow or client stability affected. +// also see GT_MAX_LEVEL define +#define MAX_LEVEL 100 + +// Server side limitation. Base at used code requirements. +// also see MAX_LEVEL and GT_MAX_LEVEL define +#define STRONG_MAX_LEVEL 255 + enum AreaTeams { AREATEAM_NONE = 0, @@ -26,28 +34,190 @@ enum AreaTeams AREATEAM_HORDE = 4 }; +enum AchievementFactionFlags +{ + ACHIEVEMENT_FACTION_FLAG_HORDE = 0x00000000, + ACHIEVEMENT_FACTION_FLAG_ALLIANCE = 0x00000001, +}; + +enum AchievementFlags +{ + ACHIEVEMENT_FLAG_COUNTER = 0x00000001, + ACHIEVEMENT_FLAG_REACH_LEVEL = 0x00000004, + ACHIEVEMENT_FLAG_RERERED_MAX = 0x00000010, // displays the maximum criteria of a refered achievement + ACHIEVEMENT_FLAG_AVERAGE = 0x00000040, + ACHIEVEMENT_FLAG_REALM_FIRST_REACH= 0x00000100, + ACHIEVEMENT_FLAG_REALM_FIRST_KILL = 0x00000200, +}; + +enum AchievementCriteriaCondition +{ + ACHIEVEMENT_CRITERIA_CONDITION_NONE = 0, + ACHIEVEMENT_CRITERIA_CONDITION_NO_DEATH = 1, + ACHIEVEMENT_CRITERIA_CONDITION_UNK1 = 2, // only used in "Complete a daily quest every day for five consecutive days" + ACHIEVEMENT_CRITERIA_CONDITION_MAP = 3, // requires you to be on specific map + ACHIEVEMENT_CRITERIA_CONDITION_NO_LOOSE = 4, // only used in "Win 10 arenas without losing" + ACHIEVEMENT_CRITERIA_CONDITION_UNK2 = 9, // unk + ACHIEVEMENT_CRITERIA_CONDITION_UNK3 = 13, // unk +}; + +enum AchievementCriteriaCompletionFlags +{ + // some Achievements (like 698) have several criteria but only one has to be fulfilled. These are identified by this flag. + ACHIEVEMENT_CRITERIA_COMPLETE_FLAG_ALL = 2, +}; + +enum AchievementCriteriaGroupFlags +{ + // you mustn't be in a group while fulfilling this achievement + ACHIEVEMENT_CRITERIA_GROUP_NOT_IN_GROUP = 2, +}; + +enum AchievementCriteriaTypes +{ + ACHIEVEMENT_CRITERIA_TYPE_KILL_CREATURE = 0, + ACHIEVEMENT_CRITERIA_TYPE_WIN_BG = 1, + ACHIEVEMENT_CRITERIA_TYPE_REACH_LEVEL = 5, + ACHIEVEMENT_CRITERIA_TYPE_REACH_SKILL_LEVEL = 7, + ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_ACHIEVEMENT = 8, + ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_QUEST_COUNT = 9, + // you have to complete a daily quest x times in a row + ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_DAILY_QUEST_DAILY = 10, + ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_QUESTS_IN_ZONE = 11, + ACHIEVEMENT_CRITERIA_TYPE_DAMAGE_DONE = 13, + ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_DAILY_QUEST = 14, + ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_BATTLEGROUND= 15, + ACHIEVEMENT_CRITERIA_TYPE_DEATH_AT_MAP= 16, + // TODO: this can be both arena and total deaths. Where is this difference in the dbc? + ACHIEVEMENT_CRITERIA_TYPE_DEATH= 17, + ACHIEVEMENT_CRITERIA_TYPE_DEATH_IN_DUNGEON = 18, + ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_RAID = 19, + ACHIEVEMENT_CRITERIA_TYPE_KILLED_BY_CREATURE = 20, + ACHIEVEMENT_CRITERIA_TYPE_KILLED_BY_PLAYER = 23, + ACHIEVEMENT_CRITERIA_TYPE_FALL_WITHOUT_DYING = 24, + ACHIEVEMENT_CRITERIA_TYPE_DEATHS_FROM = 26, + ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_QUEST = 27, + ACHIEVEMENT_CRITERIA_TYPE_BE_SPELL_TARGET = 28, + ACHIEVEMENT_CRITERIA_TYPE_CAST_SPELL= 29, + ACHIEVEMENT_CRITERIA_TYPE_BG_OBJECTIVE_CAPTURE = 30, + ACHIEVEMENT_CRITERIA_TYPE_HONORABLE_KILL_AT_AREA = 31, + ACHIEVEMENT_CRITERIA_TYPE_WIN_ARENA = 32, + ACHIEVEMENT_CRITERIA_TYPE_PLAY_ARENA = 33, + ACHIEVEMENT_CRITERIA_TYPE_LEARN_SPELL = 34, + // TODO: this criteria has additional conditions which can not be found in the dbcs + ACHIEVEMENT_CRITERIA_TYPE_HONORABLE_KILL = 35, + ACHIEVEMENT_CRITERIA_TYPE_OWN_ITEM = 36, + // TODO: the archievements 1162 and 1163 requires a special rating which can't be found in the dbc + ACHIEVEMENT_CRITERIA_TYPE_WIN_RATED_ARENA = 37, + ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_TEAM_RATING = 38, + ACHIEVEMENT_CRITERIA_TYPE_REACH_TEAM_RATING = 39, + ACHIEVEMENT_CRITERIA_TYPE_LEARN_SKILL_LEVEL = 40, + ACHIEVEMENT_CRITERIA_TYPE_USE_ITEM = 41, + ACHIEVEMENT_CRITERIA_TYPE_LOOT_ITEM= 42, + ACHIEVEMENT_CRITERIA_TYPE_EXPLORE_AREA = 43, + ACHIEVEMENT_CRITERIA_TYPE_OWN_RANK= 44, + ACHIEVEMENT_CRITERIA_TYPE_BUY_BANK_SLOT= 45, + ACHIEVEMENT_CRITERIA_TYPE_GAIN_REPUTATION= 46, + ACHIEVEMENT_CRITERIA_TYPE_GAIN_EXALTED_REPUTATION= 47, + // noted: rewarded as soon as the player payed, not at taking place at the seat + ACHIEVEMENT_CRITERIA_TYPE_VISIT_BARBER_SHOP= 48, + ACHIEVEMENT_CRITERIA_TYPE_EQUIP_EPIC_ITEM = 49, + // TODO: itemlevel is mentioned in text but not present in dbc + ACHIEVEMENT_CRITERIA_TYPE_ROLL_NEED_ON_LOOT = 50, + ACHIEVEMENT_CRITERIA_TYPE_ROLL_GREED_ON_LOOT= 51, + ACHIEVEMENT_CRITERIA_TYPE_HK_CLASS = 52, + ACHIEVEMENT_CRITERIA_TYPE_HK_RACE = 53, + ACHIEVEMENT_CRITERIA_TYPE_DO_EMOTE = 54, + ACHIEVEMENT_CRITERIA_TYPE_HEALING_DONE = 55, + // TODO: in some cases map not present, and in some cases need do without die + ACHIEVEMENT_CRITERIA_TYPE_GET_KILLING_BLOWS = 56, + ACHIEVEMENT_CRITERIA_TYPE_EQUIP_ITEM = 57, + ACHIEVEMENT_CRITERIA_TYPE_MONEY_FROM_VENDORS = 59, + ACHIEVEMENT_CRITERIA_TYPE_GOLD_SPENT_FOR_TALENTS = 60, + ACHIEVEMENT_CRITERIA_TYPE_NUMBER_OF_TALENT_RESETS = 61, + ACHIEVEMENT_CRITERIA_TYPE_MONEY_FROM_QUEST_REWARD = 62, + ACHIEVEMENT_CRITERIA_TYPE_GOLD_SPENT_FOR_TRAVELLING = 63, + ACHIEVEMENT_CRITERIA_TYPE_GOLD_SPENT_AT_BARBER = 65, + ACHIEVEMENT_CRITERIA_TYPE_GOLD_SPENT_FOR_MAIL = 66, + ACHIEVEMENT_CRITERIA_TYPE_LOOT_MONEY = 67, + ACHIEVEMENT_CRITERIA_TYPE_USE_GAMEOBJECT = 68, + ACHIEVEMENT_CRITERIA_TYPE_BE_SPELL_TARGET2= 69, + ACHIEVEMENT_CRITERIA_TYPE_SPECIAL_PVP_KILL= 70, + ACHIEVEMENT_CRITERIA_TYPE_FISH_IN_GAMEOBJECT = 72, + // TODO: title id is not mentioned in dbc + ACHIEVEMENT_CRITERIA_TYPE_EARNED_PVP_TITLE = 74, + ACHIEVEMENT_CRITERIA_TYPE_LEARN_SKILLLINE_SPELLS= 75, + ACHIEVEMENT_CRITERIA_TYPE_WIN_DUEL = 76, + ACHIEVEMENT_CRITERIA_TYPE_LOSE_DUEL = 77, + // TODO: creature type (demon, undead etc.) is not stored in dbc + ACHIEVEMENT_CRITERIA_TYPE_KILL_CREATURE_TYPE = 78, + ACHIEVEMENT_CRITERIA_TYPE_GOLD_EARNED_BY_AUCTIONS= 80, + ACHIEVEMENT_CRITERIA_TYPE_CREATE_AUCTION= 82, + ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_AUCTION_BID= 83, + ACHIEVEMENT_CRITERIA_TYPE_WON_AUCTIONS= 84, + ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_AUCTION_SOLD = 85, + ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_GOLD_VALUE_OWNED = 86, + ACHIEVEMENT_CRITERIA_TYPE_GAIN_REVERED_REPUTATION = 87, + ACHIEVEMENT_CRITERIA_TYPE_GAIN_HONORED_REPUTATION = 88, + ACHIEVEMENT_CRITERIA_TYPE_KNOWN_FACTIONS = 89, + ACHIEVEMENT_CRITERIA_TYPE_LOOT_EPIC_ITEM = 90, + ACHIEVEMENT_CRITERIA_TYPE_RECEIVE_EPIC_ITEM = 91, + ACHIEVEMENT_CRITERIA_TYPE_ROLL_NEED = 93, + ACHIEVEMENT_CRITERIA_TYPE_ROLL_GREED = 94, + ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_HEALTH = 95, + ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_POWER = 96, + ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_STAT = 97, + ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_SPELLPOWER = 98, + ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_ARMOR = 99, + ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_RATING = 100, + ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_HIT_DEALT = 101, + ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_HIT_RECEIVED = 102, + ACHIEVEMENT_CRITERIA_TYPE_TOTAL_DAMAGE_RECEIVED = 103, + ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_HEAL_CASTED = 104, + ACHIEVEMENT_CRITERIA_TYPE_TOTAL_HEALING_RECEIVED = 105, + ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_HEALING_RECEIVED = 106, + ACHIEVEMENT_CRITERIA_TYPE_QUEST_ABANDONED = 107, + ACHIEVEMENT_CRITERIA_TYPE_FLIGHT_PATHS_TAKEN = 108, + ACHIEVEMENT_CRITERIA_TYPE_LOOT_TYPE = 109, + // TODO: target entry is missing + ACHIEVEMENT_CRITERIA_TYPE_CAST_SPELL2 = 110, + ACHIEVEMENT_CRITERIA_TYPE_LEARN_SKILL_LINE= 112, + ACHIEVEMENT_CRITERIA_TYPE_EARN_HONORABLE_KILL = 113, + ACHIEVEMENT_CRITERIA_TYPE_ACCEPTED_SUMMONINGS = 114, + // 0..114 => 115 criteria types total + ACHIEVEMENT_CRITERIA_TYPE_TOTAL = 115, +}; + enum AreaFlags { AREA_FLAG_SNOW = 0x00000001, // snow (only Dun Morogh, Naxxramas, Razorfen Downs and Winterspring) - AREA_FLAG_UNK1 = 0x00000002, // unknown, (only Naxxramas and Razorfen Downs) - AREA_FLAG_UNK2 = 0x00000004, // Only used on development map - AREA_FLAG_SLAVE_CAPITAL = 0x00000008, // slave capital city flag? - AREA_FLAG_UNK3 = 0x00000010, // unknown + AREA_FLAG_UNK1 = 0x00000002, // may be necropolis? + AREA_FLAG_UNK2 = 0x00000004, // Only used for areas on map 571 (development before) + AREA_FLAG_SLAVE_CAPITAL = 0x00000008, // city and city subsones + AREA_FLAG_UNK3 = 0x00000010, // can't find common meaning AREA_FLAG_SLAVE_CAPITAL2 = 0x00000020, // slave capital city flag? AREA_FLAG_UNK4 = 0x00000040, // many zones have this flag AREA_FLAG_ARENA = 0x00000080, // arena, both instanced and world arenas AREA_FLAG_CAPITAL = 0x00000100, // main capital city flag AREA_FLAG_CITY = 0x00000200, // only for one zone named "City" (where it located?) - AREA_FLAG_OUTLAND = 0x00000400, // outland zones? (only Eye of the Storm not have this flag, but have 0x00004000 flag) + AREA_FLAG_OUTLAND = 0x00000400, // expansion zones? (only Eye of the Storm not have this flag, but have 0x00004000 flag) AREA_FLAG_SANCTUARY = 0x00000800, // sanctuary area (PvP disabled) AREA_FLAG_NEED_FLY = 0x00001000, // only Netherwing Ledge, Socrethar's Seat, Tempest Keep, The Arcatraz, The Botanica, The Mechanar, Sorrow Wing Point, Dragonspine Ridge, Netherwing Mines, Dragonmaw Base Camp, Dragonmaw Skyway - AREA_FLAG_UNUSED1 = 0x00002000, // not used now (no area/zones with this flag set in 2.4.2) - AREA_FLAG_OUTLAND2 = 0x00004000, // outland zones? (only Circle of Blood Arena not have this flag, but have 0x00000400 flag) + AREA_FLAG_UNUSED1 = 0x00002000, // not used now (no area/zones with this flag set in 3.0.3) + AREA_FLAG_OUTLAND2 = 0x00004000, // expansion zones? (only Circle of Blood Arena not have this flag, but have 0x00000400 flag) AREA_FLAG_PVP = 0x00008000, // pvp objective area? (Death's Door also has this flag although it's no pvp object area) AREA_FLAG_ARENA_INSTANCE = 0x00010000, // used by instanced arenas only - AREA_FLAG_UNUSED2 = 0x00020000, // not used now (no area/zones with this flag set in 2.4.2) - AREA_FLAG_UNK5 = 0x00040000, // just used for Amani Pass, Hatchet Hills - AREA_FLAG_LOWLEVEL = 0x00100000 // used for some starting areas with area_level <=15 + AREA_FLAG_UNUSED2 = 0x00020000, // not used now (no area/zones with this flag set in 3.0.3) + AREA_FLAG_UNK5 = 0x00040000, // only used for Amani Pass, Hatchet Hills + AREA_FLAG_UNK6 = 0x00080000, // Valgarde and Acherus: The Ebon Hold + AREA_FLAG_LOWLEVEL = 0x00100000, // used for some starting areas with area_level <=15 + AREA_FLAG_TOWN = 0x00200000, // small towns with Inn + AREA_FLAG_UNK7 = 0x00400000, // Warsong Hold, Acherus: The Ebon Hold, New Agamand Inn, Vengeance Landing Inn + AREA_FLAG_UNK8 = 0x00800000, // Westguard Inn, Acherus: The Ebon Hold, Valgarde + AREA_FLAG_OUTDOOR_PVP = 0x01000000, // Wintergrasp and it's subzones + AREA_FLAG_UNK9 = 0x02000000, // unknown + AREA_FLAG_UNK10 = 0x04000000, // unknown + AREA_FLAG_OUTDOOR_PVP2 = 0x08000000 // Wintergrasp and it's subzones }; enum FactionTemplateFlags @@ -101,4 +271,51 @@ enum TotemCategoryType TOTEM_CATEGORY_TYPE_SPANNER = 24 }; +// SummonProperties.dbc, col 1 +/*enum SummonGroup +{ + SUMMON_GROUP_UNKNOWN1 = 0, // 1160 spells in 3.0.3 + SUMMON_GROUP_UNKNOWN2 = 1, // 861 spells in 3.0.3 + SUMMON_GROUP_PETS = 2, // 52 spells in 3.0.3, pets mostly + SUMMON_GROUP_CONTROLLABLE = 3, // 13 spells in 3.0.3, mostly controllable + SUMMON_GROUP_UNKNOWN3 = 4 // 86 spells in 3.0.3, taxi/mounts +}; + +// SummonProperties.dbc, col 3 +enum SummonType +{ + SUMMON_TYPE_UNKNOWN = 0, // different summons, 1330 spells in 3.0.3 + SUMMON_TYPE_SUMMON = 1, // generic summons, 49 spells in 3.0.3 + SUMMON_TYPE_GUARDIAN = 2, // summon guardian, 393 spells in 3.0.3 + SUMMON_TYPE_ARMY = 3, // summon army, 5 spells in 3.0.3 + SUMMON_TYPE_TOTEM = 4, // summon totem, 169 spells in 3.0.3 + SUMMON_TYPE_CRITTER = 5, // critter/minipet, 195 spells in 3.0.3 + SUMMON_TYPE_DK = 6, // summon DRW/Ghoul, 2 spells in 3.0.3 + SUMMON_TYPE_BOMB = 7, // summon bot/bomb, 4 spells in 3.0.3 + SUMMON_TYPE_PHASING = 8, // something todo with DK prequest line, 2 spells in 3.0.3 + SUMMON_TYPE_SIEGE_VEH = 9, // summon different vehicles, 14 spells in 3.0.3 + SUMMON_TYPE_DRAKE_VEH = 10, // summon drake (vehicle), 3 spells + SUMMON_TYPE_LIGHTWELL = 11 // summon lightwell, 6 spells in 3.0.3 +}; + +// SummonProperties.dbc, col 5 +enum SummonFlags +{ + SUMMON_FLAG_NONE = 0x0000, // 1342 spells in 3.0.3 + SUMMON_FLAG_UNK1 = 0x0001, // 75 spells in 3.0.3, something unfriendly + SUMMON_FLAG_UNK2 = 0x0002, // 616 spells in 3.0.3, something friendly + SUMMON_FLAG_UNK3 = 0x0004, // 22 spells in 3.0.3, no idea... + SUMMON_FLAG_UNK4 = 0x0008, // 49 spells in 3.0.3, some mounts + SUMMON_FLAG_UNK5 = 0x0010, // 25 spells in 3.0.3, quest related? + SUMMON_FLAG_UNK6 = 0x0020, // 0 spells in 3.0.3, unused + SUMMON_FLAG_UNK7 = 0x0040, // 12 spells in 3.0.3, no idea + SUMMON_FLAG_UNK8 = 0x0080, // 4 spells in 3.0.3, no idea + SUMMON_FLAG_UNK9 = 0x0100, // 51 spells in 3.0.3, no idea, many quest related + SUMMON_FLAG_UNK10 = 0x0200, // 51 spells in 3.0.3, something defensive + SUMMON_FLAG_UNK11 = 0x0400, // 3 spells, requires something near? + SUMMON_FLAG_UNK12 = 0x0800, // 30 spells in 3.0.3, no idea + SUMMON_FLAG_UNK13 = 0x1000, // 8 spells in 3.0.3, siege vehicle + SUMMON_FLAG_UNK14 = 0x2000, // 2 spells in 3.0.3, escort? +}; +*/ #endif diff --git a/src/shared/Database/DBCStores.cpp b/src/shared/Database/DBCStores.cpp index e733551d2..0ae6f663b 100644 --- a/src/shared/Database/DBCStores.cpp +++ b/src/shared/Database/DBCStores.cpp @@ -33,9 +33,12 @@ DBCStorage sAreaStore(AreaTableEntryfmt); static AreaFlagByAreaID sAreaFlagByAreaID; static AreaFlagByMapID sAreaFlagByMapID; // for instances without generated *.map files +DBCStorage sAchievementStore(Achievementfmt); +DBCStorage sAchievementCriteriaStore(AchievementCriteriafmt); DBCStorage sAreaTriggerStore(AreaTriggerEntryfmt); DBCStorage sBankBagSlotPricesStore(BankBagSlotPricesEntryfmt); DBCStorage sBattlemasterListStore(BattlemasterListEntryfmt); +DBCStorage sBarberShopStyleStore(BarberShopStyleEntryfmt); DBCStorage sCharStartOutfitStore(CharStartOutfitEntryfmt); DBCStorage sCharTitlesStore(CharTitlesEntryfmt); DBCStorage sChatChannelsStore(ChatChannelsEntryfmt); @@ -56,7 +59,10 @@ DBCStorage sFactionStore(FactionEntryfmt); DBCStorage sFactionTemplateStore(FactionTemplateEntryfmt); DBCStorage sGemPropertiesStore(GemPropertiesEntryfmt); +DBCStorage sGlyphPropertiesStore(GlyphPropertiesfmt); +DBCStorage sGlyphSlotStore(GlyphSlotfmt); +DBCStorage sGtBarberShopCostBaseStore(GtBarberShopCostBasefmt); DBCStorage sGtCombatRatingsStore(GtCombatRatingsfmt); DBCStorage sGtChanceToMeleeCritBaseStore(GtChanceToMeleeCritBasefmt); DBCStorage sGtChanceToMeleeCritStore(GtChanceToMeleeCritfmt); @@ -82,6 +88,8 @@ DBCStorage sMapStore(MapEntryfmt); DBCStorage sQuestSortStore(QuestSortEntryfmt); DBCStorage sRandomPropertiesPointsStore(RandomPropertiesPointsfmt); +DBCStorage sScalingStatDistributionStore(ScalingStatDistributionfmt); +DBCStorage sScalingStatValuesStore(ScalingStatValuesfmt); DBCStorage sSkillLineStore(SkillLinefmt); DBCStorage sSkillLineAbilityStore(SkillLineAbilityfmt); @@ -99,8 +107,10 @@ DBCStorage sSpellDurationStore(SpellDurationfmt); DBCStorage sSpellFocusObjectStore(SpellFocusObjectfmt); DBCStorage sSpellRadiusStore(SpellRadiusfmt); DBCStorage sSpellRangeStore(SpellRangefmt); +DBCStorage sSpellRuneCostStore(SpellRuneCostfmt); DBCStorage sSpellShapeshiftStore(SpellShapeshiftfmt); DBCStorage sStableSlotPricesStore(StableSlotPricesfmt); +//DBCStorage sSummonPropertiesStore(SummonPropertiesfmt); DBCStorage sTalentStore(TalentEntryfmt); TalentSpellPosMap sTalentSpellPosMap; DBCStorage sTalentTabStore(TalentTabEntryfmt); @@ -123,12 +133,15 @@ TaxiPathNodesByPath sTaxiPathNodesByPath; static DBCStorage sTaxiPathNodeStore(TaxiPathNodeEntryfmt); DBCStorage sTotemCategoryStore(TotemCategoryEntryfmt); +DBCStorage sVehicleStore(VehicleEntryfmt); +DBCStorage sVehicleSeatStore(VehicleSeatEntryfmt); DBCStorage sWorldMapAreaStore(WorldMapAreaEntryfmt); DBCStorage sWorldSafeLocsStore(WorldSafeLocsEntryfmt); +DBCStorage sWorldMapOverlayStore(WorldMapOverlayEntryfmt); typedef std::list StoreProblemList; -static bool LoadDBC_assert_print(uint32 fsize,uint32 rsize, std::string filename) +static bool LoadDBC_assert_print(uint32 fsize,uint32 rsize, const std::string& filename) { sLog.outError("ERROR: Size of '%s' setted by format string (%u) not equal size of C++ structure (%u).",filename.c_str(),fsize,rsize); @@ -137,7 +150,7 @@ static bool LoadDBC_assert_print(uint32 fsize,uint32 rsize, std::string filename } template -inline void LoadDBC(uint32& availableDbcLocales,barGoLink& bar, StoreProblemList& errlist, DBCStorage& storage, std::string dbc_path, std::string filename) +inline void LoadDBC(uint32& availableDbcLocales,barGoLink& bar, StoreProblemList& errlist, DBCStorage& storage, const std::string& dbc_path, const std::string& filename) { // compatibility format and C++ structure sizes assert(DBCFile::GetFormatRecordSize(storage.GetFormat()) == sizeof(T) || LoadDBC_assert_print(DBCFile::GetFormatRecordSize(storage.GetFormat()),sizeof(T),filename)); @@ -172,11 +185,11 @@ inline void LoadDBC(uint32& availableDbcLocales,barGoLink& bar, StoreProblemList } } -void LoadDBCStores(std::string dataPath) +void LoadDBCStores(const std::string& dataPath) { std::string dbcPath = dataPath+"dbc/"; - const uint32 DBCFilesCount = 56; + const uint32 DBCFilesCount = 66; barGoLink bar( DBCFilesCount ); @@ -194,16 +207,19 @@ void LoadDBCStores(std::string dataPath) sAreaFlagByAreaID.insert(AreaFlagByAreaID::value_type(uint16(area->ID),area->exploreFlag)); // fill MapId->DBC records ( skip sub zones and continents ) - if(area->zone==0 && area->mapid != 0 && area->mapid != 1 && area->mapid != 530 ) + if(area->zone==0 && area->mapid != 0 && area->mapid != 1 && area->mapid != 530 && area->mapid != 571 ) sAreaFlagByMapID.insert(AreaFlagByMapID::value_type(area->mapid,area->exploreFlag)); } } + LoadDBC(availableDbcLocales,bar,bad_dbc_files,sAchievementStore, dbcPath,"Achievement.dbc"); + LoadDBC(availableDbcLocales,bar,bad_dbc_files,sAchievementCriteriaStore, dbcPath,"Achievement_Criteria.dbc"); LoadDBC(availableDbcLocales,bar,bad_dbc_files,sAreaTriggerStore, dbcPath,"AreaTrigger.dbc"); LoadDBC(availableDbcLocales,bar,bad_dbc_files,sBankBagSlotPricesStore, dbcPath,"BankBagSlotPrices.dbc"); LoadDBC(availableDbcLocales,bar,bad_dbc_files,sBattlemasterListStore, dbcPath,"BattlemasterList.dbc"); + LoadDBC(availableDbcLocales,bar,bad_dbc_files,sBarberShopStyleStore, dbcPath,"BarberShopStyle.dbc"); LoadDBC(availableDbcLocales,bar,bad_dbc_files,sCharStartOutfitStore, dbcPath,"CharStartOutfit.dbc"); - + LoadDBC(availableDbcLocales,bar,bad_dbc_files,sCharTitlesStore, dbcPath,"CharTitles.dbc"); LoadDBC(availableDbcLocales,bar,bad_dbc_files,sChatChannelsStore, dbcPath,"ChatChannels.dbc"); LoadDBC(availableDbcLocales,bar,bad_dbc_files,sChrClassesStore, dbcPath,"ChrClasses.dbc"); @@ -227,7 +243,10 @@ void LoadDBCStores(std::string dataPath) LoadDBC(availableDbcLocales,bar,bad_dbc_files,sFactionTemplateStore, dbcPath,"FactionTemplate.dbc"); LoadDBC(availableDbcLocales,bar,bad_dbc_files,sGemPropertiesStore, dbcPath,"GemProperties.dbc"); + LoadDBC(availableDbcLocales,bar,bad_dbc_files,sGlyphPropertiesStore, dbcPath,"GlyphProperties.dbc"); + LoadDBC(availableDbcLocales,bar,bad_dbc_files,sGlyphSlotStore, dbcPath,"GlyphSlot.dbc"); + LoadDBC(availableDbcLocales,bar,bad_dbc_files,sGtBarberShopCostBaseStore,dbcPath,"gtBarberShopCostBase.dbc"); LoadDBC(availableDbcLocales,bar,bad_dbc_files,sGtCombatRatingsStore, dbcPath,"gtCombatRatings.dbc"); LoadDBC(availableDbcLocales,bar,bad_dbc_files,sGtChanceToMeleeCritBaseStore, dbcPath,"gtChanceToMeleeCritBase.dbc"); @@ -252,6 +271,8 @@ void LoadDBCStores(std::string dataPath) LoadDBC(availableDbcLocales,bar,bad_dbc_files,sMapStore, dbcPath,"Map.dbc"); LoadDBC(availableDbcLocales,bar,bad_dbc_files,sQuestSortStore, dbcPath,"QuestSort.dbc"); LoadDBC(availableDbcLocales,bar,bad_dbc_files,sRandomPropertiesPointsStore, dbcPath,"RandPropPoints.dbc"); + LoadDBC(availableDbcLocales,bar,bad_dbc_files,sScalingStatDistributionStore, dbcPath,"ScalingStatDistribution.dbc"); + LoadDBC(availableDbcLocales,bar,bad_dbc_files,sScalingStatValuesStore, dbcPath,"ScalingStatValues.dbc"); LoadDBC(availableDbcLocales,bar,bad_dbc_files,sSkillLineStore, dbcPath,"SkillLine.dbc"); LoadDBC(availableDbcLocales,bar,bad_dbc_files,sSkillLineAbilityStore, dbcPath,"SkillLineAbility.dbc"); LoadDBC(availableDbcLocales,bar,bad_dbc_files,sSoundEntriesStore, dbcPath,"SoundEntries.dbc"); @@ -301,8 +322,10 @@ void LoadDBCStores(std::string dataPath) LoadDBC(availableDbcLocales,bar,bad_dbc_files,sSpellItemEnchantmentConditionStore,dbcPath,"SpellItemEnchantmentCondition.dbc"); LoadDBC(availableDbcLocales,bar,bad_dbc_files,sSpellRadiusStore, dbcPath,"SpellRadius.dbc"); LoadDBC(availableDbcLocales,bar,bad_dbc_files,sSpellRangeStore, dbcPath,"SpellRange.dbc"); + LoadDBC(availableDbcLocales,bar,bad_dbc_files,sSpellRuneCostStore, dbcPath,"SpellRuneCost.dbc"); LoadDBC(availableDbcLocales,bar,bad_dbc_files,sSpellShapeshiftStore, dbcPath,"SpellShapeshiftForm.dbc"); LoadDBC(availableDbcLocales,bar,bad_dbc_files,sStableSlotPricesStore, dbcPath,"StableSlotPrices.dbc"); + //LoadDBC(availableDbcLocales,bar,bad_dbc_files,sSummonPropertiesStore, dbcPath,"SummonProperties.dbc"); LoadDBC(availableDbcLocales,bar,bad_dbc_files,sTalentStore, dbcPath,"Talent.dbc"); // create talent spells set @@ -405,7 +428,10 @@ void LoadDBCStores(std::string dataPath) pathLength.resize(pathCount); // 0 and some other indexes not used for(uint32 i = 1; i < sTaxiPathNodeStore.GetNumRows(); ++i) if(TaxiPathNodeEntry const* entry = sTaxiPathNodeStore.LookupEntry(i)) - ++pathLength[entry->path]; + { + if (pathLength[entry->path] < entry->index + 1) + pathLength[entry->path] = entry->index + 1; + } // Set path length sTaxiPathNodesByPath.resize(pathCount); // 0 and some other indexes not used for(uint32 i = 1; i < sTaxiPathNodesByPath.size(); ++i) @@ -417,8 +443,11 @@ void LoadDBCStores(std::string dataPath) sTaxiPathNodeStore.Clear(); LoadDBC(availableDbcLocales,bar,bad_dbc_files,sTotemCategoryStore, dbcPath,"TotemCategory.dbc"); + LoadDBC(availableDbcLocales,bar,bad_dbc_files,sVehicleStore, dbcPath,"Vehicle.dbc"); + LoadDBC(availableDbcLocales,bar,bad_dbc_files,sVehicleSeatStore, dbcPath,"VehicleSeat.dbc"); LoadDBC(availableDbcLocales,bar,bad_dbc_files,sWorldMapAreaStore, dbcPath,"WorldMapArea.dbc"); LoadDBC(availableDbcLocales,bar,bad_dbc_files,sWorldSafeLocsStore, dbcPath,"WorldSafeLocs.dbc"); + LoadDBC(availableDbcLocales,bar,bad_dbc_files,sWorldMapOverlayStore, dbcPath,"WorldMapOverlay.dbc"); // error checks if(bad_dbc_files.size() >= DBCFilesCount ) @@ -436,20 +465,20 @@ void LoadDBCStores(std::string dataPath) exit(1); } - // check at up-to-date DBC files (53085 is last added spell in 2.4.3) - // check at up-to-date DBC files (17514 is last ID in SkillLineAbilities in 2.4.3) - // check at up-to-date DBC files (598 is last map added in 2.4.3) - // check at up-to-date DBC files (1127 is last gem property added in 2.4.3) - // check at up-to-date DBC files (2425 is last item extended cost added in 2.4.3) - // check at up-to-date DBC files (71 is last char title added in 2.4.3) - // check at up-to-date DBC files (1768 is last area added in 2.4.3) - if( !sSpellStore.LookupEntry(53085) || - !sSkillLineAbilityStore.LookupEntry(17514) || - !sMapStore.LookupEntry(598) || - !sGemPropertiesStore.LookupEntry(1127) || - !sItemExtendedCostStore.LookupEntry(2425) || - !sCharTitlesStore.LookupEntry(71) || - !sAreaStore.LookupEntry(1768) ) + // check at up-to-date DBC files (54909 is last added spell in 3.0.1) + // check at up-to-date DBC files (19162 is last added spell in abilities in 3.0.1) + // check at up-to-date DBC files (619 is last map added in 3.0.1) + // check at up-to-date DBC files (1361 is last gem property added in 3.0.1) + // check at up-to-date DBC files (2425 is last item extended cost added in 3.0.1) + // check at up-to-date DBC files (76 is last char title added in 3.0.1) + // check at up-to-date DBC files (2311 is last area added in 3.0.1) + if( !sSpellStore.LookupEntry(54909) || + !sSkillLineAbilityStore.LookupEntry(19162) || + !sMapStore.LookupEntry(619) || + !sGemPropertiesStore.LookupEntry(1361) || + !sItemExtendedCostStore.LookupEntry(2425) || + !sCharTitlesStore.LookupEntry(76) || + !sAreaStore.LookupEntry(2311) ) { sLog.outError("\nYou have _outdated_ DBC files. Please extract correct versions from current using client."); exit(1); @@ -535,7 +564,7 @@ uint32 GetAreaFlagByMapId(uint32 mapid) uint32 GetVirtualMapForMapAndZone(uint32 mapid, uint32 zoneId) { - if(mapid != 530) // speed for most cases + if(mapid != 530 || mapid != 571) // speed for most cases return mapid; if(WorldMapAreaEntry const* wma = sWorldMapAreaStore.LookupEntry(zoneId)) diff --git a/src/shared/Database/DBCStores.h b/src/shared/Database/DBCStores.h index 7811286c0..8143ec704 100644 --- a/src/shared/Database/DBCStores.h +++ b/src/shared/Database/DBCStores.h @@ -130,9 +130,12 @@ class DBCStorage StringPoolList m_stringPoolList; }; +extern DBCStorage sAchievementStore; +extern DBCStorage sAchievementCriteriaStore; extern DBCStorage sAreaStore;// recommend access using functions extern DBCStorage sAreaTriggerStore; extern DBCStorage sBankBagSlotPricesStore; +extern DBCStorage sBarberShopStyleStore; extern DBCStorage sBattlemasterListStore; //extern DBCStorage sChatChannelsStore; -- accessed using function, no usable index extern DBCStorage sCharStartOutfitStore; @@ -148,7 +151,10 @@ extern DBCStorage sEmotesTextStore; extern DBCStorage sFactionStore; extern DBCStorage sFactionTemplateStore; extern DBCStorage sGemPropertiesStore; +extern DBCStorage sGlyphPropertiesStore; +extern DBCStorage sGlyphSlotStore; +extern DBCStorage sGtBarberShopCostBaseStore; extern DBCStorage sGtCombatRatingsStore; extern DBCStorage sGtChanceToMeleeCritBaseStore; extern DBCStorage sGtChanceToMeleeCritStore; @@ -169,6 +175,8 @@ extern DBCStorage sMailTemplateStore; extern DBCStorage sMapStore; extern DBCStorage sQuestSortStore; extern DBCStorage sRandomPropertiesPointsStore; +extern DBCStorage sScalingStatDistributionStore; +extern DBCStorage sScalingStatValuesStore; extern DBCStorage sSkillLineStore; extern DBCStorage sSkillLineAbilityStore; extern DBCStorage sSoundEntriesStore; @@ -181,9 +189,11 @@ extern SpellCategoryStore sSpellCategoryStore; extern PetFamilySpellsStore sPetFamilySpellsStore; extern DBCStorage sSpellRadiusStore; extern DBCStorage sSpellRangeStore; +extern DBCStorage sSpellRuneCostStore; extern DBCStorage sSpellShapeshiftStore; extern DBCStorage sSpellStore; extern DBCStorage sStableSlotPricesStore; +//extern DBCStorage sSummonPropertiesStore; extern DBCStorage sTalentStore; extern DBCStorage sTalentTabStore; extern DBCStorage sTaxiNodesStore; @@ -192,10 +202,13 @@ extern TaxiMask sTaxiNodesMask; extern TaxiPathSetBySource sTaxiPathSetBySource; extern TaxiPathNodesByPath sTaxiPathNodesByPath; extern DBCStorage sTotemCategoryStore; +extern DBCStorage sVehicleStore; +extern DBCStorage sVehicleSeatStore; //extern DBCStorage sWorldMapAreaStore; -- use Zone2MapCoordinates and Map2ZoneCoordinates extern DBCStorage sWorldSafeLocsStore; +extern DBCStorage sWorldMapOverlayStore; -void LoadDBCStores(std::string dataPath); +void LoadDBCStores(const std::string& dataPath); // script support functions MANGOS_DLL_SPEC DBCStorage const* GetSoundEntriesStore(); diff --git a/src/shared/Database/DBCStructure.h b/src/shared/Database/DBCStructure.h index 59d5d18c4..839687f3d 100644 --- a/src/shared/Database/DBCStructure.h +++ b/src/shared/Database/DBCStructure.h @@ -35,57 +35,507 @@ #pragma pack(push,1) #endif -struct AreaTableEntry +struct AchievementEntry { uint32 ID; // 0 - uint32 mapid; // 1 - uint32 zone; // 2 if 0 then it's zone, else it's zone id of this area - uint32 exploreFlag; // 3, main index - uint32 flags; // 4, unknown value but 312 for all cities + uint32 factionFlag; // 1 -1=all, 0=horde, 1=alliance + uint32 mapID; // 2 -1=none + //uint32 parentAchievement; // 3 its Achievement parent (can`t start while parent uncomplete, use its Criteria if don`t have own, use its progress on begin) + //char *name[16]; // 4-19 + //uint32 name_flags; // 20 + //char *description[16]; // 21-36 + //uint32 desc_flags; // 37 + uint32 categoryId; // 38 + uint32 points; // 39 reward points + //uint32 OrderInCategory; // 40 + uint32 flags; // 41 + //uint32 icon; // 42 icon (from SpellIcon.dbc) + //char *titleReward[16]; // 43-58 + //uint32 titleReward_flags; // 59 + //uint32 count; // 60 - need this count Criteria for complete + uint32 refAchievement; // 61 - related achievement? +}; + +struct AchievementCategoryEntry +{ + uint32 ID; // 0 + uint32 parentCategory; // 1 -1 for main category + //char *name[16]; // 2-17 + //uint32 name_flags; // 18 + //uint32 sortOrder; // 19 +}; + +struct AchievementCriteriaEntry +{ + uint32 ID; // 0 + uint32 referredAchievement; // 1 + uint32 requiredType; // 2 + union + { + // ACHIEVEMENT_CRITERIA_TYPE_KILL_CREATURE = 0 + // TODO: also used for player deaths.. + struct + { + uint32 creatureID; // 3 + uint32 creatureCount; // 4 + } kill_creature; + + // ACHIEVEMENT_CRITERIA_TYPE_WIN_BG = 1 + // TODO: there are further criterias instead just winning + struct + { + uint32 bgMapID; // 3 + uint32 winCount; // 4 + } win_bg; + + // ACHIEVEMENT_CRITERIA_TYPE_REACH_LEVEL = 5 + struct + { + uint32 unused; // 3 + uint32 level; // 4 + } reach_level; + + // ACHIEVEMENT_CRITERIA_TYPE_REACH_SKILL_LEVEL = 7 + struct + { + uint32 skillID; // 3 + uint32 skillLevel; // 4 + } reach_skill_level; + + // ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_ACHIEVEMENT = 8 + struct + { + uint32 linkedAchievement; // 3 + } complete_achievement; + + // ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_QUEST_COUNT = 9 + struct + { + uint32 unused; // 3 + uint32 totalQuestCount; // 4 + } complete_quest_count; + + // ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_DAILY_QUEST_DAILY = 10 + struct + { + uint32 unused; // 3 + uint32 numberOfDays; // 4 + } complete_daily_quest_daily; + + // ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_QUESTS_IN_ZONE = 11 + struct + { + uint32 zoneID; // 3 + uint32 questCount; // 4 + } complete_quests_in_zone; + + // ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_DAILY_QUEST = 14 + struct + { + uint32 unused; // 3 + uint32 questCount; // 4 + } complete_daily_quest; + + // ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_BATTLEGROUND= 15 + struct + { + uint32 mapID; // 3 + } complete_battleground; + + // ACHIEVEMENT_CRITERIA_TYPE_DEATH_AT_MAP= 16 + struct + { + uint32 mapID; // 3 + } death_at_map; + + // ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_RAID = 19 + struct + { + uint32 groupSize; // 3 can be 5, 10 or 25 + } complete_raid; + + // ACHIEVEMENT_CRITERIA_TYPE_KILLED_BY_CREATURE = 20 + struct + { + uint32 creatureEntry; // 3 + } killed_by_creature; + + // ACHIEVEMENT_CRITERIA_TYPE_FALL_WITHOUT_DYING = 24 + struct + { + uint32 unused; // 3 + uint32 fallHeight; // 4 + } fall_without_dying; + + // ACHIEVEMENT_CRITERIA_TYPE_DEATHS_FROM = 26 + struct + { + uint32 type; // 0 - fatigue, 1 - drowning, 2 - falling, 3 - ??, 5 - fire and lava + } deaths; + + // ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_QUEST = 27 + struct + { + uint32 questID; // 3 + uint32 questCount; // 4 + } complete_quest; + + // ACHIEVEMENT_CRITERIA_TYPE_BE_SPELL_TARGET = 28 + // ACHIEVEMENT_CRITERIA_TYPE_BE_SPELL_TARGET2= 69 + struct + { + uint32 spellID; // 3 + uint32 spellCount; // 4 + } be_spell_target; + + // ACHIEVEMENT_CRITERIA_TYPE_CAST_SPELL= 29 + // ACHIEVEMENT_CRITERIA_TYPE_CAST_SPELL2 = 110 + struct + { + uint32 spellID; // 3 + uint32 castCount; // 4 + } cast_spell; + + // ACHIEVEMENT_CRITERIA_TYPE_HONORABLE_KILL_AT_AREA = 31 + struct + { + uint32 areaID; // 3 Reference to AreaTable.dbc + uint32 killCount; // 4 + } honorable_kill_at_area; + + // ACHIEVEMENT_CRITERIA_TYPE_WIN_ARENA = 32 + struct + { + uint32 mapID; // 3 Reference to Map.dbc + } win_arena; + + // ACHIEVEMENT_CRITERIA_TYPE_PLAY_ARENA = 33 + struct + { + uint32 mapID; // 3 Reference to Map.dbc + } play_arena; + + // ACHIEVEMENT_CRITERIA_TYPE_LEARN_SPELL = 34 + struct + { + uint32 spellID; // 3 Reference to Map.dbc + } learn_spell; + + // ACHIEVEMENT_CRITERIA_TYPE_OWN_ITEM = 36 + struct + { + uint32 itemID; // 3 + uint32 itemCount; // 4 + } own_item; + + // ACHIEVEMENT_CRITERIA_TYPE_WIN_RATED_ARENA = 37 + struct + { + uint32 unused; // 3 + uint32 count; // 4 + uint32 flag; // 5 4=in a row + } win_rated_arena; + + // ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_TEAM_RATING = 38 + struct + { + uint32 teamtype; // 3 {2,3,5} + } highest_team_rating; + + // ACHIEVEMENT_CRITERIA_TYPE_REACH_TEAM_RATING = 39 + struct + { + uint32 teamtype; // 3 {2,3,5} + uint32 teamrating; // 4 + } reach_team_rating; + + // ACHIEVEMENT_CRITERIA_TYPE_LEARN_SKILL_LEVEL = 40 + struct + { + uint32 skillID; // 3 + uint32 skillLevel; // 4 apprentice=1, journeyman=2, expert=3, artisan=4, master=5, grand master=6 + } learn_skill_level; + + // ACHIEVEMENT_CRITERIA_TYPE_USE_ITEM = 41 + struct + { + uint32 itemID; // 3 + uint32 itemCount; // 4 + } use_item; + + // ACHIEVEMENT_CRITERIA_TYPE_LOOT_ITEM = 42 + struct + { + uint32 itemID; // 3 + uint32 itemCount; // 4 + } loot_item; + + // ACHIEVEMENT_CRITERIA_TYPE_EXPLORE_AREA = 43 + struct + { + // TODO: This rank is _NOT_ the index from AreaTable.dbc + uint32 areaReference; // 3 + } explore_area; + + // ACHIEVEMENT_CRITERIA_TYPE_OWN_RANK= 44 + struct + { + // TODO: This rank is _NOT_ the index from CharTitles.dbc + uint32 rank; // 3 + } own_rank; + + // ACHIEVEMENT_CRITERIA_TYPE_BUY_BANK_SLOT= 45 + struct + { + uint32 unused; // 3 + uint32 numberOfSlots; // 4 + } buy_bank_slot; + + // ACHIEVEMENT_CRITERIA_TYPE_GAIN_REPUTATION= 46 + struct + { + uint32 factionID; // 3 + uint32 reputationAmount; // 4 Total reputation amount, so 42000 = exalted + } gain_reputation; + + // ACHIEVEMENT_CRITERIA_TYPE_GAIN_EXALTED_REPUTATION= 47 + struct + { + uint32 unused; // 3 + uint32 numberOfExaltedFactions; // 4 + } gain_exalted_reputation; + + // ACHIEVEMENT_CRITERIA_TYPE_VISIT_BARBER_SHOP = 48 + struct + { + uint32 unused; // 3 + uint32 numberOfVisits; // 4 + } visit_barber; + + // ACHIEVEMENT_CRITERIA_TYPE_EQUIP_EPIC_ITEM = 49 + // TODO: where is the required itemlevel stored? + struct + { + uint32 itemSlot; // 3 + } equip_epic_item; + + // ACHIEVEMENT_CRITERIA_TYPE_ROLL_NEED_ON_LOOT= 50 + struct + { + uint32 rollValue; // 3 + uint32 count; // 4 + } roll_need_on_loot; + + // ACHIEVEMENT_CRITERIA_TYPE_HK_CLASS = 52 + struct + { + uint32 classID; // 3 + uint32 count; // 4 + } hk_class; + + // ACHIEVEMENT_CRITERIA_TYPE_HK_RACE = 53 + struct + { + uint32 raceID; // 3 + uint32 count; // 4 + } hk_race; + + // ACHIEVEMENT_CRITERIA_TYPE_DO_EMOTE = 54 + // TODO: where is the information about the target stored? + struct + { + uint32 emoteID; // 3 + } do_emote; + // ACHIEVEMENT_CRITERIA_TYPE_DAMAGE_DONE = 13 + // ACHIEVEMENT_CRITERIA_TYPE_HEALING_DONE = 55 + // ACHIEVEMENT_CRITERIA_TYPE_GET_KILLING_BLOWS = 56 + struct + { + uint32 unused; // 3 + uint32 count; // 4 + uint32 flag; // 5 =3 for battleground healing + uint32 mapid; // 6 + } healing_done; + + // ACHIEVEMENT_CRITERIA_TYPE_EQUIP_ITEM = 57 + struct + { + uint32 itemID; // 3 + } equip_item; + + + // ACHIEVEMENT_CRITERIA_TYPE_LOOT_MONEY = 67 + struct + { + uint32 unused; // 3 + uint32 goldInCopper; // 4 + } loot_money; + + // ACHIEVEMENT_CRITERIA_TYPE_USE_GAMEOBJECT = 68 + struct + { + uint32 goEntry; // 3 + uint32 useCount; // 4 + } use_gameobject; + + // ACHIEVEMENT_CRITERIA_TYPE_SPECIAL_PVP_KILL= 70 + // TODO: are those special criteria stored in the dbc or do we have to add another sql table? + struct + { + uint32 unused; // 3 + uint32 killCount; // 4 + } special_pvp_kill; + + // ACHIEVEMENT_CRITERIA_TYPE_FISH_IN_GAMEOBJECT = 72 + struct + { + uint32 goEntry; // 3 + uint32 lootCount; // 4 + } fish_in_gameobject; + + // ACHIEVEMENT_CRITERIA_TYPE_LEARN_SKILLLINE_SPELLS= 75 + struct + { + uint32 skillLine; // 3 + uint32 spellCount; // 4 + } learn_skilline_spell; + + // ACHIEVEMENT_CRITERIA_TYPE_WIN_DUEL = 76 + struct + { + uint32 unused; // 3 + uint32 duelCount; // 4 + } win_duel; + + // ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_POWER = 96 + struct + { + uint32 powerType; // 3 mana=0, 1=rage, 3=energy, 6=runic power + } highest_power; + + // ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_STAT = 97 + struct + { + uint32 statType; // 3 4=spirit, 3=int, 2=stamina, 1=agi, 0=strength + } highest_stat; + + // ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_SPELLPOWER = 98 + struct + { + uint32 spellSchool; // 3 + } highest_spellpower; + + // ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_RATING = 100 + struct + { + uint32 ratingType; // 3 + } highest_rating; + + // ACHIEVEMENT_CRITERIA_TYPE_LOOT_TYPE = 109 + struct + { + uint32 lootType; // 3 3=fishing, 2=pickpocket, 4=disentchant + uint32 lootTypeCount; // 4 + } loot_type; + + // ACHIEVEMENT_CRITERIA_TYPE_LEARN_SKILL_LINE= 112 + struct + { + uint32 skillLine; // 3 + uint32 spellCount; // 4 + } learn_skill_line; + + // ACHIEVEMENT_CRITERIA_TYPE_EARN_HONORABLE_KILL = 113 + struct + { + uint32 unused; // 3 + uint32 killCount; // 4 + } honorable_kill; + + struct + { + uint32 field3; // 3 main requirement + uint32 field4; // 4 main requirement count + uint32 additionalRequirement1_type; // 5 additional requirement 1 type + uint32 additionalRequirement1_value; // 6 additional requirement 1 value + uint32 additionalRequirement2_type; // 7 additional requirement 2 type + uint32 additionalRequirement2_value; // 8 additional requirement 1 value + } raw; + }; + //char* name[16]; // 9-24 + //uint32 name_flags; // 25 + uint32 completionFlag; // 26 + uint32 groupFlag; // 27 + //uint32 unk1; // 28 + uint32 timeLimit; // 29 time limit in seconds + //uint32 showOrder; // 30 show order +}; + +struct AreaTableEntry +{ + uint32 ID; // 0 + uint32 mapid; // 1 + uint32 zone; // 2 if 0 then it's zone, else it's zone id of this area + uint32 exploreFlag; // 3, main index + uint32 flags; // 4, unknown value but 312 for all cities // 5-9 unused - int32 area_level; // 10 - char* area_name[16]; // 11-26 + int32 area_level; // 10 + char* area_name[16]; // 11-26 // 27, string flags, unused - uint32 team; // 28 + uint32 team; // 28 }; struct AreaTriggerEntry { - uint32 id; // 0 - uint32 mapid; // 1 - float x; // 2 - float y; // 3 - float z; // 4 - float radius; // 5 - float box_x; // 6 extent x edge - float box_y; // 7 extent y edge - float box_z; // 8 extent z edge - float box_orientation; // 9 extent rotation by about z axis + uint32 id; // 0 m_ID + uint32 mapid; // 1 m_ContinentID + float x; // 2 m_x + float y; // 3 m_y + float z; // 4 m_z + float radius; // 5 m_radius + float box_x; // 6 m_box_length + float box_y; // 7 m_box_width + float box_z; // 8 m_box_heigh + float box_orientation; // 9 m_box_yaw }; struct BankBagSlotPricesEntry { - uint32 ID; - uint32 price; + uint32 ID; + uint32 price; +}; + +struct BarberShopStyleEntry +{ + uint32 Id; // 0 + uint32 type; // 1 value 0 -> hair, value 2 -> facialhair + //char* name[16]; // 2-17 name of hair style + //uint32 name_flags; // 18 + //uint32 unk_name[16]; // 19-34, all empty + //uint32 unk_flags; // 35 + //float CostMultiplier; // 36 values 1 and 0.75 + uint32 race; // 37 race + uint32 gender; // 38 0 -> male, 1 -> female + uint32 hair_id; // 39 real ID to hair/facial hair }; struct BattlemasterListEntry { - uint32 id; // 0 - uint32 mapid[3]; // 1-3 mapid - // 4-8 unused - uint32 type; // 9 (3 - BG, 4 - arena) - uint32 minlvl; // 10 - uint32 maxlvl; // 11 - uint32 maxplayersperteam; // 12 - // 13-14 unused - char* name[16]; // 15-30 - // 31 string flag, unused - // 32 unused + uint32 id; // 0 + int32 mapid[8]; // 1-8 mapid + uint32 type; // 9 (3 - BG, 4 - arena) + uint32 minlvl; // 10 + uint32 maxlvl; // 11 + uint32 maxplayersperteam; // 12 + // 13 minplayers + // 14 0 or 9 + // 15 + char* name[16]; // 16-31 + // 32 string flag, unused + // 33 unused }; -#define MAX_OUTFIT_ITEMS 12 -// #define MAX_OUTFIT_ITEMS 24 // 12->24 in 3.0.x +#define MAX_OUTFIT_ITEMS 24 struct CharStartOutfitEntry { @@ -101,20 +551,20 @@ struct CharStartOutfitEntry struct CharTitlesEntry { - uint32 ID; // 0, title ids, for example in Quest::GetCharTitleId() + uint32 ID; // 0, title ids, for example in Quest::GetCharTitleId() //uint32 unk1; // 1 flags? //char* name[16]; // 2-17, unused // 18 string flag, unused //char* name2[16]; // 19-34, unused // 35 string flag, unused - uint32 bit_index; // 36 used in PLAYER_CHOSEN_TITLE and 1<