*Update to Mangos 6938. (Only build for VC9)
--HG-- branch : trunk
This commit is contained in:
1 parent
c81299e653
commit
3cb4e7c716
171 files changed
+11207
-5092
No files matched your search
@@ -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.
|
||||
|
||||
|
||||
@@ -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
@@ -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
@@ -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
|
||||
|
||||
Binary file not shown.
Binary file not shown.
@@ -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);
|
||||
|
||||
|
||||
@@ -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
@@ -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 )
|
||||
|
||||
+6
-6
@@ -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;
|
||||
|
||||
+1
-1
@@ -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;
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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
|
||||
@@ -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
@@ -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()
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
*/
|
||||
@@ -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
|
||||
@@ -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
@@ -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);
|
||||
}
|
||||
@@ -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 },
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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 )
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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);
|
||||
|
||||
@@ -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
@@ -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
|
||||
|
||||
@@ -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
@@ -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
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
@@ -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;
|
||||
|
||||
@@ -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
@@ -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());
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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
@@ -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
@@ -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*/)
|
||||
|
||||
@@ -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
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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*/);
|
||||
|
||||
@@ -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) ;
|
||||
|
||||
@@ -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";
|
||||
|
||||
@@ -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
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
File diff suppressed because it is too large.
Load diff
+262
-134
@@ -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
@@ -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
@@ -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
@@ -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);
|
||||
}
|
||||
@@ -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
File diff suppressed because it is too large.
Load diff
+130
-28
@@ -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
@@ -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
@@ -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
@@ -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;
|
||||
|
||||
@@ -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
@@ -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
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
File diff suppressed because it is too large.
Load diff
+24
-8
@@ -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
Reference in new issue
Block a user