*Update to Mangos 6938. (Only build for VC9)

--HG--
branch : trunk
This commit is contained in:
megamage committed 2008-12-24 09:58:26 -06:00
1 parent c81299e653
commit 3cb4e7c716
171 files changed
+11207 -5092

No files matched your search

+3
View File
@@ -20,6 +20,9 @@ similar to this one:
Thanks to the ScriptDev2 team (http://www.scriptdev2.com) for scripts.
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.
+71 -47
View File
@@ -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<argc;c++)
for(int c = 1; c < argc; ++c)
{
//i - input path
//o - output path
//r - resolution, array of (r * r) heights will be created
//e - extract only MAP(1)/DBC(2) - standard both(3)
// i - input path
// o - output path
// r - resolution, array of (r * r) heights will be created
// e - extract only MAP(1)/DBC(2) - standard both(3)
if(arg[c][0] != '-')
Usage(arg[0]);
switch(arg[c][1])
{
case 'i':
if(c+1<argc)//all ok
strcpy(input_path,arg[(c++) +1]);
if(c + 1 < argc) // all ok
strcpy(input_path, arg[(c++) + 1]);
else
Usage(arg[0]);
break;
case 'o':
if(c+1<argc)//all ok
strcpy(output_path,arg[(c++) +1]);
if(c + 1 < argc) // all ok
strcpy(output_path, arg[(c++) + 1]);
else
Usage(arg[0]);
break;
case 'r':
if(c+1<argc)//all ok
iRes=atoi(arg[(c++) +1]);
if(c + 1 < argc) // all ok
iRes=atoi(arg[(c++) + 1]);
else
Usage(arg[0]);
break;
case 'e':
if(c+1<argc)//all ok
if(c + 1 < argc) // all ok
{
extract=atoi(arg[(c++) +1]);
extract=atoi(arg[(c++) + 1]);
if(!(extract > 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;x<map_count;x++)
size_t map_count = dbc.getRecordCount();
map_ids = new map_id[map_count];
for(uint32 x = 0; x < map_count; ++x)
{
map_ids[x].id=dbc.getRecord(x).getUInt(0);
strcpy(map_ids[x].name,dbc.getRecord(x).getString(1));
map_ids[x].id = dbc.getRecord(x).getUInt(0);
strcpy(map_ids[x].name, dbc.getRecord(x).getString(1));
}
printf("Done! (%u maps loaded)\n", map_count);
return map_count;
@@ -135,20 +137,39 @@ uint32 ReadMapDBC()
void ReadAreaTableDBC()
{
printf("Read AreaTable.dbc file... ");
printf("Read AreaTable.dbc file...");
DBCFile dbc("DBFilesClient\\AreaTable.dbc");
dbc.open();
unsigned int area_count=dbc.getRecordCount();
uint32 maxid = dbc.getMaxId();
areas=new uint16[maxid + 1];
memset(areas, 0xff, sizeof(areas));
for(unsigned int x=0; x<area_count;++x)
size_t area_count = dbc.getRecordCount();
size_t maxid = dbc.getMaxId();
areas = new uint16[maxid + 1];
memset(areas, 0xff, (maxid + 1) * sizeof(uint16));
for(uint32 x = 0; x < area_count; ++x)
areas[dbc.getRecord(x).getUInt(0)] = dbc.getRecord(x).getUInt(3);
maxAreaId = dbc.getMaxId();
printf("Done! (%u areas loaded)\n", area_count);
}
void ReadLiquidTypeTableDBC()
{
printf("Read LiquidType.dbc file...");
DBCFile dbc("DBFilesClient\\LiquidType.dbc");
dbc.open();
size_t LiqType_count = dbc.getRecordCount();
size_t LiqType_maxid = dbc.getMaxId();
LiqType = new uint16[LiqType_maxid + 1];
memset(LiqType, 0xff, (LiqType_maxid + 1) * sizeof(uint16));
for(uint32 x = 0; x < LiqType_count; ++x)
LiqType[dbc.getRecord(x).getUInt(0)] = dbc.getRecord(x).getUInt(3);
printf("Done! (%u LiqTypes loaded)\n", LiqType_count);
}
void ExtractMapsFromMpq()
{
char mpq_filename[1024];
@@ -159,27 +180,28 @@ void ExtractMapsFromMpq()
uint32 map_count = ReadMapDBC();
ReadAreaTableDBC();
ReadLiquidTypeTableDBC();
unsigned int total=map_count*ADT_RES*ADT_RES;
unsigned int done=0;
unsigned int total = map_count * ADT_RES * ADT_RES;
unsigned int done = 0;
std::string path = output_path;
path += "/maps/";
CreateDir(path);
for(unsigned int x = 0; x < ADT_RES; ++x)
for(uint32 x = 0; x < ADT_RES; ++x)
{
for(unsigned int y = 0; y < ADT_RES; ++y)
for(uint32 y = 0; y < ADT_RES; ++y)
{
for(unsigned int z = 0; z < map_count; ++z)
for(uint32 z = 0; z < map_count; ++z)
{
sprintf(mpq_filename,"World\\Maps\\%s\\%s_%u_%u.adt",map_ids[z].name,map_ids[z].name,x,y);
sprintf(output_filename,"%s/maps/%03u%02u%02u.map",output_path,map_ids[z].id,y,x);
ConvertADT(mpq_filename,output_filename);
sprintf(mpq_filename, "World\\Maps\\%s\\%s_%u_%u.adt", map_ids[z].name, map_ids[z].name, x, y);
sprintf(output_filename, "%s/maps/%03u%02u%02u.map", output_path, map_ids[z].id, y, x);
ConvertADT(mpq_filename, output_filename);
done++;
}
//draw progess bar
printf("Processing........................%d%%\r",(100*done)/total);
// draw progress bar
printf("Processing........................%d%%\r", (100 * done) / total);
}
}
@@ -222,7 +244,7 @@ void ExtractDBCFiles(int locale, bool basicLocale)
string filename = path;
filename += (iter->c_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);
@@ -271,7 +295,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);
}
Binary file not shown.
+263 -267
View File
@@ -15,16 +15,15 @@
#include "adt.h"
#include "mpq_libmpq.h"
//#include <windows.h>
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,56 +34,84 @@ 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()<fs)
chunk_num = 0;
k = 0;
m = 0;
while (!mf.isEof())
{
uint32 fourcc;
mf.read(&fourcc,4);
mf.read(&fourcc, 4);
mf.read(&size, 4);
size_t nextpos = mf.getPos() + size;
switch(fourcc)
//if(fourcc==0x4d484452) // MHDR header
//if(fourcc==0x4d564552) // MVER
if(fourcc == 0x4d43494e) // MCIN
{
case 0x4d43494e: // MCIN
for (uint32 i = 0; i < 256; ++i)
{
//printf("Found chunks info\n");
// mapchunk offsets/sizes
for (int i=0; i<256; i++)
{
mf.read(&mcnk_offsets[i],4);
mf.read(&mcnk_sizes[i],4);
mf.seekRelative(8);
}
break;
mf.read(&mcnk_offsets[i], 4);
mf.read(&mcnk_sizes[i], 4);
mf.seekRelative(8);
}
case 0x4d4f4446: // MODF
}
//if(fourcc == 0x4d544558) // MTEX textures (strings)
//if(fourcc == 0x4d4d4458) // MMDX m2 models (strings)
//if(fourcc == 0x4d4d4944) // MMID offsets for strings in MMDX
//if(fourcc == 0x4d574d4f) // MWMO
//if(fourcc == 0x4d574944) // MWID offsets for strings in MWMO
//if(fourcc == 0x4d444446) // MDDF
//if(fourcc == 0x4d4f4446) // MODF
if(fourcc == 0x4d48324f) // MH2O new in WotLK
{
// çäåñü íàäî çàïîìíèòü áàçîâóþ ïîçèöèþ â ôàéëå òê âñå ñìåùåíèÿ áóäóò îò íåãî
uint32 base_pos = mf.getPos();
uint32 header_pos = 0;
MH2O_offsData *LiqOffsData = new MH2O_offsData;
MH2O_Data1 *LiqChunkData1 = new MH2O_Data1;
float *ChunkLiqHeight = new float[81];
for(chunk_num = 0; chunk_num < 256; ++chunk_num)
{
/*
if(size)
mf.read(LiqOffsData, 0x0C);
header_pos = mf.getPos();
if(LiqOffsData->offsData1 != 0) // åñëè äàííûå â Data1 î âîäå åñòü, òî èõ íàäî êîíâåðòèðîâàòü
{
//printf("\nwmo count %d\n",size/64);
wmo_count =size/64;
for (int i=0; i<wmo_count; i++)
// ïåðåõîäèì ïî ñìåùåíèþ èç 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)
{
int id;
mf.read(&id, 4);
WMO *wmo = (WMO*)wmomanager.items[wmomanager.get(wmos[id])];
WMOInstance inst(wmo, mf);
wmois.push_back(inst);
ChunkLiqHeight[j] = -999999; // no liquid/water
}
<<<<<<< HEAD:contrib/extractor/adt.cpp
}*/
break;
@@ -98,14 +125,38 @@ bool LoadADT(char* filename)
mf.read(buf, size);
char *p=buf;
while (p<buf+size)
=======
// òåïåðü âû÷èñëÿåì òå ÷òî ñ âîäîé è ïåðåçàïèñûâàåì èõ â êóñêå
for(int b = 0; b <= LiqChunkData1->height; ++b)
>>>>>>> upstream/master:contrib/extractor/adt.cpp
{
std::string path(p);
p+=strlen(p)+1;
fixname(path);
wmomanager.add(path);
wmos.push_back(path);
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;
}
<<<<<<< HEAD:contrib/extractor/adt.cpp
delete[] buf;
}*/
break;
@@ -126,77 +177,50 @@ bool LoadADT(char* filename)
// mf.seekRelative(-3);
printf("Unhandled map chunk: %u\n",fourcc);
break;
=======
k = k + 120;
}
>>>>>>> upstream/master:contrib/extractor/adt.cpp
}
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;t<wmo_count ;t++)
chunk_num = 0;
k = 0;
m = 0;
for (int j = 0; j < 16; ++j)
{
wmois[t].draw();
}*/
for (int i = 0; i < 16; ++i)
{
mf.seek((int)mcnk_offsets[j * 16 + i]);
LoadMapChunk(mf, &(mcells->ch[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,295 +231,267 @@ 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<zmin)zmin=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)
<<<<<<< HEAD:contrib/extractor/adt.cpp
_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;
>>>>>>> upstream/master:contrib/extractor/adt.cpp
}
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<iRes;x++)
for(unsigned int y=0;y<iRes;y++)
for(uint32 x = 0; x < iRes; ++x)
{
float z=(float)GetZ(
(((double)(y))*TILESIZE)/((double)(iRes-1)),
(((double)(x))*TILESIZE)/((double)(iRes-1)));
for(uint32 y = 0; y < iRes; ++y)
{
float z = (float)GetZ(
(((double)(y)) * TILESIZE) / ((double)(iRes - 1)),
(((double)(x)) * TILESIZE) / ((double)(iRes - 1)));
fwrite(&z,1,sizeof(z),output);
fwrite(&z, 1, sizeof(z), output);
}
}
fclose(output);
delete cell;
/*
for (std::vector<std::string>::iterator it = wmos.begin(); it != wmos.end(); ++it)
wmomanager.delbyname(*it);
wmos.clear();
wmois.clear();
for (std::vector<model>::iterator it = wmomodel.begin(); it != wmomodel.end(); ++it)
{
it->tr.clear();
}
//printf("\n %d \n",in);
wmomodel.clear();
//polygons.clear();*/
return true;
}
+112 -37
View File
@@ -9,46 +9,121 @@ 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
+26 -119
View File
@@ -1,11 +1,7 @@
//#include "common.h"
#include "model.h"
//#include "world.h"
#include <cassert>
#include <algorithm>
//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; i<header.nBoundingVertices; i++)
{
f.close();
return false;
}
#endif
trans = 1.0f;
origVertices = (ModelVertex*)(f.getBuffer() + header.ofsVertices);
vertices = new Vec3D[header.nVertices];
normals = new Vec3D[header.nVertices];
for (size_t i=0; i<header.nVertices; i++)
{
origVertices[i].pos = fixCoordSystem(origVertices[i].pos);
origVertices[i].normal = fixCoordSystem(origVertices[i].normal);
vertices[i] = origVertices[i].pos;
normals[i] = origVertices[i].normal.normalize();
}
ModelView *view = (ModelView*)(f.getBuffer() + header.ofsViews);
uint16 *indexLookup = (uint16*)(f.getBuffer() + view->ofsIndex);
uint16 *triangles = (uint16*)(f.getBuffer() + view->ofsTris);
nIndices = view->nTris;
indices = new uint16[nIndices];
for (size_t i = 0; i<nIndices; i++)
{
indices[i] = indexLookup[triangles[i]];
vertices[i] = fixCoordSystem(vertices[i]);
}
f.seek(0);
f.seekRelative(header.ofsBoundingTriangles);
indices = new uint16[header.nBoundingTriangles];
f.read(indices,header.nBoundingTriangles*2);
f.close();
} else {
}
else
{
//printf("not included %s\n", filename.c_str());
f.close();
return false;
}
return true;
}
bool Model::isAnimated(MPQFile &f)
{
// see if we have any animated bones
ModelBoneDef *bo = (ModelBoneDef*)(f.getBuffer() + header.ofsBones);
animGeometry = false;
animBones = false;
ind = false;
ModelVertex *verts = (ModelVertex*)(f.getBuffer() + header.ofsVertices);
for (size_t i=0; i<header.nVertices && !animGeometry; i++) {
for (size_t b=0; b<4; b++) {
if (verts[i].weights[b]>0) {
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<header.nBones; i++) {
ModelBoneDef &bb = bo[i];
if (bb.translation.type || bb.rotation.type || bb.scaling.type) {
animBones = true;
break;
}
}
}
animTextures = header.nTexAnims > 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; i<header.nColors; i++) {
if (cols[i].color.type!=0 || cols[i].opacity.type!=0) {
animMisc = true;
break;
}
}
}
// animated opacity
if (header.nTransparency && !animMisc) {
ModelTransDef *trs = (ModelTransDef*)(f.getBuffer() + header.ofsTransparency);
for (size_t i=0; i<header.nTransparency; i++) {
if (trs[i].trans.type!=0) {
animMisc = true;
break;
}
}
}
// guess not...
return animGeometry || animTextures || animMisc;
}
bool Model::ConvertToVMAPModel(char * outfilename)
{
@@ -151,7 +57,8 @@ bool Model::ConvertToVMAPModel(char * outfilename)
return false;
}
fwrite("VMAP002",8,1,output);
int nVertices = header.nVertices;
uint32 nVertices = 0;
nVertices = header.nBoundingVertices;
fwrite(&nVertices, sizeof(int), 1, output);
uint32 nofgroups = 1;
fwrite(&nofgroups,sizeof(uint32), 1, output);
@@ -162,15 +69,16 @@ bool Model::ConvertToVMAPModel(char * outfilename)
wsize = sizeof(branches) + sizeof(uint32) * branches;
fwrite(&wsize, sizeof(int), 1, output);
fwrite(&branches,sizeof(branches), 1, output);
uint32 nIdexes = (uint32) nIndices;
fwrite(&nIndices,sizeof(uint32), 1, output);
uint32 nIndexes = 0;
nIndexes = header.nBoundingTriangles;
fwrite(&nIndexes,sizeof(uint32), 1, output);
fwrite("INDX",4, 1, output);
wsize = sizeof(uint32) + sizeof(unsigned short) * nIdexes;
wsize = sizeof(uint32) + sizeof(unsigned short) * nIndexes;
fwrite(&wsize, sizeof(int), 1, output);
fwrite(&nIdexes, sizeof(uint32), 1, output);
if(nIdexes >0)
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 <nVertices; ++vpos)
for(uint32 vpos=0; vpos <nVertices; ++vpos)
{
float sy = vertices[vpos].y;
vertices[vpos].y = vertices[vpos].z;
@@ -189,7 +97,6 @@ bool Model::ConvertToVMAPModel(char * outfilename)
delete[] vertices;
delete[] indices;
delete[] normals;
fclose(output);
+5 -22
View File
@@ -4,7 +4,6 @@
#include "vec3d.h"
#include "mpq.h"
#include "modelheaders.h"
//#include "quaternion.h"
#include <vector>
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);
@@ -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)
@@ -421,6 +421,10 @@ bool fillArchiveNameVector(std::vector<std::string>& 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<std::string>& pArchiveNames) {
for (std::vector<std::string>::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());
+88 -13
View File
@@ -15,22 +15,13 @@
/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;
--
-- Table structure for table `saved_variables`
--
CREATE TABLE `saved_variables` (
`NextArenaPointDistributionTime` bigint(40) UNSIGNED NOT NULL DEFAULT '0'
) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=FIXED COMMENT='Variable Saves';
--
-- Table structure for table `character_db_version`
--
DROP TABLE IF EXISTS `character_db_version`;
CREATE TABLE `character_db_version` (
`required_2008_12_15_01_character_arenas` 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';
--
@@ -44,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`
--
@@ -228,6 +241,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`
--
@@ -410,9 +466,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',
@@ -1234,6 +1288,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`
--
@@ -1324,6 +1379,26 @@ 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 */;
@@ -137,6 +137,9 @@ EndScriptData */
#define FLAME_ENRAGE_DISTANCE 30
#define FLAME_CHARGE_DISTANCE 50
#define ITEM_ID_MAIN_HAND 32837
#define ITEM_ID_OFF_HAND 32838
/**** Creature Summon and Recognition IDs ****/
enum CreatureEntry
{
@@ -454,7 +457,7 @@ struct TRINITY_DLL_DECL boss_illidan_stormrageAI : public ScriptedAI
{
GameObject* Door = GameObject::GetGameObject((*m_creature), pInstance->GetData64(i));
if(Door)
Door->SetUInt32Value(GAMEOBJECT_STATE, 0); // Open Doors
Door->SetGoState(0); // Open Doors
}
}
@@ -487,10 +490,10 @@ struct TRINITY_DLL_DECL boss_illidan_stormrageAI : public ScriptedAI
{
if(spell->Id == SPELL_GLAIVE_RETURNS) // Re-equip our warblades!
{
if(!m_creature->GetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_DISPLAY))
m_creature->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_DISPLAY, 45479);
if(!m_creature->GetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID))
m_creature->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID, 45479);
else
m_creature->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_DISPLAY+1, 45481);
m_creature->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID+1, 45481);
m_creature->SetByteValue(UNIT_FIELD_BYTES_2, 0, SHEATH_STATE_MELEE );
}
}
@@ -567,8 +570,8 @@ struct TRINITY_DLL_DECL boss_illidan_stormrageAI : public ScriptedAI
Timer[EVENT_FLIGHT_SEQUENCE] = 700;
break;
case 4://throw another
m_creature->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_DISPLAY, 0);
m_creature->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_DISPLAY+1, 0);
m_creature->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID, 0);
m_creature->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID+1, 0);
{
uint8 i=0;
Creature* Glaive = m_creature->SummonCreature(BLADE_OF_AZZINOTH, GlaivePosition[i].x, GlaivePosition[i].y, GlaivePosition[i].z, 0, TEMPSUMMON_CORPSE_DESPAWN, 0);
@@ -653,14 +656,14 @@ struct TRINITY_DLL_DECL boss_illidan_stormrageAI : public ScriptedAI
if(DemonTransformation[TransformCount].equip)
{
m_creature->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_DISPLAY, 45479); // Requip warglaives if needed
m_creature->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_DISPLAY+1, 45481);
m_creature->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID, 45479); // Requip warglaives if needed
m_creature->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID+1, 45481);
m_creature->SetByteValue(UNIT_FIELD_BYTES_2, 0, SHEATH_STATE_MELEE );
}
else
{
m_creature->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_DISPLAY, 0); // Unequip warglaives if needed
m_creature->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_DISPLAY+1, 0);
m_creature->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID+0, 0); // Unequip warglaives if needed
m_creature->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID+1, 0);
}
switch(TransformCount)
@@ -1006,10 +1009,10 @@ struct TRINITY_DLL_DECL npc_akama_illidanAI : public ScriptedAI
DoorGUID[1] = pInstance->GetData64(DATA_GAMEOBJECT_ILLIDAN_DOOR_L);
if(GETGO(Gate, GateGUID))
Gate->SetUInt32Value(GAMEOBJECT_STATE, 1);
Gate->SetGoState(1);
for(uint8 i = 0; i < 2; i++)
if(GETGO(Door, DoorGUID[i]))
Door->SetUInt32Value(GAMEOBJECT_STATE, 1);
Door->SetGoState(1);
}
else
{
@@ -1079,7 +1082,7 @@ struct TRINITY_DLL_DECL npc_akama_illidanAI : public ScriptedAI
for(uint8 i = 0; i < 2; i++)
if(GETGO(Door, DoorGUID[i]))
Door->SetUInt32Value(GAMEOBJECT_STATE, 1);
Door->SetGoState(1);
if(GETCRE(Illidan, IllidanGUID))
{
@@ -1245,7 +1248,7 @@ struct TRINITY_DLL_DECL npc_akama_illidanAI : public ScriptedAI
Spirit[0]->InterruptNonMeleeSpells(true);
Spirit[1]->InterruptNonMeleeSpells(true);
if(GETGO(Gate, GateGUID))
Gate->SetUInt32Value(GAMEOBJECT_STATE, 0);
Gate->SetGoState(0);
Timer = 2000;
break;
case 4:
@@ -1276,7 +1279,7 @@ struct TRINITY_DLL_DECL npc_akama_illidanAI : public ScriptedAI
case 6:
for(uint8 i = 0; i < 2; i++)
if(GETGO(Door, DoorGUID[i]))
Door->SetUInt32Value(GAMEOBJECT_STATE, 0);
Door->SetGoState(0);
break;
case 8:
if(Phase == PHASE_WALK)
@@ -1386,9 +1389,9 @@ struct TRINITY_DLL_DECL boss_maievAI : public ScriptedAI
Timer[EVENT_MAIEV_STEALTH] = 0;
Timer[EVENT_MAIEV_TAUNT] = 22000 + rand()%21 * 1000;
Timer[EVENT_MAIEV_SHADOW_STRIKE] = 30000;
m_creature->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_DISPLAY, 44850);
m_creature->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_DISPLAY + 1, 0);
m_creature->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_DISPLAY + 2, 45738);
m_creature->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID, 44850);
m_creature->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID + 1, 0);
m_creature->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID + 2, 45738);
}
void Aggro(Unit *who) {}
@@ -1674,7 +1677,7 @@ bool GOHello_cage_trap(Player* plr, GameObject* go)
cell_lock->Visit(cell_lock, cSearcher, *(plr->GetMap()));
((cage_trap_triggerAI*)trigger->AI())->Active = true;
go->SetUInt32Value(GAMEOBJECT_STATE, 0);
go->SetGoState(0);
return true;
}
@@ -1859,8 +1862,8 @@ void boss_illidan_stormrageAI::Reset()
m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_ATTACKABLE_2);
m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
m_creature->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_DISPLAY, 0);
m_creature->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_DISPLAY+1, 0);
m_creature->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID, 0);
m_creature->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID+1, 0);
m_creature->RemoveUnitMovementFlag(MOVEMENTFLAG_LEVITATING + MOVEMENTFLAG_ONTRANSPORT);
m_creature->CastSpell(m_creature, SPELL_DUAL_WIELD, true);
@@ -1907,8 +1910,8 @@ void boss_illidan_stormrageAI::HandleTalkSequence()
m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
break;
case 8:
m_creature->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_DISPLAY, 45479); // Equip our warglaives!
m_creature->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_DISPLAY+1, 45481);
m_creature->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID, 45479); // Equip our warglaives!
m_creature->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID+1, 45481);
m_creature->SetByteValue(UNIT_FIELD_BYTES_2, 0, SHEATH_STATE_MELEE );
m_creature->RemoveUnitMovementFlag(MOVEMENTFLAG_WALK_MODE);
break;
@@ -118,13 +118,13 @@ struct TRINITY_DLL_DECL instance_black_temple : public ScriptedInstance
void OpenDoor(uint64 DoorGUID, bool open)
{
if(GameObject *Door = instance->GetGameObjectInMap(DoorGUID))
Door->SetUInt32Value(GAMEOBJECT_STATE, open ? 0 : 1);
Door->SetGoState(open ? 0 : 1);
}
void CloseDoor(uint64 DoorGUID, bool close)
{
if(GameObject *Door = instance->GetGameObjectInMap(DoorGUID))
Door->SetUInt32Value(GAMEOBJECT_STATE, close ? 1 : 0);
Door->SetGoState(close ? 1 : 0);
}
void OnCreatureCreate(Creature *creature, uint32 creature_entry)
@@ -89,13 +89,13 @@ struct TRINITY_DLL_DECL instance_blackrock_depths : public ScriptedInstance
void OpenGO(uint64 DoorGUID, bool open)
{
if(GameObject *Door = instance->GetGameObjectInMap(DoorGUID))
Door->SetUInt32Value(GAMEOBJECT_STATE, open ? 0 : 1);
Door->SetGoState(open ? 0 : 1);
}
void CloseGO(uint64 DoorGUID, bool close)
{
if(GameObject *Door = instance->GetGameObjectInMap(DoorGUID))
Door->SetUInt32Value(GAMEOBJECT_STATE, close ? 1 : 0);
Door->SetGoState(close ? 1 : 0);
}
uint32 GetData(uint32 type)
@@ -146,13 +146,13 @@ struct TRINITY_DLL_DECL instance_blackrock_depths : public ScriptedInstance
{
switch(go->GetEntry())
{
case 170561: SupplyRoomGate = go->GetGUID(); state = go->GetUInt32Value(GAMEOBJECT_STATE); break;
case 170562: GateDughal = go->GetGUID(); state = go->GetUInt32Value(GAMEOBJECT_STATE); break;
case 170566: GateTobias = go->GetGUID(); state = go->GetUInt32Value(GAMEOBJECT_STATE); break;
case 170567: GateCrest = go->GetGUID(); state = go->GetUInt32Value(GAMEOBJECT_STATE); break;
case 170568: GateJaz = go->GetGUID(); state = go->GetUInt32Value(GAMEOBJECT_STATE); break;
case 170569: GateShill = go->GetGUID(); state = go->GetUInt32Value(GAMEOBJECT_STATE); break;
case 166872: SupplyCrate = go->GetGUID(); state = go->GetUInt32Value(GAMEOBJECT_STATE); break;
case 170561: SupplyRoomGate = go->GetGUID(); state = go->GetGoState(); break;
case 170562: GateDughal = go->GetGUID(); state = go->GetGoState(); break;
case 170566: GateTobias = go->GetGUID(); state = go->GetGoState(); break;
case 170567: GateCrest = go->GetGUID(); state = go->GetGoState(); break;
case 170568: GateJaz = go->GetGUID(); state = go->GetGoState(); break;
case 170569: GateShill = go->GetGUID(); state = go->GetGoState(); break;
case 166872: SupplyCrate = go->GetGUID(); state = go->GetGoState(); break;
}
}
@@ -235,12 +235,12 @@ struct TRINITY_DLL_DECL npc_thrall_old_hillsbradAI : public npc_escortAI
case 9:
DoScriptText(SAY_TH_ARMORY, m_creature);
m_creature->AddUnitMovementFlag(MOVEMENTFLAG_WALK_MODE);
m_creature->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_DISPLAY, THRALL_WEAPON_MODEL);
m_creature->SetUInt32Value(UNIT_VIRTUAL_ITEM_INFO, THRALL_WEAPON_INFO);
m_creature->SetUInt32Value(UNIT_VIRTUAL_ITEM_INFO+1, 781);
m_creature->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_DISPLAY+1, THRALL_SHIELD_MODEL);
m_creature->SetUInt32Value(UNIT_VIRTUAL_ITEM_INFO+2, THRALL_SHIELD_INFO);
m_creature->SetUInt32Value(UNIT_VIRTUAL_ITEM_INFO+3, 1038);
m_creature->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID, THRALL_WEAPON_MODEL);
//m_creature->SetUInt32Value(UNIT_VIRTUAL_ITEM_INFO, THRALL_WEAPON_INFO);
//m_creature->SetUInt32Value(UNIT_VIRTUAL_ITEM_INFO+1, 781);
m_creature->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID+1, THRALL_SHIELD_MODEL);
//m_creature->SetUInt32Value(UNIT_VIRTUAL_ITEM_INFO+2, THRALL_SHIELD_INFO);
//m_creature->SetUInt32Value(UNIT_VIRTUAL_ITEM_INFO+3, 1038);
break;
case 10:
m_creature->SetUInt32Value(UNIT_FIELD_DISPLAYID, THRALL_MODEL_EQUIPPED);
@@ -399,12 +399,8 @@ struct TRINITY_DLL_DECL npc_thrall_old_hillsbradAI : public npc_escortAI
{
DoUnmount();
HadMount = false;
m_creature->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_DISPLAY, 0);
m_creature->SetUInt32Value(UNIT_VIRTUAL_ITEM_INFO, 0);
m_creature->SetUInt32Value(UNIT_VIRTUAL_ITEM_INFO+1, 0);
m_creature->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_DISPLAY+1, 0);
m_creature->SetUInt32Value(UNIT_VIRTUAL_ITEM_INFO+2, 0);
m_creature->SetUInt32Value(UNIT_VIRTUAL_ITEM_INFO+3, 0);
m_creature->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID, 0);
m_creature->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID+1, 0);
m_creature->SetUInt32Value(UNIT_FIELD_DISPLAYID, THRALL_MODEL_UNEQUIPPED);
}
if( IsBeingEscorted )
@@ -198,8 +198,8 @@ struct TRINITY_DLL_DECL boss_leotheras_the_blindAI : public ScriptedAI
m_creature->ApplySpellImmune(0, IMMUNITY_STATE, SPELL_AURA_MOD_TAUNT, true);
m_creature->ApplySpellImmune(0, IMMUNITY_EFFECT,SPELL_EFFECT_ATTACK_ME, true);
m_creature->SetUInt32Value(UNIT_FIELD_DISPLAYID, MODEL_NIGHTELF);
m_creature->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_DISPLAY , 0);
m_creature->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_DISPLAY+1, 0);
m_creature->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID , 0);
m_creature->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID+1, 0);
m_creature->CastSpell(m_creature, SPELL_DUAL_WIELD, true);
m_creature->SetCorpseDelay(1000*60*60);
if(pInstance)
@@ -305,8 +305,8 @@ struct TRINITY_DLL_DECL boss_leotheras_the_blindAI : public ScriptedAI
m_creature->SetUInt32Value(UNIT_FIELD_DISPLAYID, MODEL_DEMON);
// and removing weapons
m_creature->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_DISPLAY , 0);
m_creature->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_DISPLAY+1, 0);
m_creature->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID , 0);
m_creature->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID+1, 0);
}
}
@@ -469,8 +469,8 @@ struct TRINITY_DLL_DECL boss_leotheras_the_blindAI : public ScriptedAI
m_creature->RemoveAurasDueToSpell(SPELL_WHIRLWIND,0);
m_creature->SetUInt32Value(UNIT_FIELD_DISPLAYID, MODEL_DEMON);
DoScriptText(SAY_SWITCH_TO_DEMON, m_creature);
m_creature->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_DISPLAY , 0);
m_creature->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_DISPLAY+1, 0);
m_creature->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID , 0);
m_creature->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID+1, 0);
DemonForm = true;
NeedThreatReset = true;
SwitchToDemon_Timer = 45000;
@@ -137,7 +137,7 @@ struct TRINITY_DLL_DECL instance_serpentshrine_cavern : public ScriptedInstance
void OpenDoor(uint64 DoorGUID, bool open)
{
if(GameObject *Door = instance->GetGameObjectInMap(DoorGUID))
Door->SetUInt32Value(GAMEOBJECT_STATE, open ? 0 : 1);
Door->SetGoState(open ? 0 : 1);
}
void OnCreatureCreate(Creature *creature, uint32 creature_entry)
@@ -120,13 +120,13 @@ struct TRINITY_DLL_DECL instance_deadmines : public ScriptedInstance
void ShootCannon()
{
DefiasCannon->SetUInt32Value(GAMEOBJECT_STATE, 0);
DefiasCannon->SetGoState(0);
DoPlaySound(DefiasCannon, SOUND_CANNONFIRE);
}
void BlastOutDoor()
{
IronCladDoor->SetUInt32Value(GAMEOBJECT_STATE, 2);
IronCladDoor->SetGoState(2);
DoPlaySound(IronCladDoor, SOUND_DESTROYDOOR);
}
@@ -238,8 +238,8 @@ struct TRINITY_DLL_DECL boss_high_king_maulgarAI : public ScriptedAI
DoScriptText(SAY_ENRAGE, m_creature);
m_creature->CastSpell(m_creature, SPELL_DUAL_WIELD, true);
m_creature->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_DISPLAY, 0);
m_creature->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_DISPLAY+1, 0);
m_creature->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID, 0);
m_creature->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID+1, 0);
}
if(Phase2)
@@ -289,11 +289,11 @@ struct TRINITY_DLL_DECL boss_malchezaarAI : public ScriptedAI
void ClearWeapons()
{
m_creature->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_DISPLAY, 0);
m_creature->SetUInt32Value(UNIT_VIRTUAL_ITEM_INFO, 0);
m_creature->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID, 0);
//m_creature->SetUInt32Value(UNIT_VIRTUAL_ITEM_INFO, 0);
m_creature->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_DISPLAY+1, 0);
m_creature->SetUInt32Value(UNIT_VIRTUAL_ITEM_INFO+2, 0);
m_creature->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID+1, 0);
//m_creature->SetUInt32Value(UNIT_VIRTUAL_ITEM_INFO+2, 0);
//damage
const CreatureInfo *cinfo = m_creature->GetCreatureInfo();
@@ -433,11 +433,11 @@ struct TRINITY_DLL_DECL boss_malchezaarAI : public ScriptedAI
m_creature->CastSpell(m_creature, SPELL_THRASH_AURA, true);
//models
m_creature->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_DISPLAY, AXE_EQUIP_MODEL);
m_creature->SetUInt32Value(UNIT_VIRTUAL_ITEM_INFO, AXE_EQUIP_INFO);
m_creature->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID, AXE_EQUIP_MODEL);
//m_creature->SetUInt32Value(UNIT_VIRTUAL_ITEM_INFO, AXE_EQUIP_INFO);
m_creature->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_DISPLAY+1, AXE_EQUIP_MODEL);
m_creature->SetUInt32Value(UNIT_VIRTUAL_ITEM_INFO+2, AXE_EQUIP_INFO);
m_creature->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID+1, AXE_EQUIP_MODEL);
//m_creature->SetUInt32Value(UNIT_VIRTUAL_ITEM_INFO+2, AXE_EQUIP_INFO);
//damage
const CreatureInfo *cinfo = m_creature->GetCreatureInfo();
@@ -475,8 +475,8 @@ struct TRINITY_DLL_DECL boss_malchezaarAI : public ScriptedAI
Creature *axe = m_creature->SummonCreature(MALCHEZARS_AXE, m_creature->GetPositionX(), m_creature->GetPositionY(), m_creature->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 1000);
if(axe)
{
axe->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_DISPLAY, AXE_EQUIP_MODEL);
axe->SetUInt32Value(UNIT_VIRTUAL_ITEM_INFO, AXE_EQUIP_INFO);
axe->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID, AXE_EQUIP_MODEL);
//axe->SetUInt32Value(UNIT_VIRTUAL_ITEM_INFO, AXE_EQUIP_INFO);
axe->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
axe->setFaction(m_creature->getFaction());
@@ -736,7 +736,7 @@ struct TRINITY_DLL_DECL mob_pulsing_pumpkinAI : public ScriptedAI
sprouted = false;
DoCast(m_creature,SPELL_PUMPKIN_AURA,true);
DoCast(m_creature,SPELL_SPROUTING);
m_creature->SetFlag(UNIT_FIELD_FLAGS,UNIT_FLAG_DISABLE_ROTATE);
m_creature->SetFlag(UNIT_FIELD_FLAGS,UNIT_FLAG_STUNNED);
}
void Aggro(Unit *who){}
@@ -747,7 +747,7 @@ struct TRINITY_DLL_DECL mob_pulsing_pumpkinAI : public ScriptedAI
{
sprouted = true;
m_creature->RemoveAllAuras();
m_creature->RemoveFlag(UNIT_FIELD_FLAGS,UNIT_FLAG_DISABLE_ROTATE);
m_creature->RemoveFlag(UNIT_FIELD_FLAGS,UNIT_FLAG_STUNNED);
DoCast(m_creature,SPELL_SPROUT_BODY,true);
m_creature->UpdateEntry(PUMPKIN_FIEND);
DoStartMovement(m_creature->getVictim());
@@ -92,7 +92,7 @@ struct TRINITY_DLL_DECL instance_scarlet_monastery : public ScriptedInstance
{
GameObject *Shrine = instance->GetGameObjectInMap(PumpkinShrineGUID);
if(Shrine)
Shrine->SetUInt32Value(GAMEOBJECT_STATE,1);
Shrine->SetGoState(1);
}break;
case DATA_HORSEMAN_EVENT:
if (data == DONE)
@@ -106,7 +106,7 @@ struct TRINITY_DLL_DECL instance_scarlet_monastery : public ScriptedInstance
HorsemanAdds.clear();
GameObject *Shrine = instance->GetGameObjectInMap(PumpkinShrineGUID);
if(Shrine)
Shrine->SetUInt32Value(GAMEOBJECT_STATE,1);
Shrine->SetGoState(1);
}
break;
}
@@ -59,7 +59,7 @@ struct TRINITY_DLL_DECL instance_shadowfang_keep : public ScriptedInstance
void OpenDoor(uint64 DoorGUID, bool open)
{
if(GameObject *Door = instance->GetGameObjectInMap(DoorGUID))
Door->SetUInt32Value(GAMEOBJECT_STATE, open ? 0 : 1);
Door->SetGoState(open ? 0 : 1);
}
void SetData(uint32 type, uint32 data)
@@ -70,7 +70,7 @@ struct TRINITY_DLL_DECL instance_uldaman : public ScriptedInstance
break;
case ANCIENT_VAULT_DOOR:
go->SetUInt32Value(GAMEOBJECT_STATE,1);
go->SetGoState(1);
go->SetUInt32Value(GAMEOBJECT_FLAGS, 33);
ancientVaultDoor = go->GetGUID();
break;
@@ -93,7 +93,7 @@ struct TRINITY_DLL_DECL instance_uldaman : public ScriptedInstance
return;
go->SetUInt32Value(GAMEOBJECT_FLAGS, 33);
go->SetUInt32Value(GAMEOBJECT_STATE, 0);
go->SetGoState(0);
}
void ActivateStoneKeepers()
@@ -237,8 +237,7 @@ struct TRINITY_DLL_DECL boss_hex_lord_malacrassAI : public ScriptedAI
SpawnAdds();
m_creature->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_DISPLAY, 46916);
m_creature->SetUInt32Value(UNIT_VIRTUAL_ITEM_INFO, 50268674);
m_creature->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID, 46916);
m_creature->SetByteValue(UNIT_FIELD_BYTES_2, 0, SHEATH_STATE_MELEE );
}
@@ -149,7 +149,7 @@ struct TRINITY_DLL_DECL boss_nalorakkAI : public ScriptedAI
TankGUID = 0;
inBearForm = false;
m_creature->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_DISPLAY + 1, 5122);
m_creature->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID + 1, 5122);
}
void SendAttacker(Unit* target)
@@ -388,7 +388,7 @@ struct TRINITY_DLL_DECL boss_nalorakkAI : public ScriptedAI
{
if(inBearForm)
{
m_creature->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_DISPLAY + 1, 5122);
m_creature->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID + 1, 5122);
DoYell(YELL_SHIFTEDTOTROLL, LANG_UNIVERSAL, NULL);
DoPlaySoundToSet(m_creature, SOUND_YELL_TOTROLL);
m_creature->RemoveAurasDueToSpell(SPELL_BEARFORM);
@@ -400,7 +400,7 @@ struct TRINITY_DLL_DECL boss_nalorakkAI : public ScriptedAI
}
else
{
m_creature->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_DISPLAY + 1, 0);
m_creature->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID + 1, 0);
DoYell(YELL_SHIFTEDTOBEAR, LANG_UNIVERSAL, NULL);
DoPlaySoundToSet(m_creature, SOUND_YELL_TOBEAR);
DoCast(m_creature, SPELL_BEARFORM, true);
@@ -207,9 +207,9 @@ struct TRINITY_DLL_DECL boss_zuljinAI : public ScriptedAI
Summons.DespawnAll();
m_creature->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_DISPLAY, 47174);
m_creature->SetUInt32Value(UNIT_VIRTUAL_ITEM_INFO, 218172674);
m_creature->SetByteValue(UNIT_FIELD_BYTES_2, 0, SHEATH_STATE_MELEE);
m_creature->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID, 47174);
//m_creature->SetUInt32Value(UNIT_VIRTUAL_ITEM_INFO, 218172674);
//m_creature->SetByteValue(UNIT_FIELD_BYTES_2, 0, SHEATH_STATE_MELEE);
}
void Aggro(Unit *who)
@@ -341,7 +341,7 @@ struct TRINITY_DLL_DECL boss_zuljinAI : public ScriptedAI
m_creature->Relocate(CENTER_X, CENTER_Y, CENTER_Z,0);
m_creature->SendMonsterMove(CENTER_X, CENTER_Y, CENTER_Z,0,0,100);
DoResetThreat();
m_creature->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_DISPLAY, 0);
m_creature->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID, 0);
m_creature->RemoveAurasDueToSpell(Transform[Phase].unaura);
DoCast(m_creature, Transform[Phase].spell);
DoYell(Transform[Phase].text, LANG_UNIVERSAL, NULL);
@@ -140,7 +140,7 @@ struct TRINITY_DLL_DECL instance_zulaman : public ScriptedInstance
void OpenDoor(uint64 DoorGUID, bool open)
{
if(GameObject *Door = instance->GetGameObjectInMap(DoorGUID))
Door->SetUInt32Value(GAMEOBJECT_STATE, open ? 0 : 1);
Door->SetGoState(open ? 0 : 1);
}
void SummonHostage(uint8 num)
@@ -65,9 +65,9 @@ struct TRINITY_DLL_DECL boss_renatakiAI : public ScriptedAI
if (Invisible_Timer < diff)
{
m_creature->InterruptSpell(CURRENT_GENERIC_SPELL);
m_creature->SetUInt32Value( UNIT_VIRTUAL_ITEM_SLOT_DISPLAY, 0);
m_creature->SetUInt32Value( UNIT_VIRTUAL_ITEM_INFO , 218171138);
m_creature->SetUInt32Value( UNIT_VIRTUAL_ITEM_INFO + 1, 3);
m_creature->SetUInt32Value( UNIT_VIRTUAL_ITEM_SLOT_ID, 0);
//m_creature->SetUInt32Value( UNIT_VIRTUAL_ITEM_INFO , 218171138);
//m_creature->SetUInt32Value( UNIT_VIRTUAL_ITEM_INFO + 1, 3);
m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
m_creature->SetUInt32Value(UNIT_FIELD_DISPLAYID,11686);
Invisible = true;
@@ -100,9 +100,9 @@ struct TRINITY_DLL_DECL boss_renatakiAI : public ScriptedAI
m_creature->InterruptSpell(CURRENT_GENERIC_SPELL);
m_creature->SetUInt32Value(UNIT_FIELD_DISPLAYID,15268);
m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
m_creature->SetUInt32Value( UNIT_VIRTUAL_ITEM_SLOT_DISPLAY, 31818);
m_creature->SetUInt32Value( UNIT_VIRTUAL_ITEM_INFO , 218171138);
m_creature->SetUInt32Value( UNIT_VIRTUAL_ITEM_INFO + 1, 3);
m_creature->SetUInt32Value( UNIT_VIRTUAL_ITEM_SLOT_ID, 31818);
//m_creature->SetUInt32Value( UNIT_VIRTUAL_ITEM_INFO , 218171138);
//m_creature->SetUInt32Value( UNIT_VIRTUAL_ITEM_INFO + 1, 3);
m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
Invisible = false;
+910
View File
@@ -0,0 +1,910 @@
/*
* Copyright (C) 2005-2008 MaNGOS <http://getmangos.com/>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, 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 << "("<<GetPlayer()->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; i<ACHIEVEMENT_CRITERIA_TYPE_TOTAL; i++)
UpdateAchievementCriteria(AchievementCriteriaTypes(i));
}
/**
* this function will be called whenever the user might have done a criteria relevant action
*/
void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, uint32 miscvalue1, uint32 miscvalue2, Unit *unit, uint32 time)
{
sLog.outString("AchievementMgr::UpdateAchievementCriteria(%u, %u, %u, %u)", type, miscvalue1, miscvalue2, time);
AchievementCriteriaEntryList const& achievementCriteriaList = objmgr.GetAchievementCriteriaByType(type);
for(AchievementCriteriaEntryList::const_iterator i = achievementCriteriaList.begin(); i!=achievementCriteriaList.end(); ++i)
{
AchievementCriteriaEntry const *achievementCriteria = (*i);
// don't update already completed criteria
if(IsCompletedCriteria(achievementCriteria))
continue;
if(achievementCriteria->groupFlag & 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; i<CRITERIA_CAST_SPELL_REQ_COUNT; i++)
{
if (criteriaCastSpellRequirements[i].achievementCriteriaId == achievementCriteria->ID)
{
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; entryId<sAchievementCriteriaStore.GetNumRows(); entryId++)
{
AchievementCriteriaEntry const* criteria = sAchievementCriteriaStore.LookupEntry(entryId);
if(!criteria || criteria->referredAchievement!= 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; i<ACHIEVEMENT_REWARD_COUNT; i++)
{
if (achievementRewards[i].achievementId == achievement->ID)
{
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);
}
+101
View File
@@ -0,0 +1,101 @@
/*
* Copyright (C) 2005-2008 MaNGOS <http://getmangos.com/>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, 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<uint32, CriteriaProgress> CriteriaProgressMap;
typedef UNORDERED_MAP<uint32, CompletedAchievementData> 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
+20
View File
@@ -752,3 +752,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);
}
+1 -1
View File
@@ -34,7 +34,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()
+5 -4
View File
@@ -576,6 +576,7 @@ void BattleGround::EndBattleGround(uint32 winner)
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)
@@ -1405,10 +1406,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
+4 -3
View File
@@ -132,8 +132,6 @@ struct BattleGroundObjectInfo
uint32 spellid;
};
#define MAX_QUEUED_PLAYERS_MAP 7
enum BattleGroundTypeId
{
BATTLEGROUND_AV = 1,
@@ -143,7 +141,10 @@ 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
+4 -1
View File
@@ -1267,13 +1267,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:
+2 -2
View File
@@ -32,9 +32,9 @@ typedef std::map<uint32, BattleGround*> BattleGroundSet;
//typedef std::map<uint32, BattleGroundQueue*> BattleGroundQueueSet;
typedef std::deque<BattleGround*> 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
#define MAX_BATTLEGROUND_QUEUE_TYPES 8
+17
View File
@@ -0,0 +1,17 @@
/*
* Copyright (C) 2005-2008 MaNGOS <http://getmangos.com/>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
+26
View File
@@ -0,0 +1,26 @@
/*
* Copyright (C) 2005-2008 MaNGOS <http://getmangos.com/>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, 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
+118
View File
@@ -0,0 +1,118 @@
/*
* Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, 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);
}
+295 -54
View File
@@ -82,7 +82,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_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;
}
@@ -232,17 +234,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;
}
@@ -309,29 +310,77 @@ 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;
}
// speedup check for heroic class disabled case
uint32 req_level_for_heroic = sWorld.getConfig(CONFIG_MIN_LEVEL_FOR_HEROIC_CHARACTER_CREATING);
if(GetSecurity()==SEC_PLAYER && class_ == CLASS_DEATH_KNIGHT && req_level_for_heroic > sWorld.getConfig(CONFIG_MAX_PLAYER_LEVEL))
{
data << (uint8)CHAR_CREATE_LEVEL_REQUIREMENT;
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 0 then allowed creating without any characters
bool have_req_level_for_heroic = (req_level_for_heroic==0);
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 guid,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[1].GetUInt32();
if(GetSecurity()==SEC_PLAYER && class_ == CLASS_DEATH_KNIGHT)
{
uint8 acc_class = field[2].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;
}
}
if(!have_req_level_for_heroic)
{
uint32 acc_guid = field[0].GetUInt32();
uint32 acc_level = Player::GetUInt32ValueFromDB(UNIT_FIELD_LEVEL,acc_guid);
if(acc_level >= req_level_for_heroic)
have_req_level_for_heroic = true;
}
}
// 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 );
@@ -340,20 +389,55 @@ 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[1].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[2].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;
}
}
if(!have_req_level_for_heroic)
{
uint32 acc_guid = field[0].GetUInt32();
uint32 acc_level = Player::GetUInt32ValueFromDB(UNIT_FIELD_LEVEL,acc_guid);
if(acc_level >= req_level_for_heroic)
have_req_level_for_heroic = true;
}
}
have_same_race = race_ == race;
}
delete result2;
}
}
if(GetSecurity()==SEC_PLAYER && class_ == CLASS_DEATH_KNIGHT && !have_req_level_for_heroic)
{
data << (uint8)CHAR_CREATE_LEVEL_REQUIREMENT;
SendPacket( &data );
return;
}
// extract other data required for player creating
uint8 gender, skin, face, hairStyle, hairColor, facialHair, outfitId;
recv_data >> gender >> skin >> face;
@@ -510,9 +594,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
@@ -609,12 +695,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 );
}
}
}
@@ -658,22 +752,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);
}
@@ -903,11 +981,11 @@ void WorldSession::HandleToggleCloakOpcode( WorldPacket & /*recv_data*/ )
void WorldSession::HandleChangePlayerNameOpcode(WorldPacket& recv_data)
{
CHECK_PACKET_SIZE(recv_data, 8+1);
uint64 guid;
std::string newname;
CHECK_PACKET_SIZE(recv_data, 8+1);
recv_data >> guid;
recv_data >> newname;
@@ -915,15 +993,15 @@ void WorldSession::HandleChangePlayerNameOpcode(WorldPacket& recv_data)
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;
}
@@ -932,7 +1010,7 @@ 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;
}
@@ -961,7 +1039,7 @@ void WorldSession::HandleChangePlayerNameOpcodeCallBack(QueryResult *result, uin
if (!result)
{
WorldPacket data(SMSG_CHAR_RENAME, 1);
data << (uint8)CHAR_CREATE_ERROR;
data << uint8(CHAR_CREATE_ERROR);
session->SendPacket( &data );
return;
}
@@ -975,11 +1053,11 @@ void WorldSession::HandleChangePlayerNameOpcodeCallBack(QueryResult *result, uin
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);
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());
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;
session->SendPacket(&data);
}
@@ -1073,3 +1151,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);
}
+3
View File
@@ -190,6 +190,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 },
@@ -263,6 +264,7 @@ ChatCommand * ChatHandler::getCommandTable()
{ "item_enchantment_template", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadItemEnchantementsCommand, "", NULL },
{ "item_loot_template", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadLootTemplatesItemCommand, "", NULL },
{ "trinity_string", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadTrinityStringCommand, "", 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 },
@@ -589,6 +591,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 },
+3
View File
@@ -233,6 +233,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);
@@ -434,6 +435,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);
@@ -467,6 +469,7 @@ class ChatHandler
bool HandleUnPossessCommand(const char* args);
bool HandleBindSightCommand(const char* args);
bool HandleUnbindSightCommand(const char* args);
bool HandleSpawnVehicle(const char * args);
Player* getSelectedPlayer();
Creature* getSelectedCreature();
+1 -1
View File
@@ -36,7 +36,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;
+10 -15
View File
@@ -145,11 +145,12 @@ Unit(), i_AI(NULL), i_AI_possessed(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_reactState(REACT_AGGRESSIVE),
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_reactState(REACT_AGGRESSIVE),
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_formationID(0)
{
m_regenTimer = 200;
m_valuesCount = UNIT_END;
for(int i =0; i<4; ++i)
@@ -315,7 +316,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)
@@ -765,8 +765,11 @@ bool Creature::isCanInteractWithBattleMaster(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;
}
@@ -1459,11 +1462,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;
@@ -1475,11 +1474,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
+3 -4
View File
@@ -244,9 +244,7 @@ struct NpcOptionLocale
struct EquipmentInfo
{
uint32 entry;
uint32 equipmodel[3];
uint32 equipinfo[3];
uint32 equipslot[3];
uint32 equipentry[3];
};
// from `creature` table
@@ -423,6 +421,7 @@ class TRINITY_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; }
@@ -657,11 +656,11 @@ class TRINITY_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
ReactStates m_reactState; // for AI, not charmInfo
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
+1 -1
View File
@@ -38,7 +38,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;
}
+60 -36
View File
@@ -46,7 +46,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;
@@ -127,17 +127,33 @@ 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);
SetUInt32Value(GAMEOBJECT_FACTION, goinfo->faction);
SetUInt32Value(GAMEOBJECT_FLAGS, goinfo->flags);
SetUInt32Value(OBJECT_FIELD_ENTRY, goinfo->id);
SetEntry(goinfo->id);
SetUInt32Value(GAMEOBJECT_DISPLAYID, goinfo->displayId);
@@ -146,8 +162,6 @@ bool GameObject::Create(uint32 guidlow, uint32 name_id, Map *map, float x, float
SetGoAnimProgress(animprogress);
SetUInt32Value (GAMEOBJECT_ARTKIT, ArtKit);
// Spell charges for GAMEOBJECT_TYPE_SPELLCASTER (22)
if (goinfo->type == GAMEOBJECT_TYPE_SPELLCASTER)
m_charges = goinfo->spellcaster.charges;
@@ -264,7 +278,7 @@ void GameObject::Update(uint32 /*p_time*/)
return;
}
// respawn timer
MapManager::Instance().GetMap(GetMapId(), this)->Add(this);
GetMap()->Add(this);
break;
}
}
@@ -414,7 +428,7 @@ void GameObject::Update(uint32 /*p_time*/)
//burning flags in some battlegrounds, if you find better condition, just add it
if (GetGoAnimProgress() > 0)
{
SendObjectDeSpawnAnim(this->GetGUID());
SendObjectDeSpawnAnim(GetGUID());
//reset flags
SetUInt32Value(GAMEOBJECT_FLAGS, GetGOInfo()->flags);
}
@@ -451,7 +465,7 @@ void GameObject::Refresh()
return;
if(isSpawned())
MapManager::Instance().GetMap(GetMapId(), this)->Add(this);
GetMap()->Add(this);
}
void GameObject::AddUniqueUse(Player* player)
@@ -504,7 +518,7 @@ void GameObject::SaveToDB(uint32 mapid, uint8 spawnMask)
if (!goI)
return;
if (!m_DBTableGuid)
m_DBTableGuid = GetGUIDLow();
// update in loaded data (changing data only in this place)
@@ -517,34 +531,33 @@ 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();
data.spawnMask = spawnMask;
data.ArtKit = GetUInt32Value (GAMEOBJECT_ARTKIT);
// updated in DB
std::ostringstream ss;
ss << "INSERT INTO gameobject VALUES ( "
<< m_DBTableGuid << ", "
<< GetUInt32Value (OBJECT_FIELD_ENTRY) << ", "
<< GetEntry() << ", "
<< mapid << ", "
<< (uint32)spawnMask << ", "
<< GetFloatValue(GAMEOBJECT_POS_X) << ", "
<< 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 << ", "
<< GetGoAnimProgress() << ", "
<< GetGoState() << ")";
<< (uint32)GetGoAnimProgress() << ", "
<< (uint32)GetGoState() << ")";
WorldDatabase.BeginTransaction();
WorldDatabase.PExecuteLog("DELETE FROM gameobject WHERE guid = '%u'", m_DBTableGuid);
@@ -563,7 +576,7 @@ bool GameObject::LoadFromDB(uint32 guid, Map *map)
}
uint32 entry = data->id;
uint32 map_id = data->mapid;
//uint32 map_id = data->mapid; // already used before call
float x = data->posX;
float y = data->posY;
float z = data->posZ;
@@ -576,12 +589,11 @@ bool GameObject::LoadFromDB(uint32 guid, Map *map)
uint32 animprogress = data->animprogress;
uint32 go_state = data->go_state;
uint32 ArtKit = data->ArtKit;
m_DBTableGuid = guid;
if (map->GetInstanceId() != 0) guid = objmgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT);
if (!Create(guid,entry, map, x, y, z, ang, rotation0, rotation1, rotation2, rotation3, animprogress, go_state, ArtKit) )
if (!Create(guid,entry, map, x, y, z, ang, rotation0, rotation1, rotation2, rotation3, animprogress, go_state) )
return false;
switch(GetGOInfo()->type)
@@ -846,14 +858,6 @@ void GameObject::UseDoorOrButton(uint32 time_to_restore)
}
void GameObject::SetGoArtKit(uint32 kit)
{
SetUInt32Value(GAMEOBJECT_ARTKIT, kit);
GameObjectData *data = const_cast<GameObjectData*>(objmgr.GetGOData(m_DBTableGuid));
if(data)
data->ArtKit = kit;
}
void GameObject::SwitchDoorOrButton(bool activate)
{
if(activate)
@@ -1209,7 +1213,7 @@ void GameObject::Use(Unit* user)
Player* player = (Player*)user;
if( player->isAllowUseBattleGroundObject() )
if( player->isAllowUseBattleGroundObject() )
{
// in battleground check
BattleGround *bg = player->GetBattleGround();
@@ -1247,6 +1251,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;
+19 -12
View File
@@ -336,12 +336,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
{
@@ -350,6 +350,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
@@ -504,14 +511,14 @@ class TRINITY_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);
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);
+13 -4
View File
@@ -417,10 +417,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))
{
@@ -466,6 +470,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++)
@@ -542,6 +547,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;
@@ -590,13 +597,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 )
@@ -678,9 +686,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 )
+1 -1
View File
@@ -140,7 +140,7 @@ VisibleNotifier::Notify()
// send data at target visibility change (adding to client)
for(std::set<WorldObject*>::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
+7 -6
View File
@@ -66,24 +66,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
};
+19 -17
View File
@@ -688,10 +688,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)
@@ -720,7 +720,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);
}
}
@@ -754,17 +754,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)
@@ -801,7 +801,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);
}
}
@@ -824,6 +824,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;
@@ -834,6 +835,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
@@ -843,8 +845,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
@@ -858,11 +860,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<uint64>(maskPos,auramask); // GROUP_UPDATE_FLAG_AURAS
@@ -873,8 +875,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
@@ -884,10 +886,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;
}
}
+32 -6
View File
@@ -785,6 +785,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)" );
@@ -1602,7 +1603,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);
@@ -1618,10 +1633,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);
@@ -1703,7 +1729,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))
+4 -1
View File
@@ -56,7 +56,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
@@ -156,6 +157,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
+11 -7
View File
@@ -206,6 +206,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;
}
@@ -450,7 +454,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();
@@ -765,9 +769,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);
}
@@ -776,7 +780,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);
}
@@ -785,7 +789,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);
}
@@ -795,7 +799,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);
}
+20 -18
View File
@@ -148,29 +148,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
@@ -211,6 +212,7 @@ class TRINITY_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();
@@ -256,9 +258,9 @@ class TRINITY_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);
+8 -3
View File
@@ -324,7 +324,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);
@@ -349,11 +349,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;
@@ -437,7 +440,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
@@ -845,6 +849,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));
}
+70 -12
View File
@@ -57,10 +57,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
{
@@ -185,10 +193,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
{
@@ -214,10 +223,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
{
@@ -272,10 +282,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
{
@@ -310,10 +321,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
{
@@ -423,7 +436,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)
@@ -500,7 +514,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;
@@ -536,12 +553,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
@@ -563,6 +581,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
+2
View File
@@ -328,6 +328,8 @@ enum TrinityStrings
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
+154 -5
View File
@@ -950,7 +950,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);
@@ -1063,8 +1063,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);
@@ -3213,6 +3213,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)
{
@@ -3840,6 +3893,36 @@ bool ChatHandler::HandleRepairitemsCommand(const char* /*args*/)
return true;
}
bool ChatHandler::HandleWaterwalkCommand(const char* args)
{
if(!*args)
return false;
Player *player = getSelectedPlayer();
if(!player)
{
PSendSysMessage(LANG_NO_CHAR_SELECTED);
SetSentErrorMessage(true);
return false;
}
if (strncmp(args, "on", 3) == 0)
player->SetMovement(MOVE_WATER_WALK); // ON
else if (strncmp(args, "off", 4) == 0)
player->SetMovement(MOVE_LAND_WALK); // OFF
else
{
SendSysMessage(LANG_USE_BOL);
return false;
}
PSendSysMessage(LANG_YOU_SET_WATERWALK, args, player->GetName());
if(needReportToTarget(player))
ChatHandler(player).PSendSysMessage(LANG_YOUR_WATERWALK_SET, args, GetName());
return true;
}
bool ChatHandler::HandleNpcFollowCommand(const char* /*args*/)
{
Player *player = m_session->GetPlayer();
@@ -3896,6 +3979,72 @@ bool ChatHandler::HandleNpcUnFollowCommand(const char* /*args*/)
return true;
}
bool ChatHandler::HandleNpcTameCommand(const char* /*args*/)
{
Creature *creatureTarget = getSelectedCreature ();
if (!creatureTarget || creatureTarget->isPet ())
{
PSendSysMessage (LANG_SELECT_CREATURE);
SetSentErrorMessage (true);
return false;
}
Player *player = m_session->GetPlayer ();
if(player->GetPetGUID ())
{
SendSysMessage (LANG_YOU_ALREADY_HAVE_PET);
SetSentErrorMessage (true);
return false;
}
CreatureInfo const* cInfo = creatureTarget->GetCreatureInfo();
if (!cInfo->isTameable ())
{
PSendSysMessage (LANG_CREATURE_NON_TAMEABLE,cInfo->Entry);
SetSentErrorMessage (true);
return false;
}
// Everything looks OK, create new pet
Pet* pet = player->CreateTamedPetFrom (creatureTarget);
if (!pet)
{
PSendSysMessage (LANG_CREATURE_NON_TAMEABLE,cInfo->Entry);
SetSentErrorMessage (true);
return false;
}
// place pet before player
float x,y,z;
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 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, level - 1);
// add to world
pet->GetMap()->Add((Creature*)pet);
// visual effect for levelup
pet->SetUInt32Value(UNIT_FIELD_LEVEL, level);
// caster have pet now
player->SetPet(pet);
pet->SavePetToDB(PET_SAVE_AS_CURRENT);
player->PetSpellInitialize();
return true;
}
bool ChatHandler::HandleCreatePetCommand(const char* args)
{
Player *player = m_session->GetPlayer();
@@ -4055,7 +4204,7 @@ bool ChatHandler::HandlePetTpCommand(const char *args)
uint32 tp = atol(args);
pet->SetTP(tp);
//pet->SetTP(tp);
PSendSysMessage("Pet's tp changed to %u", tp);
return true;
@@ -4094,4 +4243,4 @@ bool ChatHandler::HandleActivateObjectCommand(const char *args)
PSendSysMessage("Object activated!");
return true;
}
}
+31 -46
View File
@@ -299,6 +299,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`)" );
@@ -1741,6 +1750,10 @@ bool ChatHandler::HandleLearnAllMySpellsCommand(const char* /*args*/)
if(!spellInfo)
continue;
// skip server-side/triggered spells
if(spellInfo->spellLevel==0)
continue;
// skip wrong class/race skills
if(!m_session->GetPlayer()->IsSpellFitByClassAndRace(spellInfo->Id))
continue;
@@ -1749,8 +1762,6 @@ bool ChatHandler::HandleLearnAllMySpellsCommand(const char* /*args*/)
if( spellInfo->SpellFamilyName != family)
continue;
//TODO: skip triggered spells
// skip spells with first rank learned as talent (and all talents then also)
uint32 first_rank = spellmgr.GetFirstSpellInChain(spellInfo->Id);
if(GetTalentSpellCost(first_rank) > 0 )
@@ -3813,36 +3824,6 @@ bool ChatHandler::HandleHoverCommand(const char* args)
return true;
}
bool ChatHandler::HandleWaterwalkCommand(const char* args)
{
if(!args)
return false;
Player *player = getSelectedPlayer();
if(!player)
{
PSendSysMessage(LANG_NO_CHAR_SELECTED);
SetSentErrorMessage(true);
return false;
}
if (strncmp(args, "on", 3) == 0)
player->SetMovement(MOVE_WATER_WALK); // ON
else if (strncmp(args, "off", 4) == 0)
player->SetMovement(MOVE_LAND_WALK); // OFF
else
{
SendSysMessage(LANG_USE_BOL);
return false;
}
PSendSysMessage(LANG_YOU_SET_WATERWALK, args, player->GetName());
if(needReportToTarget(player))
ChatHandler(player).PSendSysMessage(LANG_YOUR_WATERWALK_SET, args, GetName());
return true;
}
bool ChatHandler::HandleLevelUpCommand(const char* args)
{
char* px = strtok((char*)args, " ");
@@ -4458,7 +4439,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);
@@ -4503,6 +4484,7 @@ bool ChatHandler::HandleResetLevelCommand(const char * args)
player->SetLevel(1);
player->InitStatsForLevel(true);
player->InitTaxiNodesForLevel();
player->InitGlyphsForLevel();
player->InitTalentForLevel();
player->SetUInt32Value(PLAYER_XP,0);
@@ -4546,6 +4528,7 @@ bool ChatHandler::HandleResetStatsCommand(const char * args)
player->InitStatsForLevel(true);
player->InitTaxiNodesForLevel();
player->InitGlyphsForLevel();
player->InitTalentForLevel();
return true;
@@ -6608,30 +6591,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
@@ -6643,14 +6623,19 @@ 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;
}
+3 -1
View File
@@ -154,6 +154,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 );
@@ -326,7 +327,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))
@@ -495,6 +496,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;
+17
View File
@@ -41,6 +41,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");
@@ -1138,6 +1139,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<ItemPrototype>(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;
@@ -1230,6 +1246,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);
+3
View File
@@ -297,6 +297,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;
@@ -307,6 +308,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();
@@ -320,6 +322,7 @@ inline void LoadLootTables()
LoadLootTemplates_Fishing();
LoadLootTemplates_Gameobject();
LoadLootTemplates_Item();
LoadLootTemplates_Milling();
LoadLootTemplates_Pickpocketing();
LoadLootTemplates_Skinning();
LoadLootTemplates_Disenchant();
+5 -3
View File
@@ -593,7 +593,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)
{
@@ -604,7 +604,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);
@@ -618,13 +618,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;
+253
View File
@@ -28,6 +28,7 @@ AM_CPPFLAGS =
# later.
noinst_LIBRARIES = libgame.a
<<<<<<< HEAD:src/game/Makefile.am
libgame_a_CPPFLAGS = \
$(MYSQL_INCLUDES) \
$(POSTGRE_INCLUDES) \
@@ -36,6 +37,258 @@ $(TRINI_INCLUDES) \
-I$(top_srcdir)/src/framework \
-I$(top_srcdir)/src/shared \
-I$(top_srcdir)/src/shared/vmap
=======
# libmangossgame library will later be reused by ...
libmangosgame_a_SOURCES = \
AccountMgr.cpp \
AccountMgr.h \
AchievementMgr.h \
AchievementMgr.cpp \
AddonHandler.cpp \
AddonHandler.h \
AggressorAI.cpp \
AggressorAI.h \
AnimalRandomMovementGenerator.h \
ArenaTeam.cpp \
ArenaTeam.h \
ArenaTeamHandler.cpp \
AuctionHouse.cpp \
AuctionHouseObject.h \
Bag.cpp \
Bag.h \
BattleGround.cpp \
BattleGroundAA.cpp \
BattleGroundAB.cpp \
BattleGroundAV.cpp \
BattleGroundBE.cpp \
BattleGroundEY.cpp \
BattleGroundNA.cpp \
BattleGroundRL.cpp \
BattleGroundWS.cpp \
BattleGround.h \
BattleGroundAA.h \
BattleGroundAB.h \
BattleGroundAV.h \
BattleGroundBE.h \
BattleGroundEY.h \
BattleGroundNA.h \
BattleGroundRL.h \
BattleGroundWS.h \
BattleGroundHandler.cpp \
BattleGroundMgr.cpp \
BattleGroundMgr.h \
Calendar.cpp \
Calendar.h \
CalendarHandler.cpp \
Cell.h \
CellImpl.h \
Channel.cpp \
Channel.h \
ChannelHandler.cpp \
ChannelMgr.h \
CharacterHandler.cpp \
Chat.cpp \
Chat.h \
ChatHandler.cpp \
CombatHandler.cpp \
ConfusedMovementGenerator.cpp \
ConfusedMovementGenerator.h \
Corpse.cpp \
Corpse.h \
CreatureAI.cpp \
CreatureAI.h \
CreatureAIImpl.h \
CreatureAIRegistry.cpp \
CreatureAIRegistry.h \
CreatureAISelector.cpp \
CreatureAISelector.h \
Creature.cpp \
Creature.h \
debugcmds.cpp \
DestinationHolder.cpp \
DestinationHolder.h \
DestinationHolderImp.h \
DuelHandler.cpp \
DynamicObject.cpp \
DynamicObject.h \
FleeingMovementGenerator.cpp \
FleeingMovementGenerator.h \
Formulas.h \
GameEvent.cpp \
GameEvent.h \
GameObject.cpp \
GameObject.h \
GlobalEvents.cpp \
GlobalEvents.h \
GMTicketHandler.cpp \
GMTicketMgr.cpp \
GMTicketMgr.h \
GossipDef.cpp \
GossipDef.h \
GridDefines.h \
GridNotifiers.cpp \
GridNotifiers.h \
GridNotifiersImpl.h \
GridStates.cpp \
GridStates.h \
Group.cpp \
Group.h \
GroupHandler.cpp \
GuardAI.cpp \
GuardAI.h \
Guild.cpp \
Guild.h \
GuildHandler.cpp \
HomeMovementGenerator.cpp \
HomeMovementGenerator.h \
HostilRefManager.cpp \
HostilRefManager.h \
IdleMovementGenerator.cpp \
IdleMovementGenerator.h \
InstanceData.cpp \
InstanceData.h \
InstanceSaveMgr.cpp \
InstanceSaveMgr.h \
Item.cpp \
Item.h \
ItemEnchantmentMgr.cpp \
ItemEnchantmentMgr.h \
ItemHandler.cpp \
ItemPrototype.h \
Language.h \
Level0.cpp \
Level1.cpp \
Level2.cpp \
Level3.cpp \
LFGHandler.cpp \
LootHandler.cpp \
LootMgr.cpp \
LootMgr.h \
Mail.cpp \
Mail.h \
Map.cpp \
Map.h \
MapInstanced.cpp \
MapInstanced.h \
MapManager.cpp \
MapManager.h \
MapReference.h \
MapRefManager.h \
MiscHandler.cpp \
MotionMaster.cpp \
MotionMaster.h \
MovementGenerator.cpp \
MovementGenerator.h \
MovementGeneratorImpl.h \
MovementHandler.cpp \
NPCHandler.cpp \
NPCHandler.h \
NullCreatureAI.cpp \
NullCreatureAI.h \
ObjectAccessor.cpp \
ObjectAccessor.h \
Object.cpp \
ObjectDefines.h \
ObjectGridLoader.cpp \
ObjectGridLoader.h \
Object.h \
ObjectMgr.cpp \
ObjectMgr.h \
ObjectPosSelector.cpp \
ObjectPosSelector.h \
Opcodes.cpp \
Opcodes.h \
Path.h \
PetAI.cpp \
PetAI.h \
Pet.cpp \
Pet.h \
PetHandler.cpp \
PetitionsHandler.cpp \
Player.cpp \
Player.h \
PlayerDump.cpp \
PlayerDump.h \
PointMovementGenerator.cpp \
PointMovementGenerator.h \
QueryHandler.cpp \
QuestDef.cpp \
QuestDef.h \
QuestHandler.cpp \
RandomMovementGenerator.cpp \
RandomMovementGenerator.h \
ReactorAI.cpp \
ReactorAI.h \
ScriptCalls.cpp \
ScriptCalls.h \
SharedDefines.h \
SkillHandler.cpp \
SpellAuraDefines.h \
SpellAuras.cpp \
SpellAuras.h \
Spell.cpp \
SpellEffects.cpp \
Spell.h \
SkillDiscovery.cpp \
SkillDiscovery.h \
SkillExtraItems.cpp \
SkillExtraItems.h \
SpellHandler.cpp \
SocialMgr.cpp \
SocialMgr.h \
SpellMgr.cpp \
SpellMgr.h \
StatSystem.cpp \
TargetedMovementGenerator.cpp \
TargetedMovementGenerator.h \
TaxiHandler.cpp \
TemporarySummon.cpp \
TemporarySummon.h \
tools.cpp \
Tools.h \
TotemAI.cpp \
TotemAI.h \
Totem.cpp \
Totem.h \
TradeHandler.cpp \
Transports.cpp \
Transports.h \
ThreatManager.cpp \
ThreatManager.h \
Traveller.h \
Unit.cpp \
Unit.h \
UnitEvents.h \
UpdateData.cpp \
UpdateData.h \
UpdateFields.h \
UpdateMask.h \
Vehicle.cpp \
Vehicle.h \
VoiceChatHandler.cpp \
WaypointManager.cpp \
WaypointManager.h \
WaypointMovementGenerator.cpp \
WaypointMovementGenerator.h \
Weather.cpp \
Weather.h \
World.cpp \
World.h \
WorldLog.cpp \
WorldLog.h \
WorldSession.cpp \
WorldSession.h \
WorldSocket.cpp \
WorldSocket.h \
WorldSocketMgr.cpp \
WorldSocketMgr.h \
FollowerReference.cpp \
FollowerReference.h \
FollowerRefManager.h \
GroupReference.cpp \
GroupReference.h \
GroupRefManager.h
>>>>>>> upstream/master:src/game/Makefile.am
# libmangossgame library will later be reused by ...
libgame_a_SOURCES = \
+3 -3
View File
@@ -45,7 +45,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];
@@ -257,7 +257,7 @@ template<>
void Map::AddToGrid(Creature* obj, NGridType *grid, Cell const& cell)
{
// add to world object registry in grid
if(obj->isPet() || obj->isPossessedByPlayer())
if(obj->isPet() || obj->isPossessedByPlayer() || obj->isVehicle())
{
(*grid)(cell.CellX(), cell.CellY()).AddWorldObject<Creature>(obj, obj->GetGUID());
obj->SetCurrentCell(cell);
@@ -301,7 +301,7 @@ template<>
void Map::RemoveFromGrid(Creature* obj, NGridType *grid, Cell const& cell)
{
// remove from world object registry in grid
if(obj->isPet() || obj->isPossessedByPlayer())
if(obj->isPet() || obj->isPossessedByPlayer() || obj->isVehicle())
{
(*grid)(cell.CellX(), cell.CellY()).RemoveWorldObject<Creature>(obj, obj->GetGUID());
}
+11
View File
@@ -224,6 +224,17 @@ class TRINITY_DLL_SPEC Map : public GridRefManager<NGridType>, public Trinity::O
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();
+4 -2
View File
@@ -175,7 +175,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;
}
@@ -280,7 +281,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)
+121 -29
View File
@@ -45,6 +45,7 @@
#include "Pet.h"
#include "SocialMgr.h"
#include "CellImpl.h"
#include "Tools.h"
void WorldSession::HandleRepopRequestOpcode( WorldPacket & /*recv_data*/ )
{
@@ -312,7 +313,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 );
@@ -349,7 +350,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" );
@@ -363,10 +364,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))
@@ -882,7 +885,7 @@ void WorldSession::HandleAreaTriggerOpcode(WorldPacket & recv_data)
if(missingItem)
SendAreaTriggerMessage(GetTrinityString(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)
@@ -894,16 +897,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<uint8*>(dest.contents()), &realSize, const_cast<uint8*>(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<uint8*>(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)
@@ -1434,11 +1517,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_;
@@ -1508,26 +1591,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");
@@ -1594,3 +1657,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);
}
+90 -125
View File
@@ -178,64 +178,12 @@ 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);
/* 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;
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())
@@ -252,7 +200,7 @@ void WorldSession::HandleMovementOpcodes( WorldPacket & recv_data )
Unit* pos_unit = GetPlayer()->GetCharm();
if (pos_unit && pos_unit->isPossessed()) // can be charmed but not possessed
{
HandlePossessedMovement(recv_data, movementInfo, MovementFlags);
HandlePossessedMovement(recv_data, movementInfo, movementInfo.flags);
return;
}
@@ -260,10 +208,10 @@ void WorldSession::HandleMovementOpcodes( WorldPacket & recv_data )
return;
//Save movement flags
GetPlayer()->SetUnitMovementFlags(MovementFlags);
GetPlayer()->SetUnitMovementFlags(movementInfo.flags);
/* 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)
@@ -282,9 +230,6 @@ void WorldSession::HandleMovementOpcodes( WorldPacket & recv_data )
{
if ((*iter)->GetGUID() == movementInfo.t_guid)
{
// unmount before boarding
GetPlayer()->RemoveSpellsCausingAura(SPELL_AURA_MOUNTED);
GetPlayer()->m_transport = (*iter);
(*iter)->AddPassenger(GetPlayer());
break;
@@ -301,13 +246,14 @@ 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())
GetPlayer()->HandleFallDamage(movementInfo);
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) );
@@ -316,14 +262,35 @@ void WorldSession::HandleMovementOpcodes( WorldPacket & recv_data )
/*----------------------*/
/* process position-change */
recv_data.put<uint32>(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<uint32>(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(!_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);
@@ -396,20 +363,13 @@ void WorldSession::HandlePossessedMovement(WorldPacket& recv_data, MovementInfo&
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;
@@ -420,47 +380,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);
@@ -473,7 +396,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)
@@ -486,6 +409,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;
@@ -520,20 +444,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::HandleNotActiveMoverOpcode(WorldPacket& /*recv_data*/)
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*/)
+7 -9
View File
@@ -524,13 +524,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)
{
@@ -541,8 +540,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;
@@ -592,7 +590,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
@@ -656,7 +654,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();
@@ -700,7 +698,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)
+51 -26
View File
@@ -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
@@ -292,12 +299,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)
@@ -330,12 +337,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();
}
//TrinIty 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;
@@ -384,6 +392,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)
@@ -485,7 +494,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;
@@ -508,6 +517,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;
@@ -515,9 +533,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
@@ -525,6 +546,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
@@ -540,10 +568,8 @@ 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);
}
if (GetUInt32Value(GAMEOBJECT_ARTKIT))
updateMask->SetBit(GAMEOBJECT_ARTKIT);
}
}
else //case UPDATETYPE_VALUES
@@ -554,8 +580,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);
}
}
@@ -572,7 +598,6 @@ void Object::_BuildValuesUpdate(uint8 updatetype, ByteBuffer * data, UpdateMask
if( updateMask->GetBit( index ) )
{
// remove custom flag before send
if( index == UNIT_NPC_FLAGS )
*data << uint32(m_uint32Values[ index ] & ~(UNIT_NPC_FLAG_GUARD + UNIT_NPC_FLAG_OUTDOORPVP));
// FIXME: Some values at server stored in float format but must be sent to client in uint32 format
@@ -641,7 +666,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 )
{
@@ -1093,7 +1118,7 @@ uint32 WorldObject::GetAreaId() const
InstanceData* WorldObject::GetInstanceData()
{
Map *map = MapManager::Instance().GetMap(m_mapId, this);
Map *map = GetMap();
return map->IsDungeon() ? ((InstanceMap*)map)->GetInstanceData() : NULL;
}
@@ -1303,7 +1328,7 @@ namespace Trinity
{
public:
MessageChatLocaleCacheDo(WorldObject const& obj, ChatMsg msgtype, int32 textId, uint32 language, uint64 targetGUID, float dist)
: i_object(obj), i_msgtype(msgtype), i_textId(textId), i_language(language),
: i_object(obj), i_msgtype(msgtype), i_textId(textId), i_language(language),
i_targetGUID(targetGUID), i_dist(dist)
{
}
@@ -1448,7 +1473,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;
@@ -1467,7 +1492,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;
@@ -1620,4 +1645,4 @@ void WorldObject::GetNearPoint(WorldObject const* searcher, float &x, float &y,
z = GetPositionZ();
UpdateGroundPositionZ(x,y,z);
}
}
+11
View File
@@ -134,6 +134,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);
}
@@ -351,6 +354,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)
{
@@ -602,6 +611,7 @@ template <class T> ZThread::FastMutex HashMapHolder<T>::i_lock;
template class HashMapHolder<Player>;
template class HashMapHolder<Pet>;
template class HashMapHolder<Vehicle>;
template class HashMapHolder<GameObject>;
template class HashMapHolder<DynamicObject>;
template class HashMapHolder<Creature>;
@@ -609,6 +619,7 @@ template class HashMapHolder<Corpse>;
template Player* ObjectAccessor::GetObjectInWorld<Player>(uint32 mapid, float x, float y, uint64 guid, Player* /*fake*/);
template Pet* ObjectAccessor::GetObjectInWorld<Pet>(uint32 mapid, float x, float y, uint64 guid, Pet* /*fake*/);
template Vehicle* ObjectAccessor::GetObjectInWorld<Vehicle>(uint32 mapid, float x, float y, uint64 guid, Vehicle* /*fake*/);
template Creature* ObjectAccessor::GetObjectInWorld<Creature>(uint32 mapid, float x, float y, uint64 guid, Creature* /*fake*/);
template Corpse* ObjectAccessor::GetObjectInWorld<Corpse>(uint32 mapid, float x, float y, uint64 guid, Corpse* /*fake*/);
template GameObject* ObjectAccessor::GetObjectInWorld<GameObject>(uint32 mapid, float x, float y, uint64 guid, GameObject* /*fake*/);
+2
View File
@@ -33,6 +33,7 @@
#include "GridDefines.h"
#include "Object.h"
#include "Player.h"
#include "Vehicle.h"
#include <set>
@@ -150,6 +151,7 @@ class TRINITY_DLL_DECL ObjectAccessor : public Trinity::Singleton<ObjectAccessor
static DynamicObject* GetDynamicObject(Unit const &, uint64);
static Corpse* GetCorpse(WorldObject const &u, uint64 guid);
static Pet* GetPet(uint64 guid);
static Vehicle* GetVehicle(uint64 guid);
static Player* FindPlayer(uint64);
Player* FindPlayerByName(const char *name) ;
+4
View File
@@ -41,6 +41,7 @@ enum HighGuid
HIGHGUID_TRANSPORT = 0xF120, // blizz F120 (for GAMEOBJECT_TYPE_TRANSPORT)
HIGHGUID_UNIT = 0xF130, // blizz F130
HIGHGUID_PET = 0xF140, // blizz F140
HIGHGUID_VEHICLE = 0xF150, // blizz F550
HIGHGUID_DYNAMICOBJECT = 0xF100, // blizz F100
HIGHGUID_CORPSE = 0xF101, // blizz F100
HIGHGUID_MO_TRANSPORT = 0x1FC0, // blizz 1FC0 (for GAMEOBJECT_TYPE_MO_TRANSPORT)
@@ -50,6 +51,7 @@ enum HighGuid
#define IS_CREATURE_GUID(Guid) ( GUID_HIPART(Guid) == HIGHGUID_UNIT )
#define IS_PET_GUID(Guid) ( GUID_HIPART(Guid) == HIGHGUID_PET )
#define IS_VEHICLE_GUID(Guid) ( GUID_HIPART(Guid) == HIGHGUID_VEHICLE )
#define IS_CREATURE_OR_PET_GUID(Guid)( IS_CREATURE_GUID(Guid) || IS_PET_GUID(Guid) )
#define IS_PLAYER_GUID(Guid) ( GUID_HIPART(Guid) == HIGHGUID_PLAYER && Guid!=0 )
#define IS_UNIT_GUID(Guid) ( IS_CREATURE_OR_PET_GUID(Guid) || IS_PLAYER_GUID(Guid) )
@@ -87,6 +89,7 @@ inline bool IsGuidHaveEnPart(uint64 const& guid)
case HIGHGUID_TRANSPORT:
case HIGHGUID_UNIT:
case HIGHGUID_PET:
case HIGHGUID_VEHICLE:
case HIGHGUID_MO_TRANSPORT:
default:
return true;
@@ -106,6 +109,7 @@ inline char const* GetLogNameForGuid(uint64 guid)
case HIGHGUID_TRANSPORT: return "transport";
case HIGHGUID_UNIT: return "creature";
case HIGHGUID_PET: return "pet";
case HIGHGUID_VEHICLE: return "vehicle";
case HIGHGUID_DYNAMICOBJECT:return "dynobject";
case HIGHGUID_CORPSE: return "corpse";
case HIGHGUID_MO_TRANSPORT: return "mo_transport";
+1 -1
View File
@@ -59,7 +59,7 @@ ObjectGridRespawnMover::Visit(CreatureMapType &m)
Creature * c = iter->getSource();
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();
+116 -34
View File
@@ -116,6 +116,7 @@ ObjectMgr::ObjectMgr()
m_hiCharGuid = 1;
m_hiCreatureGuid = 1;
m_hiPetGuid = 1;
m_hiVehicleGuid = 1;
m_hiItemGuid = 1;
m_hiGoGuid = 1;
m_hiDoGuid = 1;
@@ -641,6 +642,22 @@ void ObjectMgr::LoadCreatureLocales()
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
@@ -1003,8 +1020,47 @@ void ObjectMgr::LoadEquipmentTemplates()
{
sEquipmentStorage.Load();
for(uint32 i=0; i< sEquipmentStorage.MaxEntry; ++i)
{
EquipmentInfo const* eqInfo = sEquipmentStorage.LookupEntry<EquipmentInfo>(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<EquipmentInfo*>(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<EquipmentInfo*>(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)
@@ -1678,7 +1734,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<ItemPrototype*>(proto)->Class = ITEM_CLASS_JUNK;
const_cast<ItemPrototype*>(proto)->Class = ITEM_CLASS_MISC;
}
if(proto->SubClass >= MaxItemSubclassValues[proto->Class])
@@ -1775,7 +1831,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)
@@ -1812,7 +1868,7 @@ void ObjectMgr::LoadItemPrototypes()
const_cast<ItemPrototype*>(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<ItemPrototype*>(proto)->Spells[0].SpellId = 0;
@@ -1858,7 +1914,7 @@ void ObjectMgr::LoadItemPrototypes()
const_cast<ItemPrototype*>(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<ItemPrototype*>(proto)->Spells[j].SpellId = 0;
@@ -1927,9 +1983,6 @@ void ObjectMgr::LoadItemPrototypes()
const_cast<ItemPrototype*>(proto)->FoodType = 0;
}
}
// this DBC used currently only for check item templates in DB.
sItemStore.Clear();
}
void ObjectMgr::LoadAuctionItems()
@@ -2919,31 +2972,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)
@@ -4776,17 +4829,19 @@ uint16 ObjectMgr::GetTaxiMount( uint32 id, uint32 team )
TaxiNodesEntry const* node = sTaxiNodesStore.LookupEntry(id);
if(node)
{
if (team == ALLIANCE) mount_entry = node->alliance_mount_type;
else mount_entry = node->horde_mount_type;
CreatureInfo const *cinfo = GetCreatureTemplate(mount_entry);
if (cinfo)
if (team == ALLIANCE)
{
if(! (mount_id = cinfo->GetRandomValidModelId()))
{
sLog.outErrorDb("No displayid found for the taxi mount with the entry %u! Can't load it!", mount_entry);
return false;
}
mount_entry = node->MountCreatureID[1];
CreatureInfo const *ci = GetCreatureTemplate(mount_entry);
if(ci)
mount_id = ci->Modelid1;
}
if (team == HORDE)
{
mount_entry = node->MountCreatureID[0];
CreatureInfo const *ci = GetCreatureTemplate(mount_entry);
if(ci)
mount_id = ci->Modelid3;
}
}
@@ -5265,6 +5320,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 )
@@ -5418,6 +5475,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)
{
@@ -6380,6 +6445,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; entryId<sAchievementCriteriaStore.GetNumRows(); entryId++)
{
AchievementCriteriaEntry const* criteria = sAchievementCriteriaStore.LookupEntry(entryId);
if(!criteria)
continue;
m_AchievementCriteriasByType[criteria->requiredType].push_back(criteria);
}
}
void ObjectMgr::LoadBattleMastersEntry()
{
mBattleMastersMap.clear(); // need for reload case
@@ -6756,7 +6838,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;
}
@@ -6933,7 +7015,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;
@@ -6948,7 +7030,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;
}
}
+11
View File
@@ -264,6 +264,8 @@ typedef std::list<GossipOption> CacheNpcOptionList;
typedef UNORDERED_MAP<uint32, VendorItemData> CacheVendorItemMap;
typedef UNORDERED_MAP<uint32, TrainerSpellData> CacheTrainerSpellMap;
typedef std::list<const AchievementCriteriaEntry*> AchievementCriteriaEntryList;
enum SkillRangeType
{
SKILL_RANGE_LANGUAGE, // 300..300
@@ -588,6 +590,7 @@ class ObjectMgr
void LoadNpcTextId();
void LoadVendors();
void LoadTrainerSpell();
void LoadCompletedAchievements();
std::string GeneratePetName(uint32 entry);
uint32 GetBaseXP(uint32 level);
@@ -801,6 +804,10 @@ class ObjectMgr
bool RemoveVendorItem(uint32 entry,uint32 item, bool savetodb = true); // for event
bool IsVendorItemValid( uint32 vendor_entry, uint32 item, uint32 maxcount, uint32 ptime, uint32 ExtendedCost, Player* pl = NULL, std::set<uint32>* skip_vendors = NULL, uint32 ORnpcflag = 0 ) const;
void LoadAchievementCriteriaList();
AchievementCriteriaEntryList const& GetAchievementCriteriaByType(AchievementCriteriaTypes type);
std::set<uint32> allCompletedAchievements;
void LoadScriptNames();
ScriptNameMap &GetScriptNames() { return m_scriptNames; }
const char * GetScriptName(uint32 id) { return id < m_scriptNames.size() ? m_scriptNames[id].c_str() : ""; }
@@ -819,6 +826,7 @@ class ObjectMgr
uint32 m_hiCharGuid;
uint32 m_hiCreatureGuid;
uint32 m_hiPetGuid;
uint32 m_hiVehicleGuid;
uint32 m_hiItemGuid;
uint32 m_hiGoGuid;
uint32 m_hiDoGuid;
@@ -929,6 +937,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 Trinity::Singleton<ObjectMgr>::Instance()
+1190 -1060
View File
File diff suppressed because it is too large. Load diff
+262 -134
View File
@@ -49,8 +49,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,
@@ -66,7 +66,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,
@@ -86,7 +86,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,
@@ -214,7 +214,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,
@@ -347,7 +347,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,
@@ -371,10 +371,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,
@@ -578,7 +578,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,
@@ -733,8 +733,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,
@@ -967,10 +967,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,
@@ -980,127 +980,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
{
+118 -277
View File
@@ -41,27 +41,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;
@@ -71,17 +50,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);
@@ -128,24 +106,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;
@@ -160,7 +140,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;
@@ -194,8 +174,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();
@@ -206,72 +186,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)
{
@@ -290,11 +265,11 @@ bool Pet::LoadPetFromDB( Unit* owner, uint32 petentry, uint32 petnumber, bool cu
// patch for old data where some spells have ACT_DECIDE but should have ACT_CAST
// so overwrite old state
SpellEntry const *spellInfo = sSpellStore.LookupEntry(m_charmInfo->GetActionBarEntry(index)->SpellOrAction);
if (spellInfo && spellInfo->AttributesEx & SPELL_ATTR_EX_UNAUTOCASTABLE_BY_PET) m_charmInfo->GetActionBarEntry(index)->Type = ACT_CAST;
if (spellInfo && spellInfo->AttributesEx & SPELL_ATTR_EX_UNAUTOCASTABLE_BY_PET) m_charmInfo->GetActionBarEntry(index)->Type = ACT_ENABLED;
}
//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());
@@ -309,7 +284,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;
@@ -375,6 +353,7 @@ bool Pet::LoadPetFromDB( Unit* owner, uint32 petentry, uint32 petnumber, bool cu
}
}
m_loading = false;
return true;
}
@@ -417,10 +396,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);
@@ -437,7 +412,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() << ", "
@@ -446,9 +421,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) << ", "
@@ -521,12 +494,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);
}
}
@@ -553,6 +526,7 @@ void Pet::Update(uint32 diff)
// unsummon pet that lost owner
Unit* owner = GetOwner();
if(!owner || (!IsWithinDistInMap(owner, OWNER_MAX_DISTANCE) && !isPossessed()) || 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;
@@ -598,14 +572,6 @@ void Pet::Update(uint32 diff)
else
m_happinessTimer -= diff;
if(m_loyaltyTimer <= diff)
{
TickLoyaltyChange();
m_loyaltyTimer = 12000;
}
else
m_loyaltyTimer -= diff;
break;
}
default:
@@ -637,83 +603,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)
@@ -724,11 +619,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;
@@ -765,82 +655,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();
@@ -903,9 +717,6 @@ void Pet::GivePetXP(uint32 xp)
}
SetUInt32Value(UNIT_FIELD_PETEXPERIENCE, newXP);
if(getPetType() == HUNTER_PET)
KillLoyaltyBonus(level);
}
void Pet::GivePetLevel(uint32 level)
@@ -913,9 +724,7 @@ void Pet::GivePetLevel(uint32 level)
if(!level)
return;
InitStatsForLevel( level);
SetTP(m_TrainingPoints + (GetLoyaltyLevel() - 1));
InitStatsForLevel(level);
}
bool Pet::CreateBaseAtCreature(Creature* creature)
@@ -973,16 +782,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;
}
@@ -1112,7 +917,7 @@ bool Pet::InitStatsForLevel(uint32 petlevel)
case HUNTER_PET:
{
SetUInt32Value(UNIT_FIELD_PETNEXTLEVELEXP, uint32((Trinity::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)) );
@@ -1323,10 +1128,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)
@@ -1467,7 +1268,7 @@ bool Pet::addSpell(uint16 spell_id, uint16 active, PetSpellState state, uint16 s
// same spells don't have autocast option
if (spellInfo->AttributesEx & SPELL_ATTR_EX_UNAUTOCASTABLE_BY_PET)
active = ACT_CAST;
active = ACT_ENABLED;
PetSpellMap::iterator itr = m_spells.find(spell_id);
if (itr != m_spells.end())
@@ -1519,11 +1320,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)
{
@@ -1557,20 +1359,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)
{
@@ -1581,6 +1428,8 @@ void Pet::removeSpell(uint16 spell_id)
itr->second->state = PETSPELL_REMOVED;
RemoveAurasDueToSpell(spell_id);
return true;
}
bool Pet::_removeSpell(uint16 spell_id)
@@ -1600,7 +1449,7 @@ void Pet::InitPetCreateSpells()
m_charmInfo->InitPetActionBar();
m_spells.clear();
int32 usedtrainpoints = 0, petspellid;
int32 petspellid;
PetCreateSpellEntry const* CreateSpells = objmgr.GetPetCreateSpellEntry(GetEntry());
if(CreateSpells)
{
@@ -1629,23 +1478,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)
@@ -1704,7 +1542,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);
@@ -1715,7 +1555,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);
@@ -1738,8 +1580,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);
+9 -32
View File
@@ -52,16 +52,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,
@@ -122,9 +112,6 @@ typedef std::vector<uint32> 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
@@ -167,14 +154,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);
@@ -194,10 +174,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; }
@@ -215,7 +193,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;
@@ -225,11 +205,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;
@@ -241,14 +220,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;
+143 -10
View File
@@ -174,9 +174,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)
@@ -257,7 +257,7 @@ void WorldSession::HandlePetAction( WorldPacket & recv_data )
if(pet->isPossessed())
{
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:
@@ -369,7 +369,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)
@@ -542,11 +542,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)
@@ -616,11 +615,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);
// This opcode is also sent from charmed and possessed units (players and creatures)
if(!_player->GetPet() && !_player->GetCharm())
@@ -655,6 +658,7 @@ void WorldSession::HandlePetCastSpellOpcode( WorldPacket& recvPacket )
caster->clearUnitState(UNIT_STAT_FOLLOW);
Spell *spell = new Spell(caster, spellInfo, false);
spell->m_cast_count = cast_count; // probably pending spell cast
spell->m_targets = targets;
int16 result = spell->PetCanCast(NULL);
@@ -713,3 +717,132 @@ void WorldSession::SendPetNameInvalid(uint32 error, const std::string& name, Dec
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);
}
+4 -4
View File
@@ -199,9 +199,9 @@ 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);
@@ -565,7 +565,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))
+1011 -368
View File
File diff suppressed because it is too large. Load diff
+130 -28
View File
@@ -35,6 +35,7 @@
#include "Pet.h"
#include "MapReference.h"
#include "Util.h" // for Tokens typedef
#include "AchievementMgr.h"
#include<string>
#include<vector>
@@ -49,6 +50,8 @@ class Transport;
class UpdateMask;
class PlayerSocial;
class OutdoorPvP;
class AchievementMgr;
class Vehicle;
typedef std::deque<Mail*> PlayerMails;
@@ -80,15 +83,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;
};
@@ -224,6 +229,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)
@@ -392,7 +430,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<<bit_index) without (-1)
@@ -481,7 +519,8 @@ enum LootType
LOOT_DISENCHANTING = 5, // unsupported by client, sending LOOT_SKINNING instead
LOOT_PROSPECTING = 6, // unsupported by client, sending LOOT_SKINNING instead
LOOT_INSIGNIA = 7, // unsupported by client, sending LOOT_SKINNING instead
LOOT_FISHINGHOLE = 8 // unsupported by client, sending LOOT_FISHING instead
LOOT_FISHINGHOLE = 8, // unsupported by client, sending LOOT_FISHING instead
LOOT_MILLING = 9 // unsupported by client, sending LOOT_SKINNING instead
};
enum MirrorTimerType
@@ -512,7 +551,8 @@ enum AtLoginFlags
AT_LOGIN_NONE = 0,
AT_LOGIN_RENAME = 1,
AT_LOGIN_RESET_SPELLS = 2,
AT_LOGIN_RESET_TALENTS = 4
AT_LOGIN_RESET_TALENTS = 4,
AT_LOGIN_CUSTOMIZE = 8
};
typedef std::map<uint32, QuestStatusData> QuestStatusMap;
@@ -544,7 +584,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)
};
@@ -672,6 +712,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) {}
@@ -690,14 +748,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 <TBC,WotLK> expansion installed to access this area.
TRANSFER_ABORT_DIFFICULTY = 0x07, // <Normal,Heroic,Epic> 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
@@ -711,15 +770,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;
@@ -730,17 +790,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
@@ -813,10 +873,12 @@ enum PlayerLoginQueryIndex
PLAYER_LOGIN_QUERY_LOADDECLINEDNAMES = 16,
PLAYER_LOGIN_QUERY_LOADGUILD = 17,
PLAYER_LOGIN_QUERY_LOADARENAINFO = 18,
MAX_PLAYER_LOGIN_QUERY
PLAYER_LOGIN_QUERY_LOADACHIEVEMENTS = 19,
PLAYER_LOGIN_QUERY_LOADCRITERIAPROGRESS = 20,
MAX_PLAYER_LOGIN_QUERY = 21
};
// Player summoning auto-decline time (in secs)
#define MAX_PLAYER_SUMMON_DELAY (2*MINUTE)
#define MAX_MONEY_AMOUNT (0x7FFFFFFF-1)
@@ -837,7 +899,7 @@ class TRINITY_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);
@@ -940,7 +1002,7 @@ class TRINITY_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;
@@ -953,10 +1015,12 @@ class TRINITY_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<uint32> 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); }
@@ -1052,6 +1116,7 @@ class TRINITY_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); }
@@ -1130,6 +1195,11 @@ class TRINITY_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);
@@ -1285,6 +1355,7 @@ class TRINITY_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;
@@ -1423,6 +1494,12 @@ class TRINITY_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();
@@ -1431,8 +1508,6 @@ class TRINITY_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 <class T> T ApplySpellMod(uint32 spellId, SpellModOp op, T &basevalue, Spell const* spell = NULL);
void RemoveSpellMods(Spell const* spell);
@@ -1589,6 +1664,10 @@ class TRINITY_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);
@@ -1759,6 +1838,8 @@ class TRINITY_DLL_SPEC Player : public Unit
void SetCanParry(bool value);
bool CanBlock() const { return m_canBlock; }
void SetCanBlock(bool 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; }
@@ -1792,7 +1873,7 @@ class TRINITY_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<ItemSetEffect *> ItemSetEff;
@@ -1953,6 +2034,7 @@ class TRINITY_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;
@@ -1970,6 +2052,9 @@ class TRINITY_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); }
@@ -1982,6 +2067,7 @@ class TRINITY_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; }
@@ -2080,6 +2166,18 @@ class TRINITY_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);
@@ -2216,6 +2314,7 @@ class TRINITY_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;
@@ -2249,7 +2348,6 @@ class TRINITY_DLL_SPEC Player : public Unit
bool m_DailyQuestChanged;
time_t m_lastDailyQuestTime;
uint32 m_regenTimer;
uint32 m_breathTimer;
uint32 m_drunkTimer;
uint16 m_drunk;
@@ -2268,8 +2366,10 @@ class TRINITY_DLL_SPEC Player : public Unit
uint32 m_ArmorProficiency;
bool m_canParry;
bool m_canBlock;
bool m_canTitanGrip;
uint8 m_swingErrorMsg;
float m_ammoDPS;
////////////////////Rest System/////////////////////
int time_inn_enter;
uint32 inn_pos_mapid;
@@ -2316,6 +2416,8 @@ class TRINITY_DLL_SPEC Player : public Unit
bool m_farsightVision;
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;
+35 -12
View File
@@ -33,6 +33,7 @@
#include "NPCHandler.h"
#include "ObjectAccessor.h"
#include "Pet.h"
#include "MapManager.h"
void WorldSession::SendNameQueryOpcode(Player *p)
{
@@ -185,7 +186,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->Modelid1; // Modelid1
data << (uint32)ci->Modelid2; // Modelid2
@@ -276,20 +276,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);
}
+47 -45
View File
@@ -44,88 +44,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;
+27 -20
View File
@@ -44,30 +44,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
@@ -190,6 +193,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; }
@@ -277,6 +282,8 @@ class Quest
uint32 LimitTime;
uint32 QuestFlags;
uint32 CharTitleId;
uint32 PlayersSlain;
uint32 BonusTalents;
int32 PrevQuestId;
int32 NextQuestId;
int32 ExclusiveGroup;
-6
View File
@@ -451,12 +451,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 );
+187 -122
View File
@@ -88,7 +88,8 @@ enum Classes
#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)))
@@ -134,11 +135,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
{
@@ -199,10 +201,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
enum SpellCategory
{
@@ -217,7 +220,7 @@ enum SpellCategory
#define SPELL_ATTR_UNK0 0x00000001 // 0
#define SPELL_ATTR_RANGED 0x00000002 // 1 All ranged abilities 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
@@ -272,7 +275,7 @@ enum SpellCategory
#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
@@ -288,14 +291,14 @@ enum SpellCategory
#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_TAME_BEAST 0x00010000 // 16
#define SPELL_ATTR_EX2_NOT_RESET_AUTOSHOT 0x00020000 // 17 Hunters Shot and Stings only have this flag
#define SPELL_ATTR_EX2_UNK18 0x00040000 // 18 Only Revive pet - possible req dead pet
@@ -413,37 +416,37 @@ enum SpellCategory
#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
{
@@ -566,7 +569,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,
@@ -586,16 +589,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,
@@ -608,10 +611,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, //unused
@@ -655,19 +658,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,
@@ -675,7 +678,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
@@ -703,7 +712,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
@@ -711,11 +721,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,
@@ -731,7 +741,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,
@@ -739,12 +749,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<<MECHANIC_CHARM )|(1<<MECHANIC_CONFUSED )|(1<<MECHANIC_FEAR )| \
(1<<MECHANIC_CHARM )|(1<<MECHANIC_DISORIENTED )|(1<<MECHANIC_FEAR )| \
(1<<MECHANIC_ROOT )|(1<<MECHANIC_PACIFY )|(1<<MECHANIC_SLEEP )| \
(1<<MECHANIC_SNARE )|(1<<MECHANIC_STUN )|(1<<MECHANIC_FREEZE)| \
(1<<MECHANIC_KNOCKOUT)|(1<<MECHANIC_POLYMORPH)|(1<<MECHANIC_BANISH)| \
@@ -764,7 +775,8 @@ enum DispelType
DISPEL_ALL = 7,
DISPEL_SPE_NPC_ONLY = 8,
DISPEL_ENRAGE = 9,
DISPEL_ZG_TICKET = 10
DISPEL_ZG_TICKET = 10,
DESPEL_OLD_UNUSED = 11
};
#define DISPEL_ALL_MASK ( (1<<DISPEL_MAGIC) | (1<<DISPEL_CURSE) | (1<<DISPEL_DISEASE) | (1<<DISPEL_POISON) )
@@ -978,9 +990,10 @@ enum GameobjectTypes
GAMEOBJECT_TYPE_BARBER_CHAIR = 32,
GAMEOBJECT_TYPE_DESTRUCTIBLE_BUILDING = 33,
GAMEOBJECT_TYPE_GUILD_BANK = 34,
GAMEOBJECT_TYPE_TRAPDOOR = 35
};
#define MAX_GAMEOBJECT_TYPE 35 // sending to client this or greater value can crash client.
#define MAX_GAMEOBJECT_TYPE 36 // sending to client this or greater value can crash client.
#define GAMEOBJECT_FISHINGNODE_ENTRY 35591 // Better to define it somewhere instead of hardcoding everywhere
@@ -1547,7 +1560,9 @@ enum LockType
LOCKTYPE_BLASTING = 16,
LOCKTYPE_SLOW_OPEN = 17,
LOCKTYPE_SLOW_CLOSE = 18,
LOCKTYPE_FISHING = 19
LOCKTYPE_FISHING = 19,
LOCKTYPE_INSCRIPTION = 20,
LOCKTYPE_OPEN_FROM_VEHICLE = 21
};
enum TrainerType // this is important type for npcs!
@@ -1601,7 +1616,7 @@ enum CreatureFamily
CREATURE_FAMILY_IMP = 23,
CREATURE_FAMILY_BAT = 24,
CREATURE_FAMILY_HYENA = 25,
CREATURE_FAMILY_OWL = 26,
CREATURE_FAMILY_BIRD_OF_PREY = 26,
CREATURE_FAMILY_WIND_SERPENT = 27,
CREATURE_FAMILY_REMOTE_CONTROL = 28,
CREATURE_FAMILY_FELGUARD = 29,
@@ -1611,7 +1626,16 @@ enum CreatureFamily
CREATURE_FAMILY_SPOREBAT = 33,
CREATURE_FAMILY_NETHER_RAY = 34,
CREATURE_FAMILY_SERPENT = 35,
CREATURE_FAMILY_SEA_LION = 36
CREATURE_FAMILY_MOTH = 37,
CREATURE_FAMILY_CHIMAERA = 38,
CREATURE_FAMILY_DEVILSAUR = 39,
CREATURE_FAMILY_GHOUL = 40,
CREATURE_FAMILY_SILITHID = 41,
CREATURE_FAMILY_WORM = 42,
CREATURE_FAMILY_RHINO = 43,
CREATURE_FAMILY_WASP = 44,
CREATURE_FAMILY_CORE_HOUND = 45,
CREATURE_FAMILY_SPIRIT_BEAST = 46
};
enum CreatureTypeFlags
@@ -1643,6 +1667,8 @@ enum QuestTypes
QUEST_TYPE_LEGENDARY = 83,
QUEST_TYPE_ESCORT = 84,
QUEST_TYPE_HEROIC = 85,
QUEST_TYPE_RAID_10 = 88,
QUEST_TYPE_RAID_25 = 89
};
// values based at QuestSort.dbc
@@ -1653,7 +1679,7 @@ enum QuestSort
QUEST_SORT_SEASONAL = 22,
QUEST_SORT_UNDERCITY_OLD = 23,
QUEST_SORT_HERBALISM = 24,
QUEST_SORT_SCARLET_MONASTERY_OLD= 25,
QUEST_SORT_BATTLEGROUNDS = 25,
QUEST_SORT_ULDAMN_OLD = 41,
QUEST_SORT_WARLOCK = 61,
QUEST_SORT_WARRIOR = 81,
@@ -1682,22 +1708,26 @@ enum QuestSort
QUEST_SORT_REPUTATION = 367,
QUEST_SORT_INVASION = 368,
QUEST_SORT_MIDSUMMER = 369,
QUEST_SORT_BREWFEST = 370
QUEST_SORT_BREWFEST = 370,
QUEST_SORT_INSCRIPTION = 371,
QUEST_SORT_DEATH_KNIGHT = 372,
QUEST_SORT_JEWELCRAFTING = 373
};
inline uint8 ClassByQuestSort(int32 QuestSort)
{
switch(QuestSort)
{
case QUEST_SORT_WARLOCK: return CLASS_WARLOCK;
case QUEST_SORT_WARRIOR: return CLASS_WARRIOR;
case QUEST_SORT_SHAMAN: return CLASS_SHAMAN;
case QUEST_SORT_PALADIN: return CLASS_PALADIN;
case QUEST_SORT_MAGE: return CLASS_MAGE;
case QUEST_SORT_ROGUE: return CLASS_ROGUE;
case QUEST_SORT_HUNTER: return CLASS_HUNTER;
case QUEST_SORT_PRIEST: return CLASS_PRIEST;
case QUEST_SORT_DRUID: return CLASS_DRUID;
case QUEST_SORT_WARLOCK: return CLASS_WARLOCK;
case QUEST_SORT_WARRIOR: return CLASS_WARRIOR;
case QUEST_SORT_SHAMAN: return CLASS_SHAMAN;
case QUEST_SORT_PALADIN: return CLASS_PALADIN;
case QUEST_SORT_MAGE: return CLASS_MAGE;
case QUEST_SORT_ROGUE: return CLASS_ROGUE;
case QUEST_SORT_HUNTER: return CLASS_HUNTER;
case QUEST_SORT_PRIEST: return CLASS_PRIEST;
case QUEST_SORT_DRUID: return CLASS_DRUID;
case QUEST_SORT_DEATH_KNIGHT: return CLASS_DEATH_KNIGHT;
}
return 0;
}
@@ -1709,7 +1739,6 @@ enum SkillType
SKILL_ARMS = 26,
SKILL_COMBAT = 38,
SKILL_SUBTLETY = 39,
SKILL_POISONS = 40,
SKILL_SWORDS = 43,
SKILL_AXES = 44,
SKILL_BOWS = 45,
@@ -1717,8 +1746,8 @@ enum SkillType
SKILL_BEAST_MASTERY = 50,
SKILL_SURVIVAL = 51,
SKILL_MACES = 54,
SKILL_HOLY = 56,
SKILL_2H_SWORDS = 55,
SKILL_HOLY = 56,
SKILL_SHADOW = 78,
SKILL_DEFENSE = 95,
SKILL_LANG_COMMON = 98,
@@ -1774,24 +1803,20 @@ enum SkillType
SKILL_PET_BOAR = 211,
SKILL_PET_CROCILISK = 212,
SKILL_PET_CARRION_BIRD = 213,
SKILL_PET_GORILLA = 215,
SKILL_PET_CRAB = 214,
SKILL_PET_GORILLA = 215,
SKILL_PET_RAPTOR = 217,
SKILL_PET_TALLSTRIDER = 218,
SKILL_RACIAL_UNDED = 220,
SKILL_WEAPON_TALENTS = 222,
SKILL_CROSSBOWS = 226,
SKILL_SPEARS = 227,
SKILL_WANDS = 228,
SKILL_POLEARMS = 229,
SKILL_PET_SCORPID = 236,
SKILL_ARCANE = 237,
SKILL_OPEN_LOCK = 242,
SKILL_PET_TURTLE = 251,
SKILL_ASSASSINATION = 253,
SKILL_FURY = 256,
SKILL_PROTECTION = 257,
SKILL_BEAST_TRAINING = 261,
SKILL_PROTECTION2 = 267,
SKILL_PET_TALENTS = 270,
SKILL_PLATE_MAIL = 293,
@@ -1821,7 +1846,7 @@ enum SkillType
SKILL_LOCKPICKING = 633,
SKILL_PET_BAT = 653,
SKILL_PET_HYENA = 654,
SKILL_PET_OWL = 655,
SKILL_PET_BIRD_OF_PREY = 655,
SKILL_PET_WIND_SERPENT = 656,
SKILL_LANG_GUTTERSPEAK = 673,
SKILL_RIDING_KODO = 713,
@@ -1841,10 +1866,27 @@ enum SkillType
SKILL_PET_WARP_STALKER = 766,
SKILL_PET_RAVAGER = 767,
SKILL_PET_SERPENT = 768,
SKILL_INTERNAL = 769
SKILL_INTERNAL = 769,
SKILL_DK_BLOOD = 770,
SKILL_DK_FROST = 771,
SKILL_DK_UNHOLY = 772,
SKILL_INSCRIPTION = 773,
SKILL_PET_MOTH = 775,
SKILL_RUNEFORGING = 776,
SKILL_MOUNTS = 777,
SKILL_COMPANIONS = 778,
SKILL_PET_EXOTIC_CHIMAERA = 780,
SKILL_PET_EXOTIC_DEVILSAUR = 781,
SKILL_PET_GHOUL = 782,
SKILL_PET_EXOTIC_SILITHID = 783,
SKILL_PET_EXOTIC_WORM = 784,
SKILL_PET_WASP = 785,
SKILL_PET_EXOTIC_RHINO = 786,
SKILL_PET_EXOTIC_CORE_HOUND = 787,
SKILL_PET_EXOTIC_SPIRIT_BEAST = 788
};
#define MAX_SKILL_TYPE 770
#define MAX_SKILL_TYPE 789
inline uint32 SkillByQuestSort(int32 QuestSort)
{
@@ -1859,25 +1901,27 @@ inline uint32 SkillByQuestSort(int32 QuestSort)
case QUEST_SORT_TAILORING: return SKILL_TAILORING;
case QUEST_SORT_COOKING: return SKILL_COOKING;
case QUEST_SORT_FIRST_AID: return SKILL_FIRST_AID;
case QUEST_SORT_JEWELCRAFTING: return SKILL_JEWELCRAFTING;
case QUEST_SORT_INSCRIPTION: return SKILL_INSCRIPTION;
}
return 0;
}
enum SkillCategory
{
SKILL_CATEGORY_ATTRIBUTES = 5,
SKILL_CATEGORY_WEAPON = 6,
SKILL_CATEGORY_CLASS = 7,
SKILL_CATEGORY_ARMOR = 8,
SKILL_CATEGORY_SECONDARY = 9, // secondary professions
SKILL_CATEGORY_ATTRIBUTES = 5,
SKILL_CATEGORY_WEAPON = 6,
SKILL_CATEGORY_CLASS = 7,
SKILL_CATEGORY_ARMOR = 8,
SKILL_CATEGORY_SECONDARY = 9, // secondary professions
SKILL_CATEGORY_LANGUAGES = 10,
SKILL_CATEGORY_PROFESSION = 11, // primary professions
SKILL_CATEGORY_NOT_DISPLAYED = 12
SKILL_CATEGORY_GENERIC = 12
};
enum TotemCategory
{
TC_SKINNING_SKIFE = 1,
TC_SKINNING_SKIFE_OLD = 1,
TC_EARTH_TOTEM = 2,
TC_AIR_TOTEM = 3,
TC_FIRE_TOTEM = 4,
@@ -1887,15 +1931,28 @@ enum TotemCategory
TC_GOLDEN_ROD = 8,
TC_TRUESILVER_ROD = 9,
TC_ARCANITE_ROD = 10,
TC_MINING_PICK = 11,
TC_MINING_PICK_OLD = 11,
TC_PHILOSOPHERS_STONE = 12,
TC_BLACKSMITH_HAMMER = 13,
TC_BLACKSMITH_HAMMER_OLD = 13,
TC_ARCLIGHT_SPANNER = 14,
TC_GYROMATIC_MA = 15,
TC_MASTER_TOTEM = 21,
TC_FEL_IRON_ROD = 41,
TC_ADAMANTITE_ROD = 62,
TC_ETERNIUM_ROD = 63
TC_ETERNIUM_ROD = 63,
TC_HOLLOW_QUILL = 81,
TC_RUNED_AZURITE_ROD = 101,
TC_VIRTUOSO_INKING_SET = 121,
TC_DRUMS = 141,
TC_GNOMISH_ARMY_KNIFE = 161,
TC_BLACKSMITH_HAMMER = 162,
TC_MINING_PICK = 165,
TC_SKINNING_KNIFE = 166,
TC_HAMMER_PICK = 167,
TC_BLADED_PICKAXE = 168,
TC_FLINT_AND_TINDER = 169,
TC_RUNED_COBALT_ROD = 189,
TC_RUNED_TITANIUM_ROD = 190
};
enum UnitDynFlags
@@ -1905,7 +1962,8 @@ enum UnitDynFlags
UNIT_DYNFLAG_OTHER_TAGGER = 0x0004,
UNIT_DYNFLAG_ROOTED = 0x0008,
UNIT_DYNFLAG_SPECIALINFO = 0x0010,
UNIT_DYNFLAG_DEAD = 0x0020
UNIT_DYNFLAG_DEAD = 0x0020,
UNIT_DYNFLAG_REFER_A_FRIEND = 0x0040
};
enum CorpseDynFlags
@@ -1915,6 +1973,7 @@ enum CorpseDynFlags
// Passive Spell codes explicit used in code
#define SPELL_ID_GENERIC_LEARN 483
#define SPELL_ID_GENERIC_LEARN_PET 55884 // used for learning mounts and companions
#define SPELL_ID_PASSIVE_BATTLE_STANCE 2457
#define SPELL_ID_PASSIVE_RESURRECTION_SICKNESS 15007
#define SPELL_ID_WEAPON_SWITCH_COOLDOWN_1_5s 6119
@@ -1982,9 +2041,12 @@ enum ChatMsg
CHAT_MSG_BATTLEGROUND = 0x2C,
CHAT_MSG_BATTLEGROUND_LEADER = 0x2D,
CHAT_MSG_RESTRICTED = 0x2E,
CHAT_MSG_BN = 0x2F,
CHAT_MSG_ACHIEVEMENT = 0x30,
CHAT_MSG_GUILD_ACHIEVEMENT = 0x31
};
#define MAX_CHAT_MSG_TYPE 0x2F
#define MAX_CHAT_MSG_TYPE 0x32
// Values from ItemPetFood (power of (value-1) used for compare with CreatureFamilyEntry.petDietMask
enum PetDiet
@@ -2153,42 +2215,45 @@ enum ResponseCodes
CHAR_CREATE_SERVER_QUEUE = 0x37,
CHAR_CREATE_ONLY_EXISTING = 0x38,
CHAR_CREATE_EXPANSION = 0x39,
CHAR_CREATE_EXPANSION_CLASS = 0x3A,
CHAR_CREATE_LEVEL_REQUIREMENT = 0x3B,
CHAR_CREATE_UNIQUE_CLASS_LIMIT = 0x3C,
CHAR_DELETE_IN_PROGRESS = 0x3A,
CHAR_DELETE_SUCCESS = 0x3B,
CHAR_DELETE_FAILED = 0x3C,
CHAR_DELETE_FAILED_LOCKED_FOR_TRANSFER = 0x3D,
CHAR_DELETE_FAILED_GUILD_LEADER = 0x3E,
CHAR_DELETE_FAILED_ARENA_CAPTAIN = 0x3F,
CHAR_DELETE_IN_PROGRESS = 0x3D,
CHAR_DELETE_SUCCESS = 0x3E,
CHAR_DELETE_FAILED = 0x3F,
CHAR_DELETE_FAILED_LOCKED_FOR_TRANSFER = 0x40,
CHAR_DELETE_FAILED_GUILD_LEADER = 0x41,
CHAR_DELETE_FAILED_ARENA_CAPTAIN = 0x42,
CHAR_LOGIN_IN_PROGRESS = 0x40,
CHAR_LOGIN_SUCCESS = 0x41,
CHAR_LOGIN_NO_WORLD = 0x42,
CHAR_LOGIN_DUPLICATE_CHARACTER = 0x43,
CHAR_LOGIN_NO_INSTANCES = 0x44,
CHAR_LOGIN_FAILED = 0x45,
CHAR_LOGIN_DISABLED = 0x46,
CHAR_LOGIN_NO_CHARACTER = 0x47,
CHAR_LOGIN_LOCKED_FOR_TRANSFER = 0x48,
CHAR_LOGIN_LOCKED_BY_BILLING = 0x49,
CHAR_LOGIN_IN_PROGRESS = 0x43,
CHAR_LOGIN_SUCCESS = 0x44,
CHAR_LOGIN_NO_WORLD = 0x45,
CHAR_LOGIN_DUPLICATE_CHARACTER = 0x46,
CHAR_LOGIN_NO_INSTANCES = 0x47,
CHAR_LOGIN_FAILED = 0x48,
CHAR_LOGIN_DISABLED = 0x49,
CHAR_LOGIN_NO_CHARACTER = 0x4A,
CHAR_LOGIN_LOCKED_FOR_TRANSFER = 0x4B,
CHAR_LOGIN_LOCKED_BY_BILLING = 0x4C,
CHAR_NAME_SUCCESS = 0x4A,
CHAR_NAME_FAILURE = 0x4B,
CHAR_NAME_NO_NAME = 0x4C,
CHAR_NAME_TOO_SHORT = 0x4D,
CHAR_NAME_TOO_LONG = 0x4E,
CHAR_NAME_INVALID_CHARACTER = 0x4F,
CHAR_NAME_MIXED_LANGUAGES = 0x50,
CHAR_NAME_PROFANE = 0x51,
CHAR_NAME_RESERVED = 0x52,
CHAR_NAME_INVALID_APOSTROPHE = 0x53,
CHAR_NAME_MULTIPLE_APOSTROPHES = 0x54,
CHAR_NAME_THREE_CONSECUTIVE = 0x55,
CHAR_NAME_INVALID_SPACE = 0x56,
CHAR_NAME_CONSECUTIVE_SPACES = 0x57,
CHAR_NAME_RUSSIAN_CONSECUTIVE_SILENT_CHARACTERS = 0x58,
CHAR_NAME_RUSSIAN_SILENT_CHARACTER_AT_BEGINNING_OR_END = 0x59,
CHAR_NAME_DECLENSION_DOESNT_MATCH_BASE_NAME = 0x5A,
CHAR_NAME_SUCCESS = 0x4D,
CHAR_NAME_FAILURE = 0x4E,
CHAR_NAME_NO_NAME = 0x4F,
CHAR_NAME_TOO_SHORT = 0x50,
CHAR_NAME_TOO_LONG = 0x51,
CHAR_NAME_INVALID_CHARACTER = 0x52,
CHAR_NAME_MIXED_LANGUAGES = 0x53,
CHAR_NAME_PROFANE = 0x54,
CHAR_NAME_RESERVED = 0x55,
CHAR_NAME_INVALID_APOSTROPHE = 0x56,
CHAR_NAME_MULTIPLE_APOSTROPHES = 0x57,
CHAR_NAME_THREE_CONSECUTIVE = 0x58,
CHAR_NAME_INVALID_SPACE = 0x59,
CHAR_NAME_CONSECUTIVE_SPACES = 0x5A,
CHAR_NAME_RUSSIAN_CONSECUTIVE_SILENT_CHARACTERS = 0x5B,
CHAR_NAME_RUSSIAN_SILENT_CHARACTER_AT_BEGINNING_OR_END = 0x5C,
CHAR_NAME_DECLENSION_DOESNT_MATCH_BASE_NAME = 0x5D
};
/// Ban function modes
-4
View File
@@ -82,10 +82,6 @@ void WorldSession::HandleLearnTalentOpcode( WorldPacket & recv_data )
}
}
// Check if it requires spell
if( talentInfo->DependsOnSpell && !player->HasSpell(talentInfo->DependsOnSpell) )
return;
// Find out how many points we have in this field
uint32 spentPoints = 0;
+323 -79
View File
@@ -237,7 +237,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)
{
@@ -357,6 +357,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
@@ -365,6 +366,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
@@ -502,6 +504,8 @@ void Spell::FillTargetMap()
case SPELL_EFFECT_TRIGGER_SPELL:
//case SPELL_EFFECT_TRIGGER_MISSILE: ??
case SPELL_EFFECT_SKILL_STEP:
case SPELL_EFFECT_PROFICIENCY:
case SPELL_EFFECT_SUMMON_OBJECT_WILD:
case SPELL_EFFECT_SELF_RESURRECT:
case SPELL_EFFECT_REPUTATION:
if(m_targets.getUnitTarget())
@@ -533,6 +537,7 @@ void Spell::FillTargetMap()
break;
case SPELL_EFFECT_SUMMON_CHANGE_ITEM:
case SPELL_EFFECT_ADD_FARSIGHT:
case SPELL_EFFECT_APPLY_GLYPH:
case SPELL_EFFECT_STUCK:
case SPELL_EFFECT_DESTROY_ALL_TOTEMS:
tmpUnitMap.push_back(m_caster);
@@ -546,6 +551,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;
@@ -1110,6 +1116,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) )
@@ -1320,6 +1337,16 @@ void Spell::SearchChainTarget(std::list<Unit*> &TagUnitMap, Unit* pUnitTarget, f
if(!pUnitTarget)
return;
// 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;
}*/
//FIXME: This very like horrible hack and wrong for most spells
if(m_spellInfo->DmgClass != SPELL_DAMAGE_CLASS_MELEE)
max_range += unMaxTargets * CHAIN_SPELL_JUMP_RADIUS;
@@ -2226,6 +2253,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();
@@ -2668,7 +2703,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<TargetInfo>::iterator ihit= m_UniqueTargetInfo.begin();ihit != m_UniqueTargetInfo.end();++ihit)
if( ihit->effectMask & (1<<auraSpellIdx) )
@@ -2724,9 +2759,9 @@ void Spell::SendCastResult(uint8 result)
if(result != 0)
{
WorldPacket data(SMSG_CAST_FAILED, (4+1+1));
data << uint8(m_cast_count); // single cast or multi 2.3 (0/1)
data << uint32(m_spellInfo->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:
@@ -2767,18 +2802,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()
@@ -2792,6 +2820,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));
@@ -2801,14 +2832,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);
@@ -2828,6 +2877,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());
@@ -2835,17 +2891,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);
}
@@ -2973,30 +3065,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())
@@ -3015,6 +3096,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;
}
@@ -3028,13 +3116,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);
}
@@ -3102,10 +3193,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);
}
@@ -3202,6 +3302,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
@@ -3209,6 +3315,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.
@@ -3217,11 +3433,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++)
{
@@ -3344,12 +3558,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
@@ -3686,7 +3913,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;
@@ -3711,15 +3938,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:
@@ -3734,15 +3955,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:
@@ -3845,27 +4060,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))
@@ -3922,9 +4137,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;
@@ -3935,9 +4150,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
@@ -3986,7 +4201,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:
{
@@ -4143,7 +4357,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;
@@ -4165,8 +4379,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;
}
@@ -4481,9 +4695,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;
@@ -4528,6 +4745,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)
@@ -4655,8 +4877,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++)
{
@@ -4824,13 +5045,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:
{
@@ -5003,9 +5247,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
+43 -10
View File
@@ -47,26 +47,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_UNKNOWN3 = 0x00000100
CAST_FLAG_AMMO = 0x00000020, // Projectiles visual
CAST_FLAG_UNKNOWN8 = 0x00000040,
CAST_FLAG_UNKNOWN9 = 0x00000080,
CAST_FLAG_UNKNOWN3 = 0x00000100,
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_UNKNOWN20 = 0x00100000,
CAST_FLAG_UNKNOWN7 = 0x00200000 // wotlk, rune cooldown list
};
enum SpellRangeFlag
@@ -275,6 +300,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);
@@ -292,6 +318,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);
@@ -318,6 +345,8 @@ class Spell
void EffectKillCredit(uint32 i);
void EffectQuestFail(uint32 i);
void EffectRedirectThreat(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();
@@ -328,6 +357,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();
@@ -386,6 +417,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; }
@@ -422,7 +454,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;
@@ -449,6 +481,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; }
+43 -15
View File
@@ -20,14 +20,19 @@
#ifndef TRINITY_SPELLAURADEFINES_H
#define TRINITY_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
@@ -233,7 +238,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,
@@ -275,7 +280,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,
@@ -285,28 +290,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,
+648 -241
View File
File diff suppressed because it is too large. Load diff
+24 -8
View File
@@ -100,6 +100,7 @@ class TRINITY_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);
@@ -184,10 +185,12 @@ class TRINITY_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);
@@ -197,6 +200,7 @@ class TRINITY_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);
@@ -209,6 +213,9 @@ class TRINITY_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);
void HandleModAttackerSpellHitChance(bool apply, bool Real);
virtual ~Aura();
@@ -231,6 +238,8 @@ class TRINITY_DLL_SPEC Aura
int32 GetAuraDuration() const { return m_duration; }
void SetAuraDuration(int32 duration) { m_duration = duration; }
time_t GetAuraApplyTime() { return m_applyTime; }
SpellModifier *getAuraSpellMod() {return m_spellmod; }
void UpdateAuraDuration();
void SendAuraDurationForCaster(Player* caster);
void UpdateSlotCounterAndDuration();
@@ -250,13 +259,19 @@ class TRINITY_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)
SendAuraUpdate(false);
}
bool IsPositive() { return m_positive; }
@@ -300,6 +315,9 @@ class TRINITY_DLL_SPEC Aura
void PeriodicTick();
void PeriodicDummyTick();
uint32 const *getAuraSpellClassMask() const { return m_spellProto->EffectSpellClassMaskA + m_effIndex * 3; }
bool isAffectedOnSpell(SpellEntry const *spell) const;
int32 GetStackAmount() {return m_stackAmount;}
void SetStackAmount(int32 amount) {m_stackAmount=amount;}
protected:
@@ -321,6 +339,8 @@ class TRINITY_DLL_SPEC Aura
AuraRemoveMode m_removeMode;
uint8 m_auraSlot;
uint8 m_auraFlags;
uint8 m_auraLevel;
bool m_positive:1;
bool m_permanent:1;
@@ -341,10 +361,6 @@ class TRINITY_DLL_SPEC Aura
int32 m_stackAmount;
private:
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 TRINITY_DLL_SPEC AreaAura : public Aura
Loaded 100 of 171 files, more files were not shown because too many files have changed in this diff. Show more