Merge branch 'master' into 310

Conflicts:
	src/game/Level2.cpp
	src/game/PetHandler.cpp
	src/game/Player.cpp
	src/game/Player.h
	src/game/SkillHandler.cpp
This commit is contained in:
tomrus88 2009-03-11 12:22:58 +03:00
commit 31b3ee95ad
163 changed files with 5278 additions and 3233 deletions

View file

@ -12,10 +12,15 @@ cmake_minimum_required (VERSION 2.6)
project (MANGOS_MAP_EXTRACTOR)
add_subdirectory (libmpq)
add_subdirectory (loadlib)
include_directories (${MANGOS_MAP_EXTRACTOR_SOURCE_DIR}/libmpq)
link_directories (${MANGOS_MAP_EXTRACTOR_SOURCE_DIR}/libmpq)
include_directories (${MANGOS_MAP_EXTRACTOR_SOURCE_DIR}/loadlib)
add_executable (ad adt.cpp dbcfile.cpp mpq_libmpq.cpp System.cpp)
link_directories (${MANGOS_MAP_EXTRACTOR_SOURCE_DIR}/libmpq)
link_directories (${MANGOS_MAP_EXTRACTOR_SOURCE_DIR}/loadlib)
add_executable (ad dbcfile.cpp mpq_libmpq.cpp System.cpp)
target_link_libraries (ad libmpq)
target_link_libraries (ad loadlib)

View file

@ -14,10 +14,10 @@
#include "dbcfile.h"
#include "mpq_libmpq.h"
extern unsigned int iRes;
extern ArchiveSet gOpenArchives;
#include "loadlib/adt.h"
#include "loadlib/wdt.h"
bool ConvertADT(char*, char*);
extern ArchiveSet gOpenArchives;
typedef struct
{
@ -25,10 +25,6 @@ typedef struct
uint32 id;
} map_id;
typedef unsigned char uint8;
typedef unsigned short uint16;
typedef unsigned int uint32;
map_id *map_ids;
uint16 *areas;
uint16 *LiqType;
@ -36,18 +32,44 @@ char output_path[128] = ".";
char input_path[128] = ".";
uint32 maxAreaId = 0;
//**************************************************
// Extractor options
//**************************************************
enum Extract
{
EXTRACT_MAP = 1,
EXTRACT_DBC = 2
};
int extract = EXTRACT_MAP | EXTRACT_DBC;
// Select data for extract
int CONF_extract = EXTRACT_MAP | EXTRACT_DBC;
// This option allow limit minimum height to some value (Allow save some memory)
bool CONF_allow_height_limit = true;
float CONF_use_minHeight = -500.0f;
// This option allow use float to int conversion
bool CONF_allow_float_to_int = true;
float CONF_float_to_int8_limit = 2.0f; // Max accuracy = val/256
float CONF_float_to_int16_limit = 2048.0f; // Max accuracy = val/65536
float CONF_flat_height_delta_limit = 0.005f; // If max - min less this value - surface is flat
float CONF_flat_liquid_delta_limit = 0.001f; // If max - min less this value - liquid surface is flat
// List MPQ for extract from
char *CONF_mpq_list[]={
"common.MPQ",
"common-2.MPQ",
"lichking.MPQ",
"expansion.MPQ",
"patch.MPQ",
"patch-2.MPQ",
"patch-3.MPQ",
"patch-4.MPQ",
"patch-5.MPQ",
};
static char* const langs[] = {"enGB", "enUS", "deDE", "esES", "frFR", "koKR", "zhCN", "zhTW", "enCN", "enTW", "esMX", "ruRU" };
#define LANG_COUNT 12
#define ADT_RES 64
void CreateDir( const std::string& Path )
{
#ifdef WIN32
@ -70,7 +92,14 @@ 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-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"\
"-e extract only MAP(1)/DBC(2) - standard: both(3)\n"\
"-f height stored as int (less map size but lost some accuracy) 1 by default\n"\
"Example: %s -f 0 -i \"c:\\games\\game\"", prg, prg);
exit(1);
}
@ -80,8 +109,9 @@ void HandleArgs(int argc, char * arg[])
{
// 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)
// f - use float to int conversion
// h - limit minimum height
if(arg[c][0] != '-')
Usage(arg[0]);
@ -99,11 +129,17 @@ void HandleArgs(int argc, char * arg[])
else
Usage(arg[0]);
break;
case 'f':
if(c + 1 < argc) // all ok
CONF_allow_float_to_int=atoi(arg[(c++) + 1])!=0;
else
Usage(arg[0]);
break;
case 'e':
if(c + 1 < argc) // all ok
{
extract=atoi(arg[(c++) + 1]);
if(!(extract > 0 && extract < 4))
CONF_extract=atoi(arg[(c++) + 1]);
if(!(CONF_extract > 0 && CONF_extract < 4))
Usage(arg[0]);
}
else
@ -165,10 +201,603 @@ void ReadLiquidTypeTableDBC()
printf("Done! (%u LiqTypes loaded)\n", LiqType_count);
}
//
// Adt file convertor function and data
//
// Map file format data
#define MAP_MAGIC 'SPAM'
#define MAP_VERSION_MAGIC '0.1w'
#define MAP_AREA_MAGIC 'AERA'
#define MAP_HEIGTH_MAGIC 'TGHM'
#define MAP_LIQUID_MAGIC 'QILM'
struct map_fileheader{
uint32 mapMagic;
uint32 versionMagic;
uint32 areaMapOffset;
uint32 areaMapSize;
uint32 heightMapOffset;
uint32 heightMapSize;
uint32 liquidMapOffset;
uint32 liquidMapSize;
};
#define MAP_AREA_NO_AREA 0x0001
struct map_areaHeader{
uint32 fourcc;
uint16 flags;
uint16 gridArea;
};
#define MAP_HEIGHT_NO_HIGHT 0x0001
#define MAP_HEIGHT_AS_INT16 0x0002
#define MAP_HEIGHT_AS_INT8 0x0004
struct map_heightHeader{
uint32 fourcc;
uint32 flags;
float gridHeight;
float gridMaxHeight;
};
#define MAP_LIQUID_TYPE_NO_WATER 0x00
#define MAP_LIQUID_TYPE_WATER 0x01
#define MAP_LIQUID_TYPE_OCEAN 0x02
#define MAP_LIQUID_TYPE_MAGMA 0x04
#define MAP_LIQUID_TYPE_SLIME 0x08
#define MAP_LIQUID_TYPE_DARK_WATER 0x10
#define MAP_LIQUID_TYPE_WMO_WATER 0x20
#define MAP_LIQUID_NO_TYPE 0x0001
#define MAP_LIQUID_NO_HIGHT 0x0002
struct map_liquidHeader{
uint32 fourcc;
uint16 flags;
uint16 liquidType;
uint8 offsetX;
uint8 offsetY;
uint8 width;
uint8 height;
float liquidLevel;
};
float selectUInt8StepStore(float maxDiff)
{
return 255 / maxDiff;
}
float selectUInt16StepStore(float maxDiff)
{
return 65535 / maxDiff;
}
// Temporary grid data store
uint16 area_flags[ADT_CELLS_PER_GRID][ADT_CELLS_PER_GRID];
float V8[ADT_GRID_SIZE][ADT_GRID_SIZE];
float V9[ADT_GRID_SIZE+1][ADT_GRID_SIZE+1];
uint16 uint16_V8[ADT_GRID_SIZE][ADT_GRID_SIZE];
uint16 uint16_V9[ADT_GRID_SIZE+1][ADT_GRID_SIZE+1];
uint8 uint8_V8[ADT_GRID_SIZE][ADT_GRID_SIZE];
uint8 uint8_V9[ADT_GRID_SIZE+1][ADT_GRID_SIZE+1];
uint8 liquid_type[ADT_CELLS_PER_GRID][ADT_CELLS_PER_GRID];
bool liquid_show[ADT_GRID_SIZE][ADT_GRID_SIZE];
float liquid_height[ADT_GRID_SIZE+1][ADT_GRID_SIZE+1];
bool ConvertADT(char *filename, char *filename2, int cell_y, int cell_x)
{
ADT_file adt;
if (!adt.loadFile(filename))
return false;
adt_MCIN *cells = adt.a_grid->getMCIN();
if (!cells)
{
printf("Can't find cells in '%s'\n", filename);
return false;
}
memset(liquid_show, 0, sizeof(liquid_show));
memset(liquid_type, 0, sizeof(liquid_type));
// Prepare map header
map_fileheader map;
map.mapMagic = MAP_MAGIC;
map.versionMagic = MAP_VERSION_MAGIC;
// Get area flags data
for (int i=0;i<ADT_CELLS_PER_GRID;i++)
{
for(int j=0;j<ADT_CELLS_PER_GRID;j++)
{
adt_MCNK * cell = cells->getMCNK(i,j);
uint32 areaid = cell->areaid;
if(areaid && areaid <= maxAreaId)
{
if(areas[areaid] != 0xffff)
{
area_flags[i][j] = areas[areaid];
continue;
}
printf("File: filename\nCan't find area flag for areaid %u [%d, %d].\n", filename, areaid, cell->ix, cell->iy);
}
area_flags[i][j] = 0xffff;
}
}
//============================================
// Try pack area data
//============================================
bool fullAreaData = false;
uint32 areaflag = area_flags[0][0];
for (int y=0;y<ADT_CELLS_PER_GRID;y++)
{
for(int x=0;x<ADT_CELLS_PER_GRID;x++)
{
if(area_flags[y][x]!=areaflag)
{
fullAreaData = true;
break;
}
}
}
map.areaMapOffset = sizeof(map);
map.areaMapSize = sizeof(map_areaHeader);
map_areaHeader areaHeader;
areaHeader.fourcc = MAP_AREA_MAGIC;
areaHeader.flags = 0;
if (fullAreaData)
{
areaHeader.gridArea = 0;
map.areaMapSize+=sizeof(area_flags);
}
else
{
areaHeader.flags |= MAP_AREA_NO_AREA;
areaHeader.gridArea = (uint16)areaflag;
}
//
// Get Height map from grid
//
for (int i=0;i<ADT_CELLS_PER_GRID;i++)
{
for(int j=0;j<ADT_CELLS_PER_GRID;j++)
{
adt_MCNK * cell = cells->getMCNK(i,j);
if (!cell)
continue;
// Height values for triangles stored in order:
// 1 2 3 4 5 6 7 8 9
// 10 11 12 13 14 15 16 17
// 18 19 20 21 22 23 24 25 26
// 27 28 29 30 31 32 33 34
// . . . . . . . .
// For better get height values merge it to V9 and V8 map
// V9 height map:
// 1 2 3 4 5 6 7 8 9
// 18 19 20 21 22 23 24 25 26
// . . . . . . . .
// V8 height map:
// 10 11 12 13 14 15 16 17
// 27 28 29 30 31 32 33 34
// . . . . . . . .
// Set map height as grid height
for (int y=0; y <= ADT_CELL_SIZE; y++)
{
int cy = i*ADT_CELL_SIZE + y;
for (int x=0; x <= ADT_CELL_SIZE; x++)
{
int cx = j*ADT_CELL_SIZE + x;
V9[cy][cx]=cell->ypos;
}
}
for (int y=0; y < ADT_CELL_SIZE; y++)
{
int cy = i*ADT_CELL_SIZE + y;
for (int x=0; x < ADT_CELL_SIZE; x++)
{
int cx = j*ADT_CELL_SIZE + x;
V8[cy][cx]=cell->ypos;
}
}
// Get custom height
adt_MCVT *v = cell->getMCVT();
if (!v)
continue;
// get V9 height map
for (int y=0; y <= ADT_CELL_SIZE; y++)
{
int cy = i*ADT_CELL_SIZE + y;
for (int x=0; x <= ADT_CELL_SIZE; x++)
{
int cx = j*ADT_CELL_SIZE + x;
V9[cy][cx]+=v->height_map[y*(ADT_CELL_SIZE*2+1)+x];
}
}
// get V8 height map
for (int y=0; y < ADT_CELL_SIZE; y++)
{
int cy = i*ADT_CELL_SIZE + y;
for (int x=0; x < ADT_CELL_SIZE; x++)
{
int cx = j*ADT_CELL_SIZE + x;
V8[cy][cx]+=v->height_map[y*(ADT_CELL_SIZE*2+1)+ADT_CELL_SIZE+1+x];
}
}
}
}
//============================================
// Try pack height data
//============================================
float maxHeight = -20000;
float minHeight = 20000;
for (int y=0; y<ADT_GRID_SIZE; y++)
{
for(int x=0;x<ADT_GRID_SIZE;x++)
{
float h = V8[y][x];
if (maxHeight < h) maxHeight = h;
if (minHeight > h) minHeight = h;
}
}
for (int y=0; y<=ADT_GRID_SIZE; y++)
{
for(int x=0;x<=ADT_GRID_SIZE;x++)
{
float h = V9[y][x];
if (maxHeight < h) maxHeight = h;
if (minHeight > h) minHeight = h;
}
}
// Check for allow limit minimum height (not store height in deep ochean - allow save some memory)
if (CONF_allow_height_limit && minHeight < CONF_use_minHeight)
{
for (int y=0; y<ADT_GRID_SIZE; y++)
for(int x=0;x<ADT_GRID_SIZE;x++)
if (V8[y][x] < CONF_use_minHeight)
V8[y][x] = CONF_use_minHeight;
for (int y=0; y<=ADT_GRID_SIZE; y++)
for(int x=0;x<=ADT_GRID_SIZE;x++)
if (V9[y][x] < CONF_use_minHeight)
V9[y][x] = CONF_use_minHeight;
if (minHeight < CONF_use_minHeight)
minHeight = CONF_use_minHeight;
if (maxHeight < CONF_use_minHeight)
maxHeight = CONF_use_minHeight;
}
map.heightMapOffset = map.areaMapOffset + map.areaMapSize;
map.heightMapSize = sizeof(map_heightHeader);
map_heightHeader heightHeader;
heightHeader.fourcc = MAP_HEIGTH_MAGIC;
heightHeader.flags = 0;
heightHeader.gridHeight = minHeight;
heightHeader.gridMaxHeight = maxHeight;
if (maxHeight == minHeight)
heightHeader.flags |=MAP_HEIGHT_NO_HIGHT;
// Not need store if flat surface
if (CONF_allow_float_to_int && (maxHeight - minHeight) < CONF_flat_height_delta_limit)
heightHeader.flags |=MAP_HEIGHT_NO_HIGHT;
// Try store as packed in uint16 or uint8 values
if (!(heightHeader.flags&MAP_HEIGHT_NO_HIGHT))
{
float step;
// Try Store as uint values
if (CONF_allow_float_to_int)
{
float diff = maxHeight - minHeight;
if (diff < CONF_float_to_int8_limit) // As uint8 (max accuracy = CONF_float_to_int8_limit/256)
{
heightHeader.flags|=MAP_HEIGHT_AS_INT8;
step = selectUInt8StepStore(diff);
}
else if (diff<CONF_float_to_int16_limit) // As uint16 (max accuracy = CONF_float_to_int16_limit/65536)
{
heightHeader.flags|=MAP_HEIGHT_AS_INT16;
step = selectUInt16StepStore(diff);
}
}
// Pack it to int values if need
if (heightHeader.flags&MAP_HEIGHT_AS_INT8)
{
for (int y=0; y<ADT_GRID_SIZE; y++)
for(int x=0;x<ADT_GRID_SIZE;x++)
uint8_V8[y][x] = uint8((V8[y][x] - minHeight) * step + 0.5f);
for (int y=0; y<=ADT_GRID_SIZE; y++)
for(int x=0;x<=ADT_GRID_SIZE;x++)
uint8_V9[y][x] = uint8((V9[y][x] - minHeight) * step + 0.5f);
map.heightMapSize+= sizeof(uint8_V9) + sizeof(uint8_V8);
}
else if (heightHeader.flags&MAP_HEIGHT_AS_INT16)
{
for (int y=0; y<ADT_GRID_SIZE; y++)
for(int x=0;x<ADT_GRID_SIZE;x++)
uint16_V8[y][x] = uint16((V8[y][x] - minHeight) * step + 0.5f);
for (int y=0; y<=ADT_GRID_SIZE; y++)
for(int x=0;x<=ADT_GRID_SIZE;x++)
uint16_V9[y][x] = uint16((V9[y][x] - minHeight) * step + 0.5f);
map.heightMapSize+= sizeof(uint16_V9) + sizeof(uint16_V8);
}
else
map.heightMapSize+= sizeof(V9) + sizeof(V8);
}
// Get liquid map for grid (in WOTLK used MH2O chunk)
adt_MH2O * h2o = adt.a_grid->getMH2O();
if (h2o)
{
for (int i=0;i<ADT_CELLS_PER_GRID;i++)
{
for(int j=0;j<ADT_CELLS_PER_GRID;j++)
{
adt_liquid_header *h = h2o->getLiquidData(i,j);
if (!h)
continue;
int count = 0;
uint64 show = h2o->getLiquidShowMap(h);
for (int y=0; y < h->height;y++)
{
int cy = i*ADT_CELL_SIZE + y + h->yOffset;
for (int x=0; x < h->width; x++)
{
int cx = j*ADT_CELL_SIZE + x + h->xOffset;
if (show & 1)
{
liquid_show[cy][cx] = true;
++count;
}
show>>=1;
}
}
uint32 type = LiqType[h->liquidType];
switch (type)
{
case LIQUID_TYPE_WATER: liquid_type[i][j] |= MAP_LIQUID_TYPE_WATER; break;
case LIQUID_TYPE_OCEAN: liquid_type[i][j] |= MAP_LIQUID_TYPE_OCEAN; break;
case LIQUID_TYPE_MAGMA: liquid_type[i][j] |= MAP_LIQUID_TYPE_MAGMA; break;
case LIQUID_TYPE_SLIME: liquid_type[i][j] |= MAP_LIQUID_TYPE_SLIME; break;
default:
printf("\nCan't find Liquid type %u for map %s\nchunk %d,%d\n", h->liquidType, filename, i, j);
break;
}
// Dark water detect
if (type == LIQUID_TYPE_OCEAN)
{
uint8 *lm = h2o->getLiquidLightMap(h);
if (!lm)
liquid_type[i][j]|=MAP_LIQUID_TYPE_DARK_WATER;
}
if (!count && liquid_type[i][j])
printf("Wrong liquid detect in MH2O chunk");
float *height = h2o->getLiquidHeightMap(h);
int pos = 0;
for (int y=0; y<=h->height;y++)
{
int cy = i*ADT_CELL_SIZE + y + h->yOffset;
for (int x=0; x<= h->width; x++)
{
int cx = j*ADT_CELL_SIZE + x + h->xOffset;
if (height)
liquid_height[cy][cx] = height[pos];
else
liquid_height[cy][cx] = h->heightLevel1;
pos++;
}
}
}
}
}
else
{
// Get from MCLQ chunk (old)
for (int i=0;i<ADT_CELLS_PER_GRID;i++)
{
for(int j=0;j<ADT_CELLS_PER_GRID;j++)
{
adt_MCNK *cell = cells->getMCNK(i, j);
if (!cell)
continue;
adt_MCLQ *liquid = cell->getMCLQ();
int count = 0;
if (!liquid || cell->sizeMCLQ <= 8)
continue;
for (int y=0; y < ADT_CELL_SIZE; y++)
{
int cy = i*ADT_CELL_SIZE + y;
for (int x=0; x < ADT_CELL_SIZE; x++)
{
int cx = j*ADT_CELL_SIZE + x;
if (liquid->flags[y][x] != 0x0F)
{
liquid_show[cy][cx] = true;
if (liquid->flags[y][x]&(1<<7))
liquid_type[i][j]|=MAP_LIQUID_TYPE_DARK_WATER;
++count;
}
}
}
uint32 c_flag = cell->flags;
if(c_flag & (1<<2))
liquid_type[i][j]|=MAP_LIQUID_TYPE_WATER; // water
if(c_flag & (1<<3))
liquid_type[i][j]|=MAP_LIQUID_TYPE_OCEAN; // ochean
if(c_flag & (1<<4))
liquid_type[i][j]|=MAP_LIQUID_TYPE_MAGMA; // magma/slime
if (!count && liquid_type[i][j])
printf("Wrong liquid detect in MCLQ chunk");
for (int y=0; y <= ADT_CELL_SIZE; y++)
{
int cy = i*ADT_CELL_SIZE + y;
for (int x=0; x<= ADT_CELL_SIZE; x++)
{
int cx = j*ADT_CELL_SIZE + x;
liquid_height[cy][cx] = liquid->liquid[y][x].height;
}
}
}
}
}
//============================================
// Pack liquid data
//============================================
uint8 type = liquid_type[0][0];
bool fullType = false;
for (int y=0;y<ADT_CELLS_PER_GRID;y++)
{
for(int x=0;x<ADT_CELLS_PER_GRID;x++)
{
if (liquid_type[y][x]!=type)
{
fullType = true;
y = ADT_CELLS_PER_GRID;
break;
}
}
}
map_liquidHeader liquidHeader;
// no water data (if all grid have 0 liquid type)
if (type == 0 && !fullType)
{
// No liquid data
map.liquidMapOffset = 0;
map.liquidMapSize = 0;
}
else
{
int minX = 255, minY = 255;
int maxX = 0, maxY = 0;
maxHeight = -20000;
minHeight = 20000;
for (int y=0; y<ADT_GRID_SIZE; y++)
{
for(int x=0; x<ADT_GRID_SIZE; x++)
{
if (liquid_show[y][x])
{
if (minX > x) minX = x;
if (maxX < x) maxX = x;
if (minY > y) minY = y;
if (maxY < y) maxY = y;
float h = liquid_height[y][x];
if (maxHeight < h) maxHeight = h;
if (minHeight > h) minHeight = h;
}
else
liquid_height[y][x] = CONF_use_minHeight;
}
}
map.liquidMapOffset = map.heightMapOffset + map.heightMapSize;
map.liquidMapSize = sizeof(map_liquidHeader);
liquidHeader.fourcc = MAP_LIQUID_MAGIC;
liquidHeader.flags = 0;
liquidHeader.liquidType = 0;
liquidHeader.offsetX = minX;
liquidHeader.offsetY = minY;
liquidHeader.width = maxX - minX + 1;
liquidHeader.height = maxY - minY + 1;
liquidHeader.liquidLevel = minHeight;
if (maxHeight == minHeight)
liquidHeader.flags|=MAP_LIQUID_NO_HIGHT;
// Not need store if flat surface
if (CONF_allow_float_to_int && (maxHeight - minHeight) < CONF_flat_liquid_delta_limit)
liquidHeader.flags|=MAP_LIQUID_NO_HIGHT;
if (!fullType)
liquidHeader.flags|=MAP_LIQUID_NO_TYPE;
if (liquidHeader.flags&MAP_LIQUID_NO_TYPE)
liquidHeader.liquidType = type;
else
map.liquidMapSize+=sizeof(liquid_type);
if (!(liquidHeader.flags&MAP_LIQUID_NO_HIGHT))
map.liquidMapSize+=sizeof(float)*liquidHeader.width*liquidHeader.height;
}
// Ok all data prepared - store it
FILE *output=fopen(filename2, "wb");
if(!output)
{
printf("Can't create the output file '%s'\n", filename2);
return false;
}
fwrite(&map, sizeof(map), 1, output);
// Store area data
fwrite(&areaHeader, sizeof(areaHeader), 1, output);
if (!(areaHeader.flags&MAP_AREA_NO_AREA))
fwrite(area_flags, sizeof(area_flags), 1, output);
// Store height data
fwrite(&heightHeader, sizeof(heightHeader), 1, output);
if (!(heightHeader.flags&MAP_HEIGHT_NO_HIGHT))
{
if (heightHeader.flags&MAP_HEIGHT_AS_INT16)
{
fwrite(uint16_V9, sizeof(uint16_V9), 1, output);
fwrite(uint16_V8, sizeof(uint16_V8), 1, output);
}
else if (heightHeader.flags&MAP_HEIGHT_AS_INT8)
{
fwrite(uint8_V9, sizeof(uint8_V9), 1, output);
fwrite(uint8_V8, sizeof(uint8_V8), 1, output);
}
else
{
fwrite(V9, sizeof(V9), 1, output);
fwrite(V8, sizeof(V8), 1, output);
}
}
// Store liquid data if need
if (map.liquidMapOffset)
{
fwrite(&liquidHeader, sizeof(liquidHeader), 1, output);
if (!(liquidHeader.flags&MAP_LIQUID_NO_TYPE))
fwrite(liquid_type, sizeof(liquid_type), 1, output);
if (!(liquidHeader.flags&MAP_LIQUID_NO_HIGHT))
{
for (int y=0; y<liquidHeader.height;y++)
fwrite(&liquid_height[y+liquidHeader.offsetY][liquidHeader.offsetX], sizeof(float), liquidHeader.width, output);
}
}
fclose(output);
return true;
}
void ExtractMapsFromMpq()
{
char mpq_filename[1024];
char output_filename[1024];
char mpq_map_name[1024];
printf("Extracting maps...\n");
@ -177,35 +806,41 @@ void ExtractMapsFromMpq()
ReadAreaTableDBC();
ReadLiquidTypeTableDBC();
unsigned int total = map_count * ADT_RES * ADT_RES;
unsigned int done = 0;
std::string path = output_path;
path += "/maps/";
CreateDir(path);
for(uint32 x = 0; x < ADT_RES; ++x)
printf("Convert map files\n");
for(uint32 z = 0; z < map_count; ++z)
{
for(uint32 y = 0; y < ADT_RES; ++y)
printf("Extract %s (%d/%d) \n", map_ids[z].name, z+1, map_count);
// Loadup map grid data
sprintf(mpq_map_name, "World\\Maps\\%s\\%s.wdt", map_ids[z].name, map_ids[z].name);
WDT_file wdt;
if (!wdt.loadFile(mpq_map_name, false))
{
for(uint32 z = 0; z < map_count; ++z)
// printf("Error loading %s map wdt data\n", map_ids[z].name);
continue;
}
for(uint32 y = 0; y < WDT_MAP_SIZE; ++y)
{
for(uint32 x = 0; x < WDT_MAP_SIZE; ++x)
{
if (!wdt.main->adt_list[y][x].exist)
continue;
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++;
ConvertADT(mpq_filename, output_filename, y, x);
}
// draw progress bar
printf("Processing........................%d%%\r", (100 * done) / total);
printf("Processing........................%d%%\r", (100 * (y+1)) / WDT_MAP_SIZE);
}
}
delete [] areas;
delete [] map_ids;
}
//bool WMO(char* filename);
void ExtractDBCFiles(int locale, bool basicLocale)
{
printf("Extracting dbc files...\n");
@ -277,21 +912,10 @@ void LoadLocaleMPQFiles(int const locale)
void LoadCommonMPQFiles()
{
char filename[512];
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);
for(int i = 1; i < 5; ++i)
int count = sizeof(CONF_mpq_list)/sizeof(char*);
for(int i = 0; i < count; ++i)
{
char ext[3] = "";
if(i > 1)
sprintf(ext, "-%i", i);
sprintf(filename, "%s/Data/patch%s.MPQ", input_path, ext);
sprintf(filename, "%s/Data/%s", input_path, CONF_mpq_list[i]);
if(FileExists(filename))
new MPQArchive(filename);
}
@ -323,7 +947,7 @@ int main(int argc, char * arg[])
//Open MPQs
LoadLocaleMPQFiles(i);
if((extract & EXTRACT_DBC) == 0)
if((CONF_extract & EXTRACT_DBC) == 0)
{
FirstLocale = i;
break;
@ -349,7 +973,7 @@ int main(int argc, char * arg[])
return 0;
}
if (extract & EXTRACT_MAP)
if (CONF_extract & EXTRACT_MAP)
{
printf("Using locale: %s\n", langs[FirstLocale]);

View file

@ -213,7 +213,15 @@
Filter="cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
>
<File
RelativePath=".\adt.cpp"
RelativePath=".\loadlib\loadlib.cpp"
>
</File>
<File
RelativePath=".\loadlib\adt.cpp"
>
</File>
<File
RelativePath=".\loadlib\wdt.cpp"
>
</File>
<File

View file

@ -218,13 +218,17 @@
Filter="cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
>
<File
RelativePath=".\adt.cpp"
RelativePath=".\loadlib\adt.cpp"
>
</File>
<File
RelativePath=".\dbcfile.cpp"
>
</File>
<File
RelativePath=".\loadlib\loadlib.cpp"
>
</File>
<File
RelativePath=".\mpq_libmpq.cpp"
>
@ -253,6 +257,10 @@
/>
</FileConfiguration>
</File>
<File
RelativePath=".\loadlib\wdt.cpp"
>
</File>
<Filter
Name="libmpq"
>

View file

@ -216,7 +216,15 @@
Filter="cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
>
<File
RelativePath=".\adt.cpp"
RelativePath=".\loadlib\loadlib.cpp"
>
</File>
<File
RelativePath=".\loadlib\adt.cpp"
>
</File>
<File
RelativePath=".\loadlib\wdt.cpp"
>
</File>
<File

Binary file not shown.

View file

@ -1,380 +0,0 @@
#define _CRT_SECURE_NO_DEPRECATE
#ifdef WIN32
#include <windows.h>
#endif
#include <string.h>
#include <stdio.h>
#include <math.h>
#include <string>
#include <map>
#include <vector>
#include <set>
#include "adt.h"
#include "mpq_libmpq.h"
extern uint16 *areas;
extern uint16 *LiqType;
extern uint32 maxAreaId;
vec wmoc;
Cell *cell;
mcell *mcells;
int holetab_h[4] = {0x1111, 0x2222, 0x4444, 0x8888};
int holetab_v[4] = {0x000F, 0x00F0, 0x0F00, 0xF000};
bool LoadADT(char* filename)
{
size_t size;
MPQFile mf(filename);
if(mf.isEof())
{
//printf("No such file %s\n", filename);
return false;
}
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];
chunk_num = 0;
k = 0;
m = 0;
while (!mf.isEof())
{
uint32 fourcc;
mf.read(&fourcc, 4);
mf.read(&size, 4);
size_t nextpos = mf.getPos() + size;
//if(fourcc==0x4d484452) // MHDR header
//if(fourcc==0x4d564552) // MVER
if(fourcc == 0x4d43494e) // MCIN
{
for (uint32 i = 0; i < 256; ++i)
{
mf.read(&mcnk_offsets[i], 4);
mf.read(&mcnk_sizes[i], 4);
mf.seekRelative(8);
}
}
//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)
{
mf.read(LiqOffsData, 0x0C);
header_pos = mf.getPos();
if(LiqOffsData->offsData1 != 0) // åñëè äàííûå â Data1 î âîäå åñòü, òî èõ íàäî êîíâåðòèðîâàòü
{
// ïåðåõîäèì ïî ñìåùåíèþ èç offsData1 ÎÒ ÍÀ×ÀËÀ êóñêà
mf.seek(base_pos + LiqOffsData->offsData1);
mf.read(LiqChunkData1, 0x18); // ñ÷èòûâàåì ñàìè äàííûå â ñòðóêòóðó òèïà MH2O_Data1
// çàíîñèì äàííûå ôëàãà äëÿ êóñêà
if(LiqType[LiqChunkData1->LiquidTypeId] == 0xffff)
printf("\nCan't find Liquid type for map %s\nchunk %d\n", filename, chunk_num);
else if(LiqType[LiqChunkData1->LiquidTypeId] == LIQUID_TYPE_WATER || LiqType[LiqChunkData1->LiquidTypeId] == LIQUID_TYPE_OCEAN)
MapLiqFlag[chunk_num] |= 1; // water/ocean
else if(LiqType[LiqChunkData1->LiquidTypeId] == LIQUID_TYPE_MAGMA || LiqType[LiqChunkData1->LiquidTypeId] == LIQUID_TYPE_SLIME)
MapLiqFlag[chunk_num] |= 2; // magma/slime
// ïðåäâàðèòåëüíî çàïîëíÿåì âåñü êóñîê äàííûìè - íåò âîäû
for(int j = 0; j < 81; ++j)
{
ChunkLiqHeight[j] = -999999; // no liquid/water
}
// òåïåðü âû÷èñëÿåì òå ÷òî ñ âîäîé è ïåðåçàïèñûâàåì èõ â êóñêå
for(int b = 0; b <= LiqChunkData1->height; ++b)
{
for(int c = LiqChunkData1->xOffset; c <= (LiqChunkData1->xOffset + LiqChunkData1->width); ++c)
{
int n = (9 * (LiqChunkData1->yOffset + b)) + c;
ChunkLiqHeight[n] = LiqChunkData1->heightLevel1;
}
}
mf.seek(header_pos); // è íå çàáûòü âåðíóòüñÿ íà èñõîäíóþ ïîçèöèþ èìåííî Â ÕÈÄÅÐÅ
}
else // åñëè äàííûõ â Data1 íåò, òî íàäî çàïîëíèòü âåñü êóñîê, íî äàííûìè - íåò âîäû
{
for(int j = 0; j < 81; ++j)
ChunkLiqHeight[j] = -999999; // no liquid/water
}
if(!(chunk_num % 16))
m = 1024 * (chunk_num / 16); // ñìåùåíèå ïî ðÿäàì êóñêîâ ñ ïåðåêðûòèåì = 1024
k = m + (chunk_num % 16) * 8; // óñòàíàâëèâàåìñÿ íà íà÷àëüíûé èíäåêñ äëÿ çàïîëíåíèÿ ðÿäà
// çàíîñèì äàííûå êóñêà â ìàññèâ äëÿ êàðòû, ñ ïåðåêðûòèåì è îáðåçàíèåì êóñêîâ òê äàííûõ 81
// ýòî àíàëîã ñòàðîãî îáðåçàíèÿ ãðàíè÷íûõ ïðàâûõ-áîêîâûõ è íèæíèõ äàííûõ
for(int p = 0; p < 72; p += 9) // íèæíèå 8 íå çàíîñèì òê îíè äóáëèðóåòñÿ ñëåä êóñêîì
{
for(int s = 0; s < 8; ++s) // 9 çíà÷åíèå â ñòðîêå íå çàíîñèì òê îíî äóáëèðóåòñÿ ñëåä êóñêîì, à â ïðàâûõ-áîêîâûõ îáðåçàåòñÿ äëÿ 128õ128
{
MapLiqHeight[k] = ChunkLiqHeight[p + s];
++k;
}
k = k + 120;
}
}
delete LiqOffsData;
delete LiqChunkData1;
delete []ChunkLiqHeight;
}
//case 0x4d434e4b: // MCNK
//case 0x4d46424f: // MFBO new in BC
//case 0x4d545846: // MTXF new in WotLK
mf.seek(nextpos);
}
//printf("Loading chunks info\n");
// read individual map chunks
chunk_num = 0;
k = 0;
m = 0;
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]));
++chunk_num;
}
}
mf.close();
return true;
}
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;
}
inline void LoadMapChunk(MPQFile &mf, chunk *_chunk)
{
float h;
uint32 fourcc;
uint32 size;
MapChunkHeader header;
mf.seekRelative(4);
mf.read(&size, 4);
size_t lastpos = mf.getPos() + size;
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;
int chunkflags = header.flags;
//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(&size, 4);
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)
{
mf.read(&h, 4);
float z = h + ybase;
if (j % 2)
{
if(isHole(header.holes, i, j))
_chunk->v8[i][j / 2] = -1000;
else
_chunk->v8[i][j / 2] = z;
}
else
{
if(isHole(header.holes, i, j))
_chunk->v9[i][j / 2] = -1000;
else
_chunk->v9[i][j / 2] = z;
}
if(z > zmax) zmax = z;
//if(z < zmin) zmin = z;
}
}
}
else if(fourcc == 0x4d434e52) // MCNR
{
nextpos = mf.getPos() + 0x1C0; // size fix
}
else if(fourcc == 0x4d434c51) // íå áóäåì ó÷èòûâàòü åñëè óæå áûëè äàííûå â MH2O, ïåðåñòðàõîâêà :) // MCLQ
{
// liquid / water level
char fcc1[5];
mf.read(fcc1, 4);
flipcc(fcc1);
fcc1[4] = 0;
float *ChunkLiqHeight = new float[81];
if (!strcmp(fcc1, "MCSE"))
{
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);
if(liq.height > maxheight)
ChunkLiqHeight[j] = -999999;
else
ChunkLiqHeight[j] = h;
}
if(chunkflags & 4 || chunkflags & 8)
MapLiqFlag[chunk_num] |= 1; // water
if(chunkflags & 16)
MapLiqFlag[chunk_num] |= 2; // magma/slime
}
// çàïîëíåì òàê æå êàê â MH2O
if(!(chunk_num % 16))
m = 1024 * (chunk_num / 16);
k = m + (chunk_num % 16) * 8;
for(int p = 0; p < 72; p += 9)
{
for(int s = 0; s < 8; ++s)
{
MapLiqHeight[k] = ChunkLiqHeight[p + s];
++k;
}
k = k + 120;
}
delete []ChunkLiqHeight;
break;
}
mf.seek(nextpos);
}
}
inline void TransformData()
{
cell = new Cell;
for(uint32 x = 0; x < 128; ++x)
{
for(uint32 y = 0; y < 128; ++y)
{
cell->v8[y][x] = (float)mcells->ch[x / 8][y / 8].v8[x % 8][y % 8];
cell->v9[y][x] = (float)mcells->ch[x / 8][y / 8].v9[x % 8][y % 8];
}
// extra 1 point on bounds
cell->v9[128][x] = (float)mcells->ch[x / 8][15].v9[x % 8][8];
// x == y
cell->v9[x][128] = (float)mcells->ch[15][x / 8].v9[8][x % 8];
}
// and the last 1
cell->v9[128][128] = (float)mcells->ch[15][15].v9[8][8];
delete mcells;
}
const char MAP_MAGIC[] = "MAP_3.00";
bool ConvertADT(char *filename, char *filename2)
{
if(!LoadADT(filename))
return false;
FILE *output=fopen(filename2, "wb");
if(!output)
{
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);
for(uint32 x = 0; x < 16; ++x)
{
for(uint32 y = 0; y < 16; ++y)
{
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);
fwrite(&areas[mcells->ch[y][x].area_id], 1, 2, output);
}
else
{
uint16 flag = 0xffff;
fwrite(&flag, 1, 2, output);
}
}
}
fwrite(MapLiqFlag, 1, 256, output);
delete [] MapLiqFlag;
fwrite(MapLiqHeight, sizeof(float), 16384, output);
delete [] MapLiqHeight;
TransformData();
fwrite(&cell->v9, 1, sizeof(cell->v9), output);
fwrite(&cell->v8, 1, sizeof(cell->v8), output);
fclose(output);
delete cell;
return true;
}

View file

@ -1,128 +0,0 @@
#ifndef ADT_H
#define ADT_H
#define TILESIZE (533.33333f)
#define CHUNKSIZE ((TILESIZE) / 16.0f)
#define UNITSIZE (CHUNKSIZE / 8.0f)
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;
} 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;
float *MapLiqHeight;
uint8 *MapLiqFlag;
uint32 k, m, chunk_num;
void LoadMapChunk(MPQFile &, chunk*);
#endif

View file

@ -0,0 +1,13 @@
# Copyright (C) 2005-2009 MaNGOS project <http://getmangos.com/>
#
# This file is free software; as a special exception the author gives
# unlimited permission to copy and/or distribute it, with or without
# modifications, as long as this notice is preserved.
#
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY, to the extent permitted by law; without even the
# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
add_library (loadlib loadlib.cpp adt.cpp wdt.cpp)
# link loadlib with zlib
target_link_libraries (loadlib z)

View file

@ -0,0 +1,131 @@
#define _CRT_SECURE_NO_DEPRECATE
#include "adt.h"
// Helper
int holetab_h[4] = {0x1111, 0x2222, 0x4444, 0x8888};
int holetab_v[4] = {0x000F, 0x00F0, 0x0F00, 0xF000};
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;
}
//
// Adt file loader class
//
ADT_file::ADT_file()
{
a_grid = 0;
}
ADT_file::~ADT_file()
{
free();
}
void ADT_file::free()
{
a_grid = 0;
FileLoader::free();
}
//
// Adt file check function
//
bool ADT_file::prepareLoadedData()
{
// Check parent
if (!FileLoader::prepareLoadedData())
return false;
// Check and prepare MHDR
a_grid = (adt_MHDR *)(GetData()+8+version->size);
if (!a_grid->prepareLoadedData())
return false;
return true;
}
bool adt_MHDR::prepareLoadedData()
{
if (fcc != 'MHDR')
return false;
if (size!=sizeof(adt_MHDR)-8)
return false;
// Check and prepare MCIN
if (offsMCIN && !getMCIN()->prepareLoadedData())
return false;
// Check and prepare MH2O
if (offsMH2O && !getMH2O()->prepareLoadedData())
return false;
return true;
}
bool adt_MCIN::prepareLoadedData()
{
if (fcc != 'MCIN')
return false;
// Check cells data
for (int i=0; i<ADT_CELLS_PER_GRID;i++)
for (int j=0; j<ADT_CELLS_PER_GRID;j++)
if (cells[i][j].offsMCNK && !getMCNK(i,j)->prepareLoadedData())
return false;
return true;
}
bool adt_MH2O::prepareLoadedData()
{
if (fcc != 'MH2O')
return false;
// Check liquid data
// for (int i=0; i<ADT_CELLS_PER_GRID;i++)
// for (int j=0; j<ADT_CELLS_PER_GRID;j++)
return true;
}
bool adt_MCNK::prepareLoadedData()
{
if (fcc != 'MCNK')
return false;
// Check height map
if (offsMCVT && !getMCVT()->prepareLoadedData())
return false;
// Check liquid data
if (offsMCLQ && !getMCLQ()->prepareLoadedData())
return false;
return true;
}
bool adt_MCVT::prepareLoadedData()
{
if (fcc != 'MCVT')
return false;
if (size != sizeof(adt_MCVT)-8)
return false;
return true;
}
bool adt_MCLQ::prepareLoadedData()
{
if (fcc != 'MCLQ')
return false;
return true;
}

View file

@ -0,0 +1,289 @@
#ifndef ADT_H
#define ADT_H
#include "loadlib.h"
#define TILESIZE (533.33333f)
#define CHUNKSIZE ((TILESIZE) / 16.0f)
#define UNITSIZE (CHUNKSIZE / 8.0f)
enum LiquidType
{
LIQUID_TYPE_WATER = 0,
LIQUID_TYPE_OCEAN = 1,
LIQUID_TYPE_MAGMA = 2,
LIQUID_TYPE_SLIME = 3
};
//**************************************************************************************
// ADT file class
//**************************************************************************************
#define ADT_CELLS_PER_GRID 16
#define ADT_CELL_SIZE 8
#define ADT_GRID_SIZE (ADT_CELLS_PER_GRID*ADT_CELL_SIZE)
//
// Adt file height map chunk
//
class adt_MCVT
{
union{
uint32 fcc;
char fcc_txt[4];
};
uint32 size;
public:
float height_map[(ADT_CELL_SIZE+1)*(ADT_CELL_SIZE+1)+ADT_CELL_SIZE*ADT_CELL_SIZE];
bool prepareLoadedData();
};
//
// Adt file liquid map chunk (old)
//
class adt_MCLQ
{
union{
uint32 fcc;
char fcc_txt[4];
};
uint32 size;
public:
float height1;
float height2;
struct liquid_data{
uint32 light;
float height;
} liquid[ADT_CELL_SIZE+1][ADT_CELL_SIZE+1];
// 1<<0 - ochen
// 1<<1 - lava/slime
// 1<<2 - water
// 1<<6 - all water
// 1<<7 - dark water
// == 0x0F - not show liquid
uint8 flags[ADT_CELL_SIZE][ADT_CELL_SIZE];
uint8 data[84];
bool prepareLoadedData();
};
//
// Adt file cell chunk
//
class adt_MCNK
{
union{
uint32 fcc;
char fcc_txt[4];
};
uint32 size;
public:
uint32 flags;
uint32 ix;
uint32 iy;
uint32 nLayers;
uint32 nDoodadRefs;
uint32 offsMCVT; // height map
uint32 offsMCNR; // Normal vectors for each vertex
uint32 offsMCLY; // Texture layer definitions
uint32 offsMCRF; // A list of indices into the parent file's MDDF chunk
uint32 offsMCAL; // Alpha maps for additional texture layers
uint32 sizeMCAL;
uint32 offsMCSH; // Shadow map for static shadows on the terrain
uint32 sizeMCSH;
uint32 areaid;
uint32 nMapObjRefs;
uint32 holes;
uint16 s[2];
uint32 data1;
uint32 data2;
uint32 data3;
uint32 predTex;
uint32 nEffectDoodad;
uint32 offsMCSE;
uint32 nSndEmitters;
uint32 offsMCLQ; // Liqid level (old)
uint32 sizeMCLQ; //
float zpos;
float xpos;
float ypos;
uint32 offsMCCV; // offsColorValues in WotLK
uint32 props;
uint32 effectId;
bool prepareLoadedData();
adt_MCVT *getMCVT()
{
if (offsMCVT)
return (adt_MCVT *)((uint8 *)this + offsMCVT);
return 0;
}
adt_MCLQ *getMCLQ()
{
if (offsMCLQ)
return (adt_MCLQ *)((uint8 *)this + offsMCLQ);
return 0;
}
};
//
// Adt file grid chunk
//
class adt_MCIN
{
union{
uint32 fcc;
char fcc_txt[4];
};
uint32 size;
public:
struct adt_CELLS{
uint32 offsMCNK;
uint32 size;
uint32 flags;
uint32 asyncId;
} cells[ADT_CELLS_PER_GRID][ADT_CELLS_PER_GRID];
bool prepareLoadedData();
// offset from begin file (used this-84)
adt_MCNK *getMCNK(int x, int y)
{
if (cells[x][y].offsMCNK)
return (adt_MCNK *)((uint8 *)this + cells[x][y].offsMCNK - 84);
return 0;
}
};
#define ADT_LIQUID_HEADER_FULL_LIGHT 0x01
#define ADT_LIQUID_HEADER_NO_HIGHT 0x02
struct adt_liquid_header{
uint16 liquidType; // Index from LiquidType.dbc
uint16 formatFlags;
float heightLevel1;
float heightLevel2;
uint8 xOffset;
uint8 yOffset;
uint8 width;
uint8 height;
uint32 offsData2a;
uint32 offsData2b;
};
//
// Adt file liquid data chunk (new)
//
class adt_MH2O
{
public:
union{
uint32 fcc;
char fcc_txt[4];
};
uint32 size;
struct adt_LIQUID{
uint32 offsData1;
uint32 used;
uint32 offsData2;
} liquid[ADT_CELLS_PER_GRID][ADT_CELLS_PER_GRID];
bool prepareLoadedData();
adt_liquid_header *getLiquidData(int x, int y)
{
if (liquid[x][y].used && liquid[x][y].offsData1)
return (adt_liquid_header *)((uint8*)this + 8 + liquid[x][y].offsData1);
return 0;
}
float *getLiquidHeightMap(adt_liquid_header *h)
{
if (h->formatFlags & ADT_LIQUID_HEADER_NO_HIGHT)
return 0;
if (h->offsData2b)
return (float *)((uint8*)this + 8 + h->offsData2b);
return 0;
}
uint8 *getLiquidLightMap(adt_liquid_header *h)
{
if (h->formatFlags&ADT_LIQUID_HEADER_FULL_LIGHT)
return 0;
if (h->offsData2b)
{
if (h->formatFlags & ADT_LIQUID_HEADER_NO_HIGHT)
return (uint8 *)((uint8*)this + 8 + h->offsData2b);
return (uint8 *)((uint8*)this + 8 + h->offsData2b + (h->width+1)*(h->height+1)*4);
}
return 0;
}
uint32 *getLiquidFullLightMap(adt_liquid_header *h)
{
if (!(h->formatFlags&ADT_LIQUID_HEADER_FULL_LIGHT))
return 0;
if (h->offsData2b)
{
if (h->formatFlags & ADT_LIQUID_HEADER_NO_HIGHT)
return (uint32 *)((uint8*)this + 8 + h->offsData2b);
return (uint32 *)((uint8*)this + 8 + h->offsData2b + (h->width+1)*(h->height+1)*4);
}
return 0;
}
uint64 getLiquidShowMap(adt_liquid_header *h)
{
if (h->offsData2a)
return *((uint64 *)((uint8*)this + 8 + h->offsData2a));
else
return 0xFFFFFFFFFFFFFFFFLL;
}
};
//
// Adt file header chunk
//
class adt_MHDR
{
union{
uint32 fcc;
char fcc_txt[4];
};
uint32 size;
uint32 pad;
uint32 offsMCIN; // MCIN
uint32 offsTex; // MTEX
uint32 offsModels; // MMDX
uint32 offsModelsIds; // MMID
uint32 offsMapObejcts; // MWMO
uint32 offsMapObejctsIds; // MWID
uint32 offsDoodsDef; // MDDF
uint32 offsObjectsDef; // MODF
uint32 offsMFBO; // MFBO
uint32 offsMH2O; // MH2O
uint32 data1;
uint32 data2;
uint32 data3;
uint32 data4;
uint32 data5;
public:
bool prepareLoadedData();
adt_MCIN *getMCIN(){ return (adt_MCIN *)((uint8 *)&pad+offsMCIN);}
adt_MH2O *getMH2O(){ return offsMH2O ? (adt_MH2O *)((uint8 *)&pad+offsMH2O) : 0;}
};
class ADT_file : public FileLoader{
public:
bool prepareLoadedData();
ADT_file();
~ADT_file();
void free();
adt_MHDR *a_grid;
};
#endif

View file

@ -0,0 +1,64 @@
#define _CRT_SECURE_NO_DEPRECATE
#include "loadlib.h"
#include "../mpq_libmpq.h"
class MPQFile;
FileLoader::FileLoader()
{
data = 0;
data_size = 0;
version = 0;
}
FileLoader::~FileLoader()
{
free();
}
bool FileLoader::loadFile(char *filename, bool log)
{
free();
MPQFile mf(filename);
if(mf.isEof())
{
if (log)
printf("No such file %s\n", filename);
return false;
}
data_size = mf.getSize();
data = new uint8 [data_size];
if (data)
{
mf.read(data, data_size);
mf.close();
if (prepareLoadedData())
return true;
}
printf("Error loading %s", filename);
mf.close();
free();
return false;
}
bool FileLoader::prepareLoadedData()
{
// Check version
version = (file_MVER *) data;
if (version->fcc != 'MVER')
return false;
if (version->ver != FILE_FORMAT_VERSION)
return false;
return true;
}
void FileLoader::free()
{
if (data) delete[] data;
data = 0;
data_size = 0;
version = 0;
}

View file

@ -0,0 +1,57 @@
#ifndef LOAD_LIB_H
#define LOAD_LIB_H
#ifdef WIN32
typedef __int64 int64;
typedef long int32;
typedef short int16;
typedef char int8;
typedef unsigned __int64 uint64;
typedef unsigned long uint32;
typedef unsigned short uint16;
typedef unsigned char uint8;
#else
#include <stdint.h>
#ifndef uint64_t
#include <linux/types.h>
#endif
typedef int64_t int64;
typedef long int32;
typedef short int16;
typedef char int8;
typedef uint64_t uint64;
typedef unsigned long uint32;
typedef unsigned short uint16;
typedef unsigned char uint8;
#endif
#define FILE_FORMAT_VERSION 18
//
// File version chunk
//
struct file_MVER
{
union{
uint32 fcc;
char fcc_txt[4];
};
uint32 size;
uint32 ver;
};
class FileLoader{
uint8 *data;
uint32 data_size;
public:
virtual bool prepareLoadedData();
uint8 *GetData() {return data;}
uint32 GetDataSize() {return data_size;}
file_MVER *version;
FileLoader();
~FileLoader();
bool loadFile(char *filename, bool log = true);
virtual void free();
};
#endif

View file

@ -0,0 +1,62 @@
#define _CRT_SECURE_NO_DEPRECATE
#include "wdt.h"
bool wdt_MWMO::prepareLoadedData()
{
if (fcc != 'MWMO')
return false;
return true;
}
bool wdt_MPHD::prepareLoadedData()
{
if (fcc != 'MPHD')
return false;
return true;
}
bool wdt_MAIN::prepareLoadedData()
{
if (fcc != 'MAIN')
return false;
return true;
}
WDT_file::WDT_file()
{
mphd = 0;
main = 0;
wmo = 0;
}
WDT_file::~WDT_file()
{
free();
}
void WDT_file::free()
{
mphd = 0;
main = 0;
wmo = 0;
FileLoader::free();
}
bool WDT_file::prepareLoadedData()
{
// Check parent
if (!FileLoader::prepareLoadedData())
return false;
mphd = (wdt_MPHD *)((uint8*)version+version->size+8);
if (!mphd->prepareLoadedData())
return false;
main = (wdt_MAIN *)((uint8*)mphd + mphd->size+8);
if (!main->prepareLoadedData())
return false;
wmo = (wdt_MWMO *)((uint8*)main+ main->size+8);
if (!wmo->prepareLoadedData())
return false;
return true;
}

View file

@ -0,0 +1,68 @@
#ifndef WDT_H
#define WDT_H
#include "loadlib.h"
//**************************************************************************************
// WDT file class and structures
//**************************************************************************************
#define WDT_MAP_SIZE 64
class wdt_MWMO{
union{
uint32 fcc;
char fcc_txt[4];
};
public:
uint32 size;
bool prepareLoadedData();
};
class wdt_MPHD{
union{
uint32 fcc;
char fcc_txt[4];
};
public:
uint32 size;
uint32 data1;
uint32 data2;
uint32 data3;
uint32 data4;
uint32 data5;
uint32 data6;
uint32 data7;
uint32 data8;
bool prepareLoadedData();
};
class wdt_MAIN{
union{
uint32 fcc;
char fcc_txt[4];
};
public:
uint32 size;
struct adtData{
uint32 exist;
uint32 data1;
} adt_list[64][64];
bool prepareLoadedData();
};
class WDT_file : public FileLoader{
public:
bool prepareLoadedData();
WDT_file();
~WDT_file();
void free();
wdt_MPHD *mphd;
wdt_MAIN *main;
wdt_MWMO *wmo;
};
#endif

View file

@ -4,6 +4,7 @@
#ifndef MPQ_H
#define MPQ_H
#include "loadlib/loadlib.h"
#include "libmpq/mpq.h"
#include <string.h>
#include <ctype.h>
@ -13,7 +14,6 @@
using namespace std;
typedef unsigned int uint32;
class MPQArchive
{

View file

@ -22,7 +22,7 @@
DROP TABLE IF EXISTS `db_version`;
CREATE TABLE `db_version` (
`version` varchar(120) default NULL,
`required_7382_01_mangos_creature_template` bit(1) default NULL
`required_7439_01_mangos_mangos_string` bit(1) default NULL
) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=FIXED COMMENT='Used DB version notes';
--
@ -135,6 +135,7 @@ CREATE TABLE `areatrigger_teleport` (
`heroic_key` mediumint(8) unsigned NOT NULL default '0',
`heroic_key2` mediumint(8) unsigned NOT NULL default '0',
`required_quest_done` int(11) unsigned NOT NULL default '0',
`required_quest_done_heroic` int(11) unsigned NOT NULL default '0',
`required_failed_text` text,
`target_map` smallint(5) unsigned NOT NULL default '0',
`target_position_x` float NOT NULL default '0',
@ -1071,6 +1072,7 @@ CREATE TABLE `game_event` (
`end_time` timestamp NOT NULL default '0000-00-00 00:00:00' COMMENT 'Absolute end date, the event will never start afler',
`occurence` bigint(20) unsigned NOT NULL default '86400' COMMENT 'Delay in hours between occurences of the event',
`length` bigint(20) unsigned NOT NULL default '43200' COMMENT 'Length in hours of the event',
`holiday` mediumint(8) unsigned NOT NULL default '0' COMMENT 'Client side holiday id',
`description` varchar(255) default NULL COMMENT 'Description of the event displayed in console',
PRIMARY KEY (`entry`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
@ -2407,6 +2409,7 @@ INSERT INTO `mangos_string` VALUES
(172,'server console command',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL),
(173,'You changed runic power of %s to %i/%i.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL),
(174,'%s changed your runic power to %i/%i.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL),
(175,'Liquid level: %f, ground: %f, type: %d, status: %d',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL),
(200,'No selection.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL),
(201,'Object GUID is: lowpart %u highpart %X',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL),
(202,'The name was too long by %i characters.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL),
@ -2812,7 +2815,6 @@ INSERT INTO `mangos_string` VALUES
(723,'Your group does not have enough players to join this match.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL),
(724,'The Gold Team wins!',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL),
(725,'The Green Team wins!',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL),
(726,'There aren\'t enough players in this battleground. It will end soon unless some more players join to balance the fight.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL),
(727,'Your group has an offline member. Please remove him before joining.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL),
(728,'Your group has players from the opposing faction. You can\'t join the battleground as a group.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL),
(729,'Your group has players from different battleground brakets. You can\'t join as group.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL),
@ -2833,6 +2835,11 @@ INSERT INTO `mangos_string` VALUES
(744,'Modifying played count, arena points etc. for loaded arena teams, sending updated stats to online players...',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL),
(745,'Modification done.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL),
(746,'Done flushing Arena points.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL),
(750,'Not enough players. This game will close in %u mins.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL),
(751,'Not enough players. This game will close in %u seconds.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL),
(753,'The battle for Warsong Gulch begins in 2 minutes.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL),
(754,'The battle for Arathi Basin begins in 2 minutes.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL),
(755,'The battle for Eye of the Storm begins in 2 minutes.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL),
(801,'You do not have enough gold',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL),
(802,'You do not have enough free slots',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL),
(803,'Your partner does not have enough free bag slots',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL),
@ -2843,6 +2850,11 @@ INSERT INTO `mangos_string` VALUES
(808,'Player %s not found or offline',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL),
(809,'Account for character %s not found',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL),
(810,'|Hplayer:$N|h[$N]|h has earned the achievement $a!',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL),
(811,'Guild Master',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL),
(812,'Officer',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL),
(813,'Veteran',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL),
(814,'Member',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL),
(815,'Initiate',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL),
(1000,'Exiting daemon...',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL),
(1001,'Account deleted: %s',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL),
(1002,'Account %s NOT deleted (probably sql file format was updated)',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL),

View file

@ -0,0 +1,5 @@
ALTER TABLE db_version CHANGE COLUMN required_7382_01_mangos_creature_template required_7388_01_mangos_mangos_string bit;
DELETE FROM mangos_string WHERE entry IN (750,751);
INSERT INTO mangos_string VALUES (750,'Not enough players. This game will close in %u mins.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL);
INSERT INTO mangos_string VALUES (751,'Not enough players. This game will close in %u seconds.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL);

View file

@ -0,0 +1,4 @@
ALTER TABLE db_version CHANGE COLUMN required_7388_01_mangos_mangos_string required_7390_01_mangos_areatrigger_teleport bit;
ALTER TABLE areatrigger_teleport
ADD COLUMN required_quest_done_heroic int(11) unsigned NOT NULL default '0' AFTER required_quest_done;

View file

@ -0,0 +1,4 @@
ALTER TABLE db_version CHANGE COLUMN required_7390_01_mangos_areatrigger_teleport required_7393_01_mangos_game_event bit;
ALTER TABLE game_event
ADD COLUMN holiday mediumint(8) unsigned NOT NULL default '0' COMMENT 'Client side holiday id' AFTER length;

View file

@ -0,0 +1,6 @@
ALTER TABLE db_version CHANGE COLUMN required_7393_01_mangos_game_event required_7399_01_mangos_mangos_string bit;
DELETE FROM mangos_string WHERE entry in (753, 754, 755);
INSERT INTO mangos_string VALUES (753,'The battle for Warsong Gulch begins in 2 minutes.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL);
INSERT INTO mangos_string VALUES (754,'The battle for Arathi Basin begins in 2 minutes.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL);
INSERT INTO mangos_string VALUES (755,'The battle for Eye of the Storm begins in 2 minutes.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL);

View file

@ -0,0 +1,9 @@
ALTER TABLE db_version CHANGE COLUMN required_7399_01_mangos_mangos_string required_7422_01_mangos_mangos_string bit;
DELETE FROM mangos_string WHERE entry in (811, 812, 813, 814, 815);
INSERT INTO mangos_string VALUES
(811,'Guild Master',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL),
(812,'Officer',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL),
(813,'Veteran',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL),
(814,'Member',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL),
(815,'Initiate',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL);

View file

@ -0,0 +1,5 @@
ALTER TABLE db_version CHANGE COLUMN required_7422_01_mangos_mangos_string required_7439_01_mangos_mangos_string bit;
DELETE FROM mangos_string WHERE entry in (175);
INSERT INTO mangos_string VALUES
(175,'Liquid level: %f, ground: %f, type: %d, status: %d',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL);

View file

@ -191,6 +191,12 @@ pkgdata_DATA = \
7369_01_mangos_quest_template.sql \
7376_01_mangos_spell_area.sql \
7382_01_mangos_creature_template.sql \
7388_01_mangos_mangos_string.sql \
7390_01_mangos_areatrigger_teleport.sql \
7393_01_mangos_game_event.sql \
7399_01_mangos_mangos_string.sql \
7422_01_mangos_mangos_string.sql \
7439_01_mangos_mangos_string.sql \
README
## Additional files to include when running 'make dist'
@ -362,4 +368,10 @@ EXTRA_DIST = \
7369_01_mangos_quest_template.sql \
7376_01_mangos_spell_area.sql \
7382_01_mangos_creature_template.sql \
7388_01_mangos_mangos_string.sql \
7390_01_mangos_areatrigger_teleport.sql \
7393_01_mangos_game_event.sql \
7399_01_mangos_mangos_string.sql \
7422_01_mangos_mangos_string.sql \
7439_01_mangos_mangos_string.sql \
README

View file

@ -55,6 +55,8 @@
# define MANGOS_GET_PROC_ADDR dlsym
# if defined(__APPLE_CC__) && defined(BIG_ENDIAN)
# define MANGOS_IMPORT __attribute__ ((longcall))
# elif defined(__x86_64__)
# define MANGOS_IMPORT
# else
# define MANGOS_IMPORT __attribute__ ((cdecl))
# endif //__APPLE_CC__ && BIG_ENDIAN

View file

@ -21,10 +21,10 @@
#include "Player.h"
#include "WorldPacket.h"
#include "Database/DBCEnums.h"
#include "GameEventMgr.h"
#include "ObjectMgr.h"
#include "Guild.h"
#include "Database/DatabaseEnv.h"
#include "GameEvent.h"
#include "World.h"
#include "SpellMgr.h"
#include "ArenaTeam.h"
@ -308,7 +308,10 @@ void AchievementMgr::LoadFromDB(QueryResult *achievementResult, QueryResult *cri
void AchievementMgr::SendAchievementEarned(AchievementEntry const* achievement)
{
sLog.outDebug("AchievementMgr::SendAchievementEarned(%u)", achievement->ID);
#ifdef MANGOS_DEBUG
if((sLog.getLogFilter() & LOG_FILTER_ACHIEVEMENT_UPDATES)==0)
sLog.outDebug("AchievementMgr::SendAchievementEarned(%u)", achievement->ID);
#endif
if(Guild* guild = objmgr.GetGuildById(GetPlayer()->GetGuildId()))
{
@ -392,7 +395,8 @@ static const uint32 achievIdForDangeon[][4] =
*/
void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, uint32 miscvalue1, uint32 miscvalue2, Unit *unit, uint32 time)
{
sLog.outDetail("AchievementMgr::UpdateAchievementCriteria(%u, %u, %u, %u)", type, miscvalue1, miscvalue2, time);
if((sLog.getLogFilter() & LOG_FILTER_ACHIEVEMENT_UPDATES)==0)
sLog.outDetail("AchievementMgr::UpdateAchievementCriteria(%u, %u, %u, %u)", type, miscvalue1, miscvalue2, time);
if (!sWorld.getConfig(CONFIG_GM_ALLOW_ACHIEVEMENT_GAINS) && m_player->GetSession()->GetSecurity() > SEC_PLAYER)
return;
@ -455,6 +459,54 @@ void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, ui
continue;
if(achievementCriteria->kill_creature.creatureID != miscvalue1)
continue;
// LOT achievement->ID required special custom checks
switch(achievement->ID)
{
// Just heroic
case 489: case 490: case 491: case 492: case 493: case 494: case 495:
case 496: case 497: case 498: case 499: case 500: case 563: case 565:
case 567: case 569: case 573: case 575: case 577: case 623: case 625:
case 667: case 668: case 669: case 670: case 671: case 672: case 673:
case 674: case 675: case 676: case 677: case 678: case 679: case 680:
case 681: case 682: case 1367: case 1368: case 1378: case 1379:
case 1380: case 1381: case 1382: case 1383: case 1384: case 1385:
case 1386: case 1387: case 1388: case 1389: case 1390: case 1393:
case 1394: case 1400: case 1402: case 1504: case 1505: case 1506:
case 1507: case 1508: case 1509: case 1510: case 1511: case 1512:
case 1513: case 1514: case 1515: case 1721: case 1754: case 1756:
case 1768: case 1817: case 1865:
if(GetPlayer()->GetDifficulty()!=DIFFICULTY_HEROIC)
continue;
break;
// Heroic + other
case 579: case 1296: case 1297: case 1816: case 1834: case 1857: case 1859:
case 1860: case 1861: case 1862: case 1864: case 1866: case 1867: case 1868:
case 1870: case 1871: case 1872: case 1873: case 1875: case 1877: case 1919:
case 2036: case 2037: case 2038: case 2039: case 2040: case 2041: case 2042:
case 2043: case 2044: case 2045: case 2046: case 2048: case 2052: case 2053:
case 2054: case 2056: case 2057: case 2058: case 2139: case 2140: case 2147:
case 2149: case 2150: case 2151: case 2152: case 2154: case 2155: case 2156:
case 2157: case 2179: case 2181: case 2183: case 2185: case 2186:
if(GetPlayer()->GetDifficulty()!=DIFFICULTY_HEROIC)
continue;
// FIX ME: mark as fail always until implement
continue;
// Normal + other
case 578: case 624: case 1790: case 1856: case 1858: case 1869: case 1874:
case 1996: case 1997: case 2047: case 2049: case 2050: case 2051: case 2146:
case 2148: case 2153: case 2178: case 2180: case 2182: case 2184: case 2187:
if(GetPlayer()->GetDifficulty()!=DIFFICULTY_NORMAL)
continue;
// FIX ME: mark as fail always until implement
continue;
// Just Normal
default:
if(GetPlayer()->GetDifficulty()!=DIFFICULTY_NORMAL)
continue;
break;
};
SetCriteriaProgress(achievementCriteria, miscvalue2, PROGRESS_ACCUMULATE);
break;
case ACHIEVEMENT_CRITERIA_TYPE_REACH_LEVEL:
@ -606,8 +658,7 @@ void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, ui
{
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))
if(!IsHolidayActive(HOLIDAY_BREWFEST))
continue;
}
// miscvalue1 is the ingame fallheight*100 as stored in dbc
@ -730,6 +781,31 @@ void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, ui
SetCriteriaProgress(achievementCriteria, 1, PROGRESS_ACCUMULATE);
break;
}
case ACHIEVEMENT_CRITERIA_TYPE_DO_EMOTE:
{
// miscvalue1 = emote
// miscvalue2 = achievement->ID for special requirement
if(!miscvalue1)
continue;
if(miscvalue1 != achievementCriteria->do_emote.emoteID)
continue;
if(achievementCriteria->do_emote.count)
{
// harcoded case
if(achievement->ID==247)
{
if (!unit || unit->GetTypeId() != TYPEID_PLAYER ||
unit->isAlive() || ((Player*)unit)->GetDeathTimer() == 0)
continue;
}
// expected as scripted case
else if(!miscvalue2 || !achievement->ID != miscvalue2)
continue;
}
SetCriteriaProgress(achievementCriteria, 1, PROGRESS_ACCUMULATE);
break;
}
case ACHIEVEMENT_CRITERIA_TYPE_LEARN_SKILLLINE_SPELLS:
{
uint32 spellCount = 0;
@ -798,7 +874,6 @@ void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, ui
case ACHIEVEMENT_CRITERIA_TYPE_EQUIP_EPIC_ITEM:
case ACHIEVEMENT_CRITERIA_TYPE_HK_CLASS:
case ACHIEVEMENT_CRITERIA_TYPE_HK_RACE:
case ACHIEVEMENT_CRITERIA_TYPE_DO_EMOTE:
case ACHIEVEMENT_CRITERIA_TYPE_HEALING_DONE:
case ACHIEVEMENT_CRITERIA_TYPE_GET_KILLING_BLOWS:
case ACHIEVEMENT_CRITERIA_TYPE_EQUIP_ITEM:
@ -927,6 +1002,8 @@ bool AchievementMgr::IsCompletedCriteria(AchievementCriteriaEntry const* achieve
case ACHIEVEMENT_CRITERIA_TYPE_ROLL_NEED_ON_LOOT:
case ACHIEVEMENT_CRITERIA_TYPE_ROLL_GREED_ON_LOOT:
return progress->counter >= achievementCriteria->roll_greed_on_loot.count;
case ACHIEVEMENT_CRITERIA_TYPE_DO_EMOTE:
return progress->counter >= achievementCriteria->do_emote.count;
case ACHIEVEMENT_CRITERIA_TYPE_MONEY_FROM_QUEST_REWARD:
return progress->counter >= achievementCriteria->quest_reward_money.goldInCopper;
case ACHIEVEMENT_CRITERIA_TYPE_LOOT_MONEY:
@ -998,7 +1075,9 @@ AchievementCompletionState AchievementMgr::GetAchievementCompletionState(Achieve
void AchievementMgr::SetCriteriaProgress(AchievementCriteriaEntry const* entry, uint32 changeValue, ProgressType ptype)
{
sLog.outDetail("AchievementMgr::SetCriteriaProgress(%u, %u) for (GUID:%u)", entry->ID, changeValue);
if((sLog.getLogFilter() & LOG_FILTER_ACHIEVEMENT_UPDATES)==0)
sLog.outDetail("AchievementMgr::SetCriteriaProgress(%u, %u) for (GUID:%u)", entry->ID, changeValue);
CriteriaProgress *progress = NULL;
CriteriaProgressMap::iterator iter = m_criteriaProgress.find(entry->ID);
@ -1024,8 +1103,12 @@ void AchievementMgr::SetCriteriaProgress(AchievementCriteriaEntry const* entry,
newValue = changeValue;
break;
case PROGRESS_ACCUMULATE:
newValue = progress->counter + changeValue;
{
// avoid overflow
uint32 max_value = std::numeric_limits<uint32>::max();
newValue = max_value - progress->counter > changeValue ? progress->counter + changeValue : max_value;
break;
}
case PROGRESS_HIGHEST:
newValue = progress->counter < changeValue ? changeValue : progress->counter;
break;

View file

@ -19,7 +19,6 @@
#include "AggressorAI.h"
#include "Errors.h"
#include "Creature.h"
#include "Player.h"
#include "ObjectAccessor.h"
#include "VMapFactory.h"
#include "World.h"

View file

@ -575,6 +575,28 @@ void ArenaTeam::MemberLost(Player * plr, uint32 againstRating)
}
}
void ArenaTeam::OfflineMemberLost(uint64 guid, uint32 againstRating)
{
// called for offline player after ending rated arena match!
for(MemberList::iterator itr = members.begin(); itr != members.end(); ++itr)
{
if(itr->guid == guid)
{
// update personal rating
float chance = GetChanceAgainst(itr->personal_rating, againstRating);
int32 mod = (int32)ceil(32.0f * (0.0f - chance));
if (int32(itr->personal_rating) + mod < 0)
itr->personal_rating = 0;
else
itr->personal_rating += mod;
// update personal played stats
itr->games_week +=1;
itr->games_season +=1;
return;
}
}
}
void ArenaTeam::MemberWon(Player * plr, uint32 againstRating)
{
// called for each participant after winning a match

View file

@ -198,6 +198,7 @@ class ArenaTeam
void MemberWon(Player * plr, uint32 againstRating);
int32 LostAgainst(uint32 againstRating);
void MemberLost(Player * plr, uint32 againstRating);
void OfflineMemberLost(uint64 guid, uint32 againstRating);
void UpdateArenaPointsHelper(std::map<uint32, uint32> & PlayerPoints);

View file

@ -25,7 +25,6 @@
#include "ArenaTeam.h"
#include "World.h"
#include "SocialMgr.h"
#include "Language.h"
void WorldSession::HandleInspectArenaStatsOpcode(WorldPacket & recv_data)
{

View file

@ -21,9 +21,7 @@
#include "ObjectMgr.h"
#include "Database/DatabaseEnv.h"
#include "Log.h"
#include "WorldPacket.h"
#include "UpdateData.h"
#include "WorldSession.h"
Bag::Bag( ): Item()
{

View file

@ -23,7 +23,6 @@
#include "Creature.h"
#include "MapManager.h"
#include "Language.h"
#include "Chat.h"
#include "SpellAuras.h"
#include "ArenaTeam.h"
#include "World.h"
@ -31,12 +30,105 @@
#include "ObjectMgr.h"
#include "WorldPacket.h"
#include "Util.h"
#include "Formulas.h"
#include "GridNotifiersImpl.h"
namespace MaNGOS
{
class BattleGroundChatBuilder
{
public:
BattleGroundChatBuilder(ChatMsg msgtype, int32 textId, Player const* source, va_list* args = NULL)
: i_msgtype(msgtype), i_textId(textId), i_source(source), i_args(args) {}
void operator()(WorldPacket& data, int32 loc_idx)
{
char const* text = objmgr.GetMangosString(i_textId,loc_idx);
if(i_args)
{
// we need copy va_list before use or original va_list will corrupted
va_list ap;
va_copy(ap,*i_args);
char str [2048];
vsnprintf(str,2048,text, ap );
va_end(ap);
do_helper(data,&str[0]);
}
else
do_helper(data,text);
}
private:
void do_helper(WorldPacket& data, char const* text)
{
uint64 target_guid = i_source ? i_source ->GetGUID() : 0;
data << uint8(i_msgtype);
data << uint32(LANG_UNIVERSAL);
data << uint64(target_guid); // there 0 for BG messages
data << uint32(0); // can be chat msg group or something
data << uint64(target_guid);
data << uint32(strlen(text)+1);
data << text;
data << uint8(i_source ? i_source->chatTag() : uint8(0));
}
ChatMsg i_msgtype;
int32 i_textId;
Player const* i_source;
va_list* i_args;
};
class BattleGround2ChatBuilder
{
public:
BattleGround2ChatBuilder(ChatMsg msgtype, int32 textId, Player const* source, int32 arg1, int32 arg2)
: i_msgtype(msgtype), i_textId(textId), i_source(source), i_arg1(arg1), i_arg2(arg2) {}
void operator()(WorldPacket& data, int32 loc_idx)
{
char const* text = objmgr.GetMangosString(i_textId,loc_idx);
char const* arg1str = i_arg1 ? objmgr.GetMangosString(i_arg1,loc_idx) : "";
char const* arg2str = i_arg2 ? objmgr.GetMangosString(i_arg2,loc_idx) : "";
char str [2048];
snprintf(str,2048,text, arg1str, arg2str );
uint64 target_guid = i_source ? i_source ->GetGUID() : 0;
data << uint8(i_msgtype);
data << uint32(LANG_UNIVERSAL);
data << uint64(target_guid); // there 0 for BG messages
data << uint32(0); // can be chat msg group or something
data << uint64(target_guid);
data << uint32(strlen(str)+1);
data << str;
data << uint8(i_source ? i_source->chatTag() : uint8(0));
}
private:
ChatMsg i_msgtype;
int32 i_textId;
Player const* i_source;
int32 i_arg1;
int32 i_arg2;
};
} // namespace MaNGOS
template<class Do>
void BattleGround::BroadcastWorker(Do& _do)
{
for(BattleGroundPlayerMap::iterator itr = m_Players.begin(); itr != m_Players.end(); ++itr)
if(Player *plr = ObjectAccessor::FindPlayer(MAKE_NEW_GUID(itr->first, 0, HIGHGUID_PLAYER)))
_do(plr);
}
BattleGround::BattleGround()
{
m_TypeID = BattleGroundTypeId(0);
m_InstanceID = 0;
m_Status = STATUS_NONE;
m_ClientInstanceID = 0;
m_EndTime = 0;
m_LastResurrectTime = 0;
m_QueueId = QUEUE_ID_MAX_LEVEL_19;
@ -88,6 +180,16 @@ BattleGround::BattleGround()
m_PrematureCountDown = false;
m_PrematureCountDown = 0;
m_StartDelayTimes[BG_STARTING_EVENT_FIRST] = BG_START_DELAY_2M;
m_StartDelayTimes[BG_STARTING_EVENT_SECOND] = BG_START_DELAY_1M;
m_StartDelayTimes[BG_STARTING_EVENT_THIRD] = BG_START_DELAY_30S;
m_StartDelayTimes[BG_STARTING_EVENT_FOURTH] = BG_START_DELAY_NONE;
//we must set to some default existing values
m_StartMessageIds[BG_STARTING_EVENT_FIRST] = LANG_BG_WS_START_TWO_MINUTES;
m_StartMessageIds[BG_STARTING_EVENT_SECOND] = LANG_BG_WS_START_ONE_MINUTE;
m_StartMessageIds[BG_STARTING_EVENT_THIRD] = LANG_BG_WS_START_HALF_MINUTE;
m_StartMessageIds[BG_STARTING_EVENT_FOURTH] = LANG_BG_WS_HAS_BEGUN;
}
BattleGround::~BattleGround()
@ -126,50 +228,30 @@ BattleGround::~BattleGround()
void BattleGround::Update(uint32 diff)
{
if(!GetPlayersSize() && !GetRemovedPlayersSize() && !GetReviveQueueSize())
if(!GetPlayersSize() && !GetReviveQueueSize())
//BG is empty
return;
if(GetRemovedPlayersSize())
// remove offline players from bg after 5 minutes
if( !m_OfflineQueue.empty() )
{
for(std::map<uint64, uint8>::iterator itr = m_RemovedPlayers.begin(); itr != m_RemovedPlayers.end(); ++itr)
BattleGroundPlayerMap::iterator itr = m_Players.find(*(m_OfflineQueue.begin()));
if( itr != m_Players.end() )
{
Player *plr = objmgr.GetPlayer(itr->first);
switch(itr->second)
if( itr->second.OfflineRemoveTime <= sWorld.GetGameTime() )
{
case 1: // currently in bg and was removed from bg
if(plr)
RemovePlayerAtLeave(itr->first, true, true);
else
RemovePlayerAtLeave(itr->first, false, false);
break;
case 2: // revive queue
RemovePlayerFromResurrectQueue(itr->first);
break;
default:
sLog.outError("BattleGround: Unknown remove player case!");
RemovePlayerAtLeave(itr->first, true, true);// remove player from BG
m_OfflineQueue.pop_front(); // remove from offline queue
//do not use itr for anything, because it is erased in RemovePlayerAtLeave()
}
}
m_RemovedPlayers.clear();
}
// remove offline players from bg after ~5 minutes
if(GetPlayersSize())
{
for(std::map<uint64, BattleGroundPlayer>::iterator itr = m_Players.begin(); itr != m_Players.end(); ++itr)
{
Player *plr = objmgr.GetPlayer(itr->first);
itr->second.LastOnlineTime += diff;
/*********************************************************/
/*** BATTLEGROUND RESSURECTION SYSTEM ***/
/*********************************************************/
if(plr)
itr->second.LastOnlineTime = 0; // update last online time
else
if(itr->second.LastOnlineTime >= MAX_OFFLINE_TIME) // 5 minutes
m_RemovedPlayers[itr->first] = 1; // add to remove list (BG)
}
}
//this should be handled by spell system:
//this should be handled by spell system
m_LastResurrectTime += diff;
if (m_LastResurrectTime >= RESURRECTION_INTERVAL)
{
@ -219,6 +301,10 @@ void BattleGround::Update(uint32 diff)
m_ResurrectQueue.clear();
}
/*********************************************************/
/*** BATTLEGROUND BALLANCE SYSTEM ***/
/*********************************************************/
// if less then minimum players are in on one side, then start premature finish timer
if(GetStatus() == STATUS_IN_PROGRESS && !isArena() && sBattleGroundMgr.GetPrematureFinishTime() && (GetPlayersCountByTeam(ALLIANCE) < GetMinPlayersPerTeam() || GetPlayersCountByTeam(HORDE) < GetMinPlayersPerTeam()))
{
@ -226,39 +312,137 @@ void BattleGround::Update(uint32 diff)
{
m_PrematureCountDown = true;
m_PrematureCountDownTimer = sBattleGroundMgr.GetPrematureFinishTime();
SendMessageToAll(LANG_BATTLEGROUND_PREMATURE_FINISH_WARNING);
}
else if(m_PrematureCountDownTimer < diff)
{
// time's up!
EndBattleGround(0); // noone wins
uint32 winner = 0;
if( GetPlayersCountByTeam(ALLIANCE) >= GetMinPlayersPerTeam() )
winner = ALLIANCE;
else if( GetPlayersCountByTeam(HORDE) >= GetMinPlayersPerTeam() )
winner = HORDE;
EndBattleGround(winner);
m_PrematureCountDown = false;
}
else
{
uint32 newtime = m_PrematureCountDownTimer - diff;
// announce every minute
if(m_PrematureCountDownTimer != sBattleGroundMgr.GetPrematureFinishTime() && newtime / 60000 != m_PrematureCountDownTimer / 60000)
SendMessageToAll(LANG_BATTLEGROUND_PREMATURE_FINISH_WARNING);
if( newtime > (MINUTE * IN_MILISECONDS) )
{
if( newtime / (MINUTE * IN_MILISECONDS) != m_PrematureCountDownTimer / (MINUTE * IN_MILISECONDS) )
PSendMessageToAll(LANG_BATTLEGROUND_PREMATURE_FINISH_WARNING, CHAT_MSG_SYSTEM, NULL, (uint32)(m_PrematureCountDownTimer / (MINUTE * IN_MILISECONDS)));
}
else
{
//announce every 15 seconds
if( newtime / (15 * IN_MILISECONDS) != m_PrematureCountDownTimer / (15 * IN_MILISECONDS) )
PSendMessageToAll(LANG_BATTLEGROUND_PREMATURE_FINISH_WARNING_SECS, CHAT_MSG_SYSTEM, NULL, (uint32)(m_PrematureCountDownTimer / IN_MILISECONDS));
}
m_PrematureCountDownTimer = newtime;
}
}
else if (m_PrematureCountDown)
m_PrematureCountDown = false;
/*********************************************************/
/*** BATTLEGROUND STARTING SYSTEM ***/
/*********************************************************/
if (GetStatus() == STATUS_WAIT_JOIN && GetPlayersSize())
{
ModifyStartDelayTime(diff);
if (!(m_Events & BG_STARTING_EVENT_1))
{
m_Events |= BG_STARTING_EVENT_1;
// setup here, only when at least one player has ported to the map
if(!SetupBattleGround())
{
EndNow();
return;
}
StartingEventCloseDoors();
SetStartDelayTime(m_StartDelayTimes[BG_STARTING_EVENT_FIRST]);
//first start warning - 2 or 1 minute
SendMessageToAll(m_StartMessageIds[BG_STARTING_EVENT_FIRST], CHAT_MSG_BG_SYSTEM_NEUTRAL);
}
// After 1 minute or 30 seconds, warning is signalled
else if (GetStartDelayTime() <= m_StartDelayTimes[BG_STARTING_EVENT_SECOND] && !(m_Events & BG_STARTING_EVENT_2))
{
m_Events |= BG_STARTING_EVENT_2;
SendMessageToAll(m_StartMessageIds[BG_STARTING_EVENT_SECOND], CHAT_MSG_BG_SYSTEM_NEUTRAL);
}
// After 30 or 15 seconds, warning is signalled
else if (GetStartDelayTime() <= m_StartDelayTimes[BG_STARTING_EVENT_THIRD] && !(m_Events & BG_STARTING_EVENT_3))
{
m_Events |= BG_STARTING_EVENT_3;
SendMessageToAll(m_StartMessageIds[BG_STARTING_EVENT_THIRD], CHAT_MSG_BG_SYSTEM_NEUTRAL);
}
// delay expired (atfer 2 or 1 minute)
else if (GetStartDelayTime() <= 0 && !(m_Events & BG_STARTING_EVENT_4))
{
m_Events |= BG_STARTING_EVENT_4;
StartingEventOpenDoors();
SendMessageToAll(m_StartMessageIds[BG_STARTING_EVENT_FOURTH], CHAT_MSG_BG_SYSTEM_NEUTRAL);
SetStatus(STATUS_IN_PROGRESS);
SetStartDelayTime(m_StartDelayTimes[BG_STARTING_EVENT_FOURTH]);
//remove preparation
if( isArena() )
{
//TODO : add arena sound PlaySoundToAll(SOUND_ARENA_START);
for(BattleGroundPlayerMap::const_iterator itr = GetPlayers().begin(); itr != GetPlayers().end(); ++itr)
if(Player *plr = objmgr.GetPlayer(itr->first))
plr->RemoveAurasDueToSpell(SPELL_ARENA_PREPARATION);
CheckArenaWinConditions();
}
else
{
PlaySoundToAll(SOUND_BG_START);
for(BattleGroundPlayerMap::const_iterator itr = GetPlayers().begin(); itr != GetPlayers().end(); ++itr)
if(Player* plr = objmgr.GetPlayer(itr->first))
plr->RemoveAurasDueToSpell(SPELL_PREPARATION);
//Announce BG starting
if( sWorld.getConfig(CONFIG_BATTLEGROUND_QUEUE_ANNOUNCER_ENABLE) )
{
sWorld.SendWorldText(LANG_BG_STARTED_ANNOUNCE_WORLD, GetName(), GetMinLevel(), GetMaxLevel());
}
}
}
}
/*********************************************************/
/*** BATTLEGROUND ENDING SYSTEM ***/
/*********************************************************/
if(GetStatus() == STATUS_WAIT_LEAVE)
{
// remove all players from battleground after 2 minutes
m_EndTime += diff;
if(m_EndTime >= TIME_TO_AUTOREMOVE) // 2 minutes
{
for(std::map<uint64, BattleGroundPlayer>::iterator itr = m_Players.begin(); itr != m_Players.end(); ++itr)
BattleGroundPlayerMap::iterator itr, next;
for(itr = m_Players.begin(); itr != m_Players.end(); itr = next)
{
m_RemovedPlayers[itr->first] = 1; // add to remove list (BG)
next = itr;
++next;
//itr is erased here!
RemovePlayerAtLeave(itr->first, true, true);// remove player from BG
// do not change any battleground's private variables
}
// do not change any battleground's private variables
}
}
}
void BattleGround::SetTeamStartLoc(uint32 TeamID, float X, float Y, float Z, float O)
@ -272,7 +456,7 @@ void BattleGround::SetTeamStartLoc(uint32 TeamID, float X, float Y, float Z, flo
void BattleGround::SendPacketToAll(WorldPacket *packet)
{
for(std::map<uint64, BattleGroundPlayer>::iterator itr = m_Players.begin(); itr != m_Players.end(); ++itr)
for(BattleGroundPlayerMap::iterator itr = m_Players.begin(); itr != m_Players.end(); ++itr)
{
Player *plr = objmgr.GetPlayer(itr->first);
if(plr)
@ -284,7 +468,7 @@ void BattleGround::SendPacketToAll(WorldPacket *packet)
void BattleGround::SendPacketToTeam(uint32 TeamID, WorldPacket *packet, Player *sender, bool self)
{
for(std::map<uint64, BattleGroundPlayer>::iterator itr = m_Players.begin(); itr != m_Players.end(); ++itr)
for(BattleGroundPlayerMap::iterator itr = m_Players.begin(); itr != m_Players.end(); ++itr)
{
Player *plr = objmgr.GetPlayer(itr->first);
@ -316,7 +500,7 @@ void BattleGround::PlaySoundToTeam(uint32 SoundID, uint32 TeamID)
{
WorldPacket data;
for(std::map<uint64, BattleGroundPlayer>::iterator itr = m_Players.begin(); itr != m_Players.end(); ++itr)
for(BattleGroundPlayerMap::iterator itr = m_Players.begin(); itr != m_Players.end(); ++itr)
{
Player *plr = objmgr.GetPlayer(itr->first);
@ -339,7 +523,7 @@ void BattleGround::PlaySoundToTeam(uint32 SoundID, uint32 TeamID)
void BattleGround::CastSpellOnTeam(uint32 SpellID, uint32 TeamID)
{
for(std::map<uint64, BattleGroundPlayer>::iterator itr = m_Players.begin(); itr != m_Players.end(); ++itr)
for(BattleGroundPlayerMap::iterator itr = m_Players.begin(); itr != m_Players.end(); ++itr)
{
Player *plr = objmgr.GetPlayer(itr->first);
@ -359,7 +543,7 @@ void BattleGround::CastSpellOnTeam(uint32 SpellID, uint32 TeamID)
void BattleGround::RewardHonorToTeam(uint32 Honor, uint32 TeamID)
{
for(std::map<uint64, BattleGroundPlayer>::iterator itr = m_Players.begin(); itr != m_Players.end(); ++itr)
for(BattleGroundPlayerMap::iterator itr = m_Players.begin(); itr != m_Players.end(); ++itr)
{
Player *plr = objmgr.GetPlayer(itr->first);
@ -384,7 +568,7 @@ void BattleGround::RewardReputationToTeam(uint32 faction_id, uint32 Reputation,
if(!factionEntry)
return;
for(std::map<uint64, BattleGroundPlayer>::iterator itr = m_Players.begin(); itr != m_Players.end(); ++itr)
for(BattleGroundPlayerMap::iterator itr = m_Players.begin(); itr != m_Players.end(); ++itr)
{
Player *plr = objmgr.GetPlayer(itr->first);
@ -425,15 +609,11 @@ void BattleGround::EndBattleGround(uint32 winner)
uint32 loser_rating = 0;
uint32 winner_rating = 0;
WorldPacket data;
Player *Source = NULL;
const char *winmsg = "";
int32 winmsg_id = 0;
if(winner == ALLIANCE)
{
if(isBattleGround())
winmsg = GetMangosString(LANG_BG_A_WINS);
else
winmsg = GetMangosString(LANG_ARENA_GOLD_WINS);
winmsg_id = isBattleGround() ? LANG_BG_A_WINS : LANG_ARENA_GOLD_WINS;
PlaySoundToAll(SOUND_ALLIANCE_WINS); // alliance wins sound
@ -441,10 +621,7 @@ void BattleGround::EndBattleGround(uint32 winner)
}
else if(winner == HORDE)
{
if(isBattleGround())
winmsg = GetMangosString(LANG_BG_H_WINS);
else
winmsg = GetMangosString(LANG_ARENA_GREEN_WINS);
winmsg_id = isBattleGround() ? LANG_BG_H_WINS : LANG_ARENA_GREEN_WINS;
PlaySoundToAll(SOUND_HORDE_WINS); // horde wins sound
@ -461,33 +638,17 @@ void BattleGround::EndBattleGround(uint32 winner)
// arena rating calculation
if(isArena() && isRated())
{
if(winner == ALLIANCE)
{
winner_arena_team = objmgr.GetArenaTeamById(GetArenaTeamIdForTeam(ALLIANCE));
loser_arena_team = objmgr.GetArenaTeamById(GetArenaTeamIdForTeam(HORDE));
}
else if(winner == HORDE)
{
winner_arena_team = objmgr.GetArenaTeamById(GetArenaTeamIdForTeam(HORDE));
loser_arena_team = objmgr.GetArenaTeamById(GetArenaTeamIdForTeam(ALLIANCE));
}
if(winner_arena_team && loser_arena_team)
winner_arena_team = objmgr.GetArenaTeamById(GetArenaTeamIdForTeam(winner));
loser_arena_team = objmgr.GetArenaTeamById(GetArenaTeamIdForTeam(GetOtherTeam(winner)));
if( winner_arena_team && loser_arena_team )
{
loser_rating = loser_arena_team->GetStats().rating;
winner_rating = winner_arena_team->GetStats().rating;
int32 winner_change = winner_arena_team->WonAgainst(loser_rating);
int32 loser_change = loser_arena_team->LostAgainst(winner_rating);
sLog.outDebug("--- Winner rating: %u, Loser rating: %u, Winner change: %u, Losser change: %u ---", winner_rating, loser_rating, winner_change, loser_change);
if(winner == ALLIANCE)
{
SetArenaTeamRatingChangeForTeam(ALLIANCE, winner_change);
SetArenaTeamRatingChangeForTeam(HORDE, loser_change);
}
else
{
SetArenaTeamRatingChangeForTeam(HORDE, winner_change);
SetArenaTeamRatingChangeForTeam(ALLIANCE, loser_change);
}
SetArenaTeamRatingChangeForTeam(winner, winner_change);
SetArenaTeamRatingChangeForTeam(GetOtherTeam(winner), loser_change);
}
else
{
@ -496,11 +657,21 @@ void BattleGround::EndBattleGround(uint32 winner)
}
}
for(std::map<uint64, BattleGroundPlayer>::iterator itr = m_Players.begin(); itr != m_Players.end(); ++itr)
for(BattleGroundPlayerMap::iterator itr = m_Players.begin(); itr != m_Players.end(); ++itr)
{
Player *plr = objmgr.GetPlayer(itr->first);
uint32 team = itr->second.Team;
if(!plr)
{
//if rated arena match - make member lost!
if(isArena() && isRated() && winner_arena_team && loser_arena_team)
{
if(team == winner)
winner_arena_team->OfflineMemberLost(itr->first, loser_rating);
else
loser_arena_team->OfflineMemberLost(itr->first, winner_rating);
}
sLog.outError("BattleGround: Player " I64FMTD " not found!", itr->first);
continue;
}
@ -515,8 +686,8 @@ void BattleGround::EndBattleGround(uint32 winner)
plr->SpawnCorpseBones();
}
uint32 team = itr->second.Team;
if(!team) team = plr->GetTeam();
//this line is obsolete - team is set ALWAYS
//if(!team) team = plr->GetTeam();
// per player calculation
if(isArena() && isRated() && winner_arena_team && loser_arena_team)
@ -529,10 +700,7 @@ void BattleGround::EndBattleGround(uint32 winner)
if(team == winner)
{
if(!Source)
Source = plr;
RewardMark(plr,ITEM_WINNER_COUNT);
UpdatePlayerScore(plr, SCORE_BONUS_HONOR, 20);
RewardQuest(plr);
}
else
@ -548,7 +716,7 @@ void BattleGround::EndBattleGround(uint32 winner)
plr->GetSession()->SendPacket(&data);
BattleGroundQueueTypeId bgQueueTypeId = BattleGroundMgr::BGQueueTypeId(GetTypeID(), GetArenaType());
sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, this, plr->GetTeam(), plr->GetBattleGroundQueueIndex(bgQueueTypeId), STATUS_IN_PROGRESS, TIME_TO_AUTOREMOVE, GetStartTime());
sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, this, plr->GetBattleGroundQueueIndex(bgQueueTypeId), STATUS_IN_PROGRESS, TIME_TO_AUTOREMOVE, GetStartTime());
plr->GetSession()->SendPacket(&data);
plr->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_BATTLEGROUND, 1);
}
@ -570,11 +738,14 @@ void BattleGround::EndBattleGround(uint32 winner)
// inform invited players about the removal
sBattleGroundMgr.m_BattleGroundQueues[BattleGroundMgr::BGQueueTypeId(GetTypeID(), GetArenaType())].BGEndedRemoveInvites(this);
if(Source)
{
ChatHandler(Source).FillMessageData(&data, CHAT_MSG_BG_SYSTEM_NEUTRAL, LANG_UNIVERSAL, Source->GetGUID(), winmsg);
SendPacketToAll(&data);
}
if(winmsg_id)
SendMessageToAll(winmsg_id, CHAT_MSG_BG_SYSTEM_NEUTRAL);
}
uint32 BattleGround::GetBonusHonorFromKill(uint32 kills) const
{
//variable kills means how many honorable kills you scored (so we need kills * honor_for_one_kill)
return MaNGOS::Honor::hk_honor_at_level(GetMaxLevel(), kills);
}
uint32 BattleGround::GetBattlemasterEntry() const
@ -723,10 +894,10 @@ void BattleGround::RemovePlayerAtLeave(uint64 guid, bool Transport, bool SendPac
uint32 team = GetPlayerTeam(guid);
bool participant = false;
// Remove from lists/maps
std::map<uint64, BattleGroundPlayer>::iterator itr = m_Players.find(guid);
BattleGroundPlayerMap::iterator itr = m_Players.find(guid);
if(itr != m_Players.end())
{
UpdatePlayersCountByTeam(team, true); // -1 player
UpdatePlayersCountByTeam(team, true); // -1 player
m_Players.erase(itr);
// check if the player was a participant of the match, or only entered through gm command (goname)
participant = true;
@ -755,21 +926,21 @@ void BattleGround::RemovePlayerAtLeave(uint64 guid, bool Transport, bool SendPac
RemovePlayer(plr, guid); // BG subclass specific code
if(plr)
if(participant) // if the player was a match participant, remove auras, calc rating, update queue
{
plr->ClearAfkReports();
if(participant) // if the player was a match participant, remove auras, calc rating, update queue
BattleGroundTypeId bgTypeId = GetTypeID();
BattleGroundQueueTypeId bgQueueTypeId = BattleGroundMgr::BGQueueTypeId(GetTypeID(), GetArenaType());
if(plr)
{
plr->ClearAfkReports();
if(!team) team = plr->GetTeam();
BattleGroundTypeId bgTypeId = GetTypeID();
BattleGroundQueueTypeId bgQueueTypeId = BattleGroundMgr::BGQueueTypeId(GetTypeID(), GetArenaType());
// if arena, remove the specific arena auras
if(isArena())
{
plr->RemoveArenaAuras(true); // removes debuffs / dots etc., we don't want the player to die after porting out
bgTypeId=BATTLEGROUND_AA; // set the bg type to all arenas (it will be used for queue refreshing)
plr->RemoveArenaAuras(true); // removes debuffs / dots etc., we don't want the player to die after porting out
bgTypeId=BATTLEGROUND_AA; // set the bg type to all arenas (it will be used for queue refreshing)
// summon old pet if there was one and there isn't a current pet
if(!plr->GetPet() && plr->GetTemporaryUnsummonedPetNumber())
@ -784,65 +955,64 @@ void BattleGround::RemovePlayerAtLeave(uint64 guid, bool Transport, bool SendPac
if(isRated() && GetStatus() == STATUS_IN_PROGRESS)
{
//left a rated match while the encounter was in progress, consider as loser
ArenaTeam * winner_arena_team = 0;
ArenaTeam * loser_arena_team = 0;
if(team == HORDE)
{
winner_arena_team = objmgr.GetArenaTeamById(GetArenaTeamIdForTeam(ALLIANCE));
loser_arena_team = objmgr.GetArenaTeamById(GetArenaTeamIdForTeam(HORDE));
}
else
{
winner_arena_team = objmgr.GetArenaTeamById(GetArenaTeamIdForTeam(HORDE));
loser_arena_team = objmgr.GetArenaTeamById(GetArenaTeamIdForTeam(ALLIANCE));
}
ArenaTeam * winner_arena_team = objmgr.GetArenaTeamById(GetArenaTeamIdForTeam(GetOtherTeam(team)));
ArenaTeam * loser_arena_team = objmgr.GetArenaTeamById(GetArenaTeamIdForTeam(team));
if(winner_arena_team && loser_arena_team)
{
loser_arena_team->MemberLost(plr,winner_arena_team->GetRating());
}
}
}
WorldPacket data;
if(SendPacket)
{
sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, this, team, plr->GetBattleGroundQueueIndex(bgQueueTypeId), STATUS_NONE, 0, 0);
WorldPacket data;
sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, this, plr->GetBattleGroundQueueIndex(bgQueueTypeId), STATUS_NONE, 0, 0);
plr->GetSession()->SendPacket(&data);
}
// this call is important, because player, when joins to battleground, this method is not called, so it must be called when leaving bg
plr->RemoveBattleGroundQueueId(bgQueueTypeId);
DecreaseInvitedCount(team);
//we should update battleground queue, but only if bg isn't ending
if (GetStatus() < STATUS_WAIT_LEAVE)
sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].Update(bgTypeId, GetQueueId());
Group * group = plr->GetGroup();
// remove from raid group if exist
if(group && group == GetBgRaid(team))
}
else
// removing offline participant
{
if(isRated() && GetStatus() == STATUS_IN_PROGRESS)
{
if(!group->RemoveMember(guid, 0)) // group was disbanded
{
SetBgRaid(team, NULL);
delete group;
}
//left a rated match while the encounter was in progress, consider as loser
ArenaTeam * others_arena_team = objmgr.GetArenaTeamById(GetArenaTeamIdForTeam(GetOtherTeam(team)));
ArenaTeam * players_arena_team = objmgr.GetArenaTeamById(GetArenaTeamIdForTeam(team));
if( others_arena_team && players_arena_team )
players_arena_team->OfflineMemberLost(guid, others_arena_team->GetRating());
}
// Let others know
sBattleGroundMgr.BuildPlayerLeftBattleGroundPacket(&data, plr);
SendPacketToTeam(team, &data, plr, false);
}
// remove from raid group if player is member
if(Group *group = GetBgRaid(team))
{
if( !group->RemoveMember(guid, 0) ) // group was disbanded
{
SetBgRaid(team, NULL);
delete group;
}
}
DecreaseInvitedCount(team);
//we should update battleground queue, but only if bg isn't ending
if( isBattleGround() && GetStatus() < STATUS_WAIT_LEAVE )
sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].Update(bgTypeId, GetQueueId());
// Let others know
WorldPacket data;
sBattleGroundMgr.BuildPlayerLeftBattleGroundPacket(&data, guid);
SendPacketToTeam(team, &data, plr, false);
}
if( plr )
{
// Do next only if found in battleground
plr->SetBattleGroundId(0, BATTLEGROUND_TYPE_NONE); // We're not in BG.
plr->SetBattleGroundId(0, BATTLEGROUND_TYPE_NONE); // We're not in BG.
// reset destination bg team
plr->SetBGTeam(0);
if(Transport)
plr->TeleportTo(plr->GetBattleGroundEntryPoint());
// Log
sLog.outDetail("BATTLEGROUND: Removed player %s from BattleGround.", plr->GetName());
}
@ -900,7 +1070,7 @@ void BattleGround::AddPlayer(Player *plr)
uint32 team = plr->GetBGTeam();
BattleGroundPlayer bp;
bp.LastOnlineTime = 0;
bp.OfflineRemoveTime = 0;
bp.Team = team;
// Add to list/maps
@ -963,7 +1133,7 @@ void BattleGround::AddPlayer(Player *plr)
}
// setup BG group membership
PlayerRelogin(plr);
PlayerAddedToBGCheckIfBGIsRunning(plr);
AddOrSetPlayerToCorrectBgGroup(plr, guid, team);
// Log
@ -992,6 +1162,38 @@ void BattleGround::AddOrSetPlayerToCorrectBgGroup(Player *plr, uint64 plr_guid,
}
}
// This method should be called when player logs into running battleground
void BattleGround::EventPlayerLoggedIn(Player* player, uint64 plr_guid)
{
// player is correct pointer
for(std::deque<uint64>::iterator itr = m_OfflineQueue.begin(); itr != m_OfflineQueue.end(); ++itr)
{
if( *itr == plr_guid )
{
m_OfflineQueue.erase(itr);
break;
}
}
m_Players[plr_guid].OfflineRemoveTime = 0;
PlayerAddedToBGCheckIfBGIsRunning(player);
// if battleground is starting, then add preparation aura
// we don't have to do that, because preparation aura isn't removed when player logs out
}
// This method should be called when player logs out from running battleground
void BattleGround::EventPlayerLoggedOut(Player* player)
{
// player is correct pointer, it is checked in WorldSession::LogoutPlayer()
m_OfflineQueue.push_back(player->GetGUID());
m_Players[player->GetGUID()].OfflineRemoveTime = sWorld.GetGameTime() + MAX_OFFLINE_TIME;
if( GetStatus() == STATUS_IN_PROGRESS )
{
if( isBattleGround() )
EventPlayerDroppedFlag(player);
else
CheckArenaWinConditions();
}
}
/* This method should be called only once ... it adds pointer to queue */
void BattleGround::AddToBGFreeSlotQueue()
@ -1024,7 +1226,7 @@ void BattleGround::RemoveFromBGFreeSlotQueue()
// returns the number how many players can join battleground to MaxPlayersPerTeam
uint32 BattleGround::GetFreeSlotsForTeam(uint32 Team) const
{
//if BG is starting ... invite anyone
//return free slot count to MaxPlayerPerTeam
if (GetStatus() == STATUS_WAIT_JOIN || GetStatus() == STATUS_IN_PROGRESS)
return (GetInvitedCount(Team) < GetMaxPlayersPerTeam()) ? GetMaxPlayersPerTeam() - GetInvitedCount(Team) : 0;
@ -1357,19 +1559,30 @@ bool BattleGround::AddSpiritGuide(uint32 type, float x, float y, float z, float
return true;
}
void BattleGround::SendMessageToAll(char const* text)
void BattleGround::SendMessageToAll(int32 entry, ChatMsg type, Player const* source)
{
WorldPacket data;
ChatHandler::FillMessageData(&data, NULL, CHAT_MSG_BG_SYSTEM_NEUTRAL, LANG_UNIVERSAL, NULL, 0, text, NULL);
SendPacketToAll(&data);
MaNGOS::BattleGroundChatBuilder bg_builder(type, entry, source);
MaNGOS::LocalizedPacketDo<MaNGOS::BattleGroundChatBuilder> bg_do(bg_builder);
BroadcastWorker(bg_do);
}
void BattleGround::SendMessageToAll(int32 entry)
void BattleGround::PSendMessageToAll(int32 entry, ChatMsg type, Player const* source, ...)
{
char const* text = GetMangosString(entry);
WorldPacket data;
ChatHandler::FillMessageData(&data, NULL, CHAT_MSG_BG_SYSTEM_NEUTRAL, LANG_UNIVERSAL, NULL, 0, text, NULL);
SendPacketToAll(&data);
va_list ap;
va_start(ap, source);
MaNGOS::BattleGroundChatBuilder bg_builder(type, entry, source, &ap);
MaNGOS::LocalizedPacketDo<MaNGOS::BattleGroundChatBuilder> bg_do(bg_builder);
BroadcastWorker(bg_do);
va_end(ap);
}
void BattleGround::SendMessage2ToAll(int32 entry, ChatMsg type, Player const* source, int32 arg1, int32 arg2)
{
MaNGOS::BattleGround2ChatBuilder bg_builder(type, entry, source, arg1, arg2);
MaNGOS::LocalizedPacketDo<MaNGOS::BattleGround2ChatBuilder> bg_do(bg_builder);
BroadcastWorker(bg_do);
}
void BattleGround::EndNow()
@ -1381,13 +1594,6 @@ void BattleGround::EndNow()
sBattleGroundMgr.m_BattleGroundQueues[BattleGroundMgr::BGQueueTypeId(GetTypeID(), GetArenaType())].BGEndedRemoveInvites(this);
}
// Battleground messages are localized using the dbc lang, they are not client language dependent
const char *BattleGround::GetMangosString(int32 entry)
{
// FIXME: now we have different DBC locales and need localized message for each target client
return objmgr.GetMangosStringForDBCLocale(entry);
}
/*
important notice:
buffs aren't spawned/despawned when players captures anything
@ -1441,7 +1647,7 @@ void BattleGround::HandleKillPlayer( Player *player, Player *killer )
UpdatePlayerScore(killer, SCORE_HONORABLE_KILLS, 1);
UpdatePlayerScore(killer, SCORE_KILLING_BLOWS, 1);
for(std::map<uint64, BattleGroundPlayer>::iterator itr = m_Players.begin(); itr != m_Players.end(); ++itr)
for(BattleGroundPlayerMap::iterator itr = m_Players.begin(); itr != m_Players.end(); ++itr)
{
Player *plr = objmgr.GetPlayer(itr->first);
@ -1461,21 +1667,26 @@ void BattleGround::HandleKillPlayer( Player *player, Player *killer )
// used in same faction arena matches mainly
uint32 BattleGround::GetPlayerTeam(uint64 guid)
{
std::map<uint64, BattleGroundPlayer>::const_iterator itr = m_Players.find(guid);
BattleGroundPlayerMap::const_iterator itr = m_Players.find(guid);
if(itr!=m_Players.end())
return itr->second.Team;
return 0;
}
uint32 BattleGround::GetOtherTeam(uint32 teamId)
{
return (teamId) ? ((teamId == ALLIANCE) ? HORDE : ALLIANCE) : 0;
}
bool BattleGround::IsPlayerInBattleGround(uint64 guid)
{
std::map<uint64, BattleGroundPlayer>::const_iterator itr = m_Players.find(guid);
if(itr!=m_Players.end())
BattleGroundPlayerMap::const_iterator itr = m_Players.find(guid);
if(itr != m_Players.end())
return true;
return false;
}
void BattleGround::PlayerRelogin(Player* plr)
void BattleGround::PlayerAddedToBGCheckIfBGIsRunning(Player* plr)
{
if(GetStatus() != STATUS_WAIT_LEAVE)
return;
@ -1488,14 +1699,14 @@ void BattleGround::PlayerRelogin(Player* plr)
sBattleGroundMgr.BuildPvpLogDataPacket(&data, this);
plr->GetSession()->SendPacket(&data);
sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, this, plr->GetTeam(), plr->GetBattleGroundQueueIndex(bgQueueTypeId), STATUS_IN_PROGRESS, TIME_TO_AUTOREMOVE, GetStartTime());
sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, this, plr->GetBattleGroundQueueIndex(bgQueueTypeId), STATUS_IN_PROGRESS, TIME_TO_AUTOREMOVE, GetStartTime());
plr->GetSession()->SendPacket(&data);
}
uint32 BattleGround::GetAlivePlayersCountByTeam(uint32 Team) const
{
int count = 0;
for(std::map<uint64, BattleGroundPlayer>::const_iterator itr = m_Players.begin(); itr != m_Players.end(); ++itr)
for(BattleGroundPlayerMap::const_iterator itr = m_Players.begin(); itr != m_Players.end(); ++itr)
{
if(itr->second.Team == Team)
{
@ -1507,6 +1718,14 @@ uint32 BattleGround::GetAlivePlayersCountByTeam(uint32 Team) const
return count;
}
void BattleGround::CheckArenaWinConditions()
{
if( !GetAlivePlayersCountByTeam(ALLIANCE) && GetPlayersCountByTeam(HORDE) )
EndBattleGround(HORDE);
else if( GetPlayersCountByTeam(ALLIANCE) && !GetAlivePlayersCountByTeam(HORDE) )
EndBattleGround(ALLIANCE);
}
void BattleGround::SetBgRaid( uint32 TeamID, Group *bg_raid )
{
Group* &old_raid = TeamID == ALLIANCE ? m_BgRaids[BG_TEAM_ALLIANCE] : m_BgRaids[BG_TEAM_HORDE];
@ -1518,4 +1737,4 @@ void BattleGround::SetBgRaid( uint32 TeamID, Group *bg_raid )
WorldSafeLocsEntry const* BattleGround::GetClosestGraveYard( Player* player )
{
return objmgr.GetClosestGraveYard( player->GetPositionX(), player->GetPositionY(), player->GetPositionZ(), player->GetMapId(), player->GetTeam() );
}
}

View file

@ -89,15 +89,19 @@ enum BattleGroundTimeIntervals
INVITATION_REMIND_TIME = 60000, // ms
INVITE_ACCEPT_WAIT_TIME = 80000, // ms
TIME_TO_AUTOREMOVE = 120000, // ms
MAX_OFFLINE_TIME = 300000, // ms
START_DELAY0 = 120000, // ms
START_DELAY1 = 60000, // ms
START_DELAY2 = 30000, // ms
START_DELAY3 = 15000, // ms used only in arena
MAX_OFFLINE_TIME = 300, // secs
RESPAWN_ONE_DAY = 86400, // secs
RESPAWN_IMMEDIATELY = 0, // secs
BUFF_RESPAWN_TIME = 180, // secs
BG_HONOR_SCORE_TICKS = 330 // points
};
enum BattleGroundStartTimeIntervals
{
BG_START_DELAY_2M = 120000, // ms (2 minutes)
BG_START_DELAY_1M = 60000, // ms (1 minute)
BG_START_DELAY_30S = 30000, // ms (30 seconds)
BG_START_DELAY_15S = 15000, // ms (15 seconds) Used only in arena
BG_START_DELAY_NONE = 0, // ms
};
enum BattleGroundBuffObjects
@ -120,7 +124,7 @@ enum BattleGroundStatus
struct BattleGroundPlayer
{
uint32 LastOnlineTime; // for tracking and removing offline players from queue after 5 minutes
time_t OfflineRemoveTime; // for tracking and removing offline players from queue after 5 minutes
uint32 Team; // Player's team
};
@ -214,6 +218,24 @@ enum BattleGroundTeamId
};
#define BG_TEAMS_COUNT 2
enum BattleGroundStartingEvents
{
BG_STARTING_EVENT_NONE = 0x00,
BG_STARTING_EVENT_1 = 0x01,
BG_STARTING_EVENT_2 = 0x02,
BG_STARTING_EVENT_3 = 0x04,
BG_STARTING_EVENT_4 = 0x08
};
enum BattleGroundStartingEventsIds
{
BG_STARTING_EVENT_FIRST = 0,
BG_STARTING_EVENT_SECOND = 1,
BG_STARTING_EVENT_THIRD = 2,
BG_STARTING_EVENT_FOURTH = 3
};
#define BG_STARTING_EVENT_COUNT 4
enum BattleGroundJoinError
{
BG_JOIN_ERR_OK = 0,
@ -266,6 +288,8 @@ class BattleGround
return true;
}
virtual void Reset(); // resets all common properties for battlegrounds, must be implemented and called in BG subclass
virtual void StartingEventCloseDoors() {}
virtual void StartingEventOpenDoors() {}
/* Battleground */
// Get methods:
@ -274,6 +298,7 @@ class BattleGround
BGQueueIdBasedOnLevel GetQueueId() const { return m_QueueId; }
uint32 GetInstanceID() const { return m_InstanceID; }
BattleGroundStatus GetStatus() const { return m_Status; }
uint32 GetClientInstanceID() const { return m_ClientInstanceID; }
uint32 GetStartTime() const { return m_StartTime; }
uint32 GetEndTime() const { return m_EndTime; }
uint32 GetLastResurrectTime() const { return m_LastResurrectTime; }
@ -290,6 +315,7 @@ class BattleGround
uint8 GetArenaType() const { return m_ArenaType; }
uint8 GetWinner() const { return m_Winner; }
uint32 GetBattlemasterEntry() const;
uint32 GetBonusHonorFromKill(uint32 kills) const;
// Set methods:
void SetName(char const* Name) { m_Name = Name; }
@ -303,6 +329,7 @@ class BattleGround
}
void SetInstanceID(uint32 InstanceID) { m_InstanceID = InstanceID; }
void SetStatus(BattleGroundStatus Status) { m_Status = Status; }
void SetClientInstanceID(uint32 InstanceID) { m_ClientInstanceID = InstanceID; }
void SetStartTime(uint32 Time) { m_StartTime = Time; }
void SetEndTime(uint32 Time) { m_EndTime = Time; }
void SetLastResurrectTime(uint32 Time) { m_LastResurrectTime = Time; }
@ -342,7 +369,6 @@ class BattleGround
typedef std::map<uint64, BattleGroundPlayer> BattleGroundPlayerMap;
BattleGroundPlayerMap const& GetPlayers() const { return m_Players; }
uint32 GetPlayersSize() const { return m_Players.size(); }
uint32 GetRemovedPlayersSize() const { return m_RemovedPlayers.size(); }
std::map<uint64, BattleGroundScore*>::const_iterator GetPlayerScoresBegin() const { return m_PlayerScores.begin(); }
std::map<uint64, BattleGroundScore*>::const_iterator GetPlayerScoresEnd() const { return m_PlayerScores.end(); }
@ -374,6 +400,10 @@ class BattleGround
virtual void FillInitialWorldStates(WorldPacket& /*data*/) {}
void SendPacketToTeam(uint32 TeamID, WorldPacket *packet, Player *sender = NULL, bool self = true);
void SendPacketToAll(WorldPacket *packet);
template<class Do>
void BroadcastWorker(Do& _do);
void PlaySoundToTeam(uint32 SoundID, uint32 TeamID);
void PlaySoundToAll(uint32 SoundID);
void CastSpellOnTeam(uint32 SpellID, uint32 TeamID);
@ -387,8 +417,11 @@ class BattleGround
void EndBattleGround(uint32 winner);
void BlockMovement(Player *plr);
void SendMessageToAll(char const* text);
void SendMessageToAll(int32 entry);
void SendMessageToAll(int32 entry, ChatMsg type, Player const* source = NULL);
void PSendMessageToAll(int32 entry, ChatMsg type, Player const* source, ... );
// specialized version with 2 string id args
void SendMessage2ToAll(int32 entry, ChatMsg type, Player const* source, int32 strId1 = 0, int32 strId2 = 0);
/* Raid Group */
Group *GetBgRaid(uint32 TeamID) const { return TeamID == ALLIANCE ? m_BgRaids[BG_TEAM_ALLIANCE] : m_BgRaids[BG_TEAM_HORDE]; }
@ -409,9 +442,10 @@ class BattleGround
// used for rated arena battles
void SetArenaTeamIdForTeam(uint32 Team, uint32 ArenaTeamId) { m_ArenaTeamIds[GetTeamIndexByTeamId(Team)] = ArenaTeamId; }
uint32 GetArenaTeamIdForTeam(uint32 Team) const { return m_ArenaTeamIds[GetTeamIndexByTeamId(Team)]; }
uint32 GetArenaTeamIdForTeam(uint32 Team) const { return m_ArenaTeamIds[GetTeamIndexByTeamId(Team)]; }
void SetArenaTeamRatingChangeForTeam(uint32 Team, int32 RatingChange) { m_ArenaTeamRatingChanges[GetTeamIndexByTeamId(Team)] = RatingChange; }
int32 GetArenaTeamRatingChangeForTeam(uint32 Team) const { return m_ArenaTeamRatingChanges[GetTeamIndexByTeamId(Team)]; }
int32 GetArenaTeamRatingChangeForTeam(uint32 Team) const { return m_ArenaTeamRatingChanges[GetTeamIndexByTeamId(Team)]; }
void CheckArenaWinConditions();
/* Triggers handle */
// must be implemented in BG subclass
@ -420,10 +454,11 @@ class BattleGround
virtual void HandleKillPlayer(Player *player, Player *killer);
/* Battleground events */
/* these functions will return true event is possible, but false if player is bugger */
virtual void EventPlayerDroppedFlag(Player* /*player*/) {}
virtual void EventPlayerClickedOnFlag(Player* /*player*/, GameObject* /*target_obj*/) {}
virtual void EventPlayerCapturedFlag(Player* /*player*/) {}
void EventPlayerLoggedIn(Player* player, uint64 plr_guid);
void EventPlayerLoggedOut(Player* player);
/* Death related */
virtual WorldSafeLocsEntry const* GetClosestGraveYard(Player* player);
@ -452,20 +487,20 @@ class BattleGround
void DoorOpen(uint32 type);
void DoorClose(uint32 type);
const char *GetMangosString(int32 entry);
virtual bool HandlePlayerUnderMap(Player * /*plr*/) { return false; }
// since arenas can be AvA or Hvh, we have to get the "temporary" team of a player
uint32 GetPlayerTeam(uint64 guid);
uint32 GetOtherTeam(uint32 teamId);
bool IsPlayerInBattleGround(uint64 guid);
void PlayerRelogin(Player* plr);
void SetDeleteThis() {m_SetDeleteThis = true;}
protected:
//this method is called, when BG cannot spawn its own spirit guide, or something is wrong, It correctly ends BattleGround
void EndNow();
void PlayerAddedToBGCheckIfBGIsRunning(Player* plr);
/* Scorekeeping */
// Player scores
@ -479,9 +514,12 @@ class BattleGround
std::map<uint64, std::vector<uint64> > m_ReviveQueue;
/*
this is important variable used for invitation messages
these are important variables used for starting messages
*/
uint8 m_Events;
BattleGroundStartTimeIntervals m_StartDelayTimes[BG_STARTING_EVENT_COUNT];
//this must be filled in constructors!
uint32 m_StartMessageIds[BG_STARTING_EVENT_COUNT];
bool m_BuffChange;
@ -490,6 +528,7 @@ class BattleGround
BattleGroundTypeId m_TypeID;
uint32 m_InstanceID; //BattleGround Instance's GUID!
BattleGroundStatus m_Status;
uint32 m_ClientInstanceID; //the instance-id which is sent to the client and without any other internal use
uint32 m_StartTime;
uint32 m_EndTime;
uint32 m_LastResurrectTime;
@ -507,7 +546,7 @@ class BattleGround
/* Player lists */
std::vector<uint64> m_ResurrectQueue; // Player GUID
std::map<uint64, uint8> m_RemovedPlayers; // uint8 is remove type (0 - bgqueue, 1 - bg, 2 - resurrect queue)
std::deque<uint64> m_OfflineQueue; // Player GUID
/* Invited counters are useful for player invitation to BG - do not allow, if BG is started to one faction to have 2 more players than another faction */
/* Invited counters will be changed only when removing already invited player from queue, removing player from battleground and inviting player to BG */

View file

@ -19,10 +19,20 @@
#include "Player.h"
#include "BattleGround.h"
#include "BattleGroundAA.h"
#include "Language.h"
BattleGroundAA::BattleGroundAA()
{
m_StartDelayTimes[BG_STARTING_EVENT_FIRST] = BG_START_DELAY_1M;
m_StartDelayTimes[BG_STARTING_EVENT_SECOND] = BG_START_DELAY_30S;
m_StartDelayTimes[BG_STARTING_EVENT_THIRD] = BG_START_DELAY_15S;
m_StartDelayTimes[BG_STARTING_EVENT_FOURTH] = BG_START_DELAY_NONE;
//we must set messageIds
m_StartMessageIds[BG_STARTING_EVENT_FIRST] = LANG_ARENA_ONE_MINUTE;
m_StartMessageIds[BG_STARTING_EVENT_SECOND] = LANG_ARENA_THIRTY_SECONDS;
m_StartMessageIds[BG_STARTING_EVENT_THIRD] = LANG_ARENA_FIFTEEN_SECONDS;
m_StartMessageIds[BG_STARTING_EVENT_FOURTH] = LANG_ARENA_HAS_BEGUN;
}
BattleGroundAA::~BattleGroundAA()
@ -35,6 +45,14 @@ void BattleGroundAA::Update(uint32 diff)
BattleGround::Update(diff);
}
void BattleGroundAA::StartingEventCloseDoors()
{
}
void BattleGroundAA::StartingEventOpenDoors()
{
}
void BattleGroundAA::AddPlayer(Player *plr)
{
BattleGround::AddPlayer(plr);

View file

@ -39,6 +39,9 @@ class BattleGroundAA : public BattleGround
/* inherited from BattlegroundClass */
virtual void AddPlayer(Player *plr);
virtual void StartingEventCloseDoors();
virtual void StartingEventOpenDoors();
void RemovePlayer(Player *plr, uint64 guid);
void HandleAreaTrigger(Player *Source, uint32 Trigger);
bool SetupBattleGround();

View file

@ -21,9 +21,7 @@
#include "BattleGround.h"
#include "BattleGroundAB.h"
#include "Creature.h"
#include "Chat.h"
#include "ObjectMgr.h"
#include "MapManager.h"
#include "Language.h"
#include "Util.h"
#include "WorldPacket.h"
@ -33,6 +31,11 @@ BattleGroundAB::BattleGroundAB()
m_BuffChange = true;
m_BgObjects.resize(BG_AB_OBJECT_MAX);
m_BgCreatures.resize(BG_AB_ALL_NODES_COUNT);
m_StartMessageIds[BG_STARTING_EVENT_FIRST] = LANG_BG_AB_START_TWO_MINUTES;
m_StartMessageIds[BG_STARTING_EVENT_SECOND] = LANG_BG_AB_START_ONE_MINUTE;
m_StartMessageIds[BG_STARTING_EVENT_THIRD] = LANG_BG_AB_START_HALF_MINUTE;
m_StartMessageIds[BG_STARTING_EVENT_FOURTH] = LANG_BG_AB_HAS_BEGUN;
}
BattleGroundAB::~BattleGroundAB()
@ -43,81 +46,7 @@ void BattleGroundAB::Update(uint32 diff)
{
BattleGround::Update(diff);
if( GetStatus() == STATUS_WAIT_JOIN && GetPlayersSize() )
{
ModifyStartDelayTime(diff);
if( !(m_Events & 0x01) )
{
m_Events |= 0x01;
// setup here, only when at least one player has ported to the map
if(!SetupBattleGround())
{
EndNow();
return;
}
sLog.outDebug("Arathi Basin: entering state STATUS_WAIT_JOIN ...");
// despawn banners, auras and buffs
for (int obj = BG_AB_OBJECT_BANNER_NEUTRAL; obj < BG_AB_DYNAMIC_NODES_COUNT * 8; ++obj)
SpawnBGObject(obj, RESPAWN_ONE_DAY);
for (int i = 0; i < BG_AB_DYNAMIC_NODES_COUNT * 3; ++i)
SpawnBGObject(BG_AB_OBJECT_SPEEDBUFF_STABLES + i, RESPAWN_ONE_DAY);
// Starting doors
SpawnBGObject(BG_AB_OBJECT_GATE_A, RESPAWN_IMMEDIATELY);
SpawnBGObject(BG_AB_OBJECT_GATE_H, RESPAWN_IMMEDIATELY);
DoorClose(BG_AB_OBJECT_GATE_A);
DoorClose(BG_AB_OBJECT_GATE_H);
// Starting base spirit guides
_NodeOccupied(BG_AB_SPIRIT_ALIANCE,ALLIANCE);
_NodeOccupied(BG_AB_SPIRIT_HORDE,HORDE);
SetStartDelayTime(START_DELAY0);
}
// After 1 minute, warning is signalled
else if( GetStartDelayTime() <= START_DELAY1 && !(m_Events & 0x04) )
{
m_Events |= 0x04;
SendMessageToAll(GetMangosString(LANG_BG_AB_ONEMINTOSTART));
}
// After 1,5 minute, warning is signalled
else if( GetStartDelayTime() <= START_DELAY2 && !(m_Events & 0x08) )
{
m_Events |= 0x08;
SendMessageToAll(GetMangosString(LANG_BG_AB_HALFMINTOSTART));
}
// After 2 minutes, gates OPEN ! x)
else if( GetStartDelayTime() < 0 && !(m_Events & 0x10) )
{
m_Events |= 0x10;
SendMessageToAll(GetMangosString(LANG_BG_AB_STARTED));
// spawn neutral banners
for (int banner = BG_AB_OBJECT_BANNER_NEUTRAL, i = 0; i < 5; banner += 8, ++i)
SpawnBGObject(banner, RESPAWN_IMMEDIATELY);
for (int i = 0; i < BG_AB_DYNAMIC_NODES_COUNT; ++i)
{
//randomly select buff to spawn
uint8 buff = urand(0, 2);
SpawnBGObject(BG_AB_OBJECT_SPEEDBUFF_STABLES + buff + i * 3, RESPAWN_IMMEDIATELY);
}
DoorOpen(BG_AB_OBJECT_GATE_A);
DoorOpen(BG_AB_OBJECT_GATE_H);
PlaySoundToAll(SOUND_BG_START);
SetStatus(STATUS_IN_PROGRESS);
for(BattleGroundPlayerMap::const_iterator itr = GetPlayers().begin(); itr != GetPlayers().end(); ++itr)
if(Player* plr = objmgr.GetPlayer(itr->first))
plr->RemoveAurasDueToSpell(SPELL_PREPARATION);
}
}
else if( GetStatus() == STATUS_IN_PROGRESS )
if( GetStatus() == STATUS_IN_PROGRESS )
{
int team_points[2] = { 0, 0 };
@ -154,13 +83,19 @@ void BattleGroundAB::Update(uint32 diff)
_SendNodeUpdate(node);
_NodeOccupied(node,(teamIndex == 0) ? ALLIANCE:HORDE);
// Message to chatlog
char buf[256];
uint8 type = (teamIndex == 0) ? CHAT_MSG_BG_SYSTEM_ALLIANCE : CHAT_MSG_BG_SYSTEM_HORDE;
sprintf(buf, GetMangosString(LANG_BG_AB_NODE_TAKEN), (teamIndex == 0) ? GetMangosString(LANG_BG_AB_ALLY) : GetMangosString(LANG_BG_AB_HORDE), _GetNodeName(node));
WorldPacket data;
ChatHandler::FillMessageData(&data, NULL, type, LANG_UNIVERSAL, NULL, 0, buf, NULL);
SendPacketToAll(&data);
PlaySoundToAll((teamIndex == 0) ? SOUND_NODE_CAPTURED_ALLIANCE : SOUND_NODE_CAPTURED_HORDE);
if(teamIndex == 0)
{
// FIXME: team and node names not localized
SendMessage2ToAll(LANG_BG_AB_NODE_TAKEN,CHAT_MSG_BG_SYSTEM_ALLIANCE,NULL,LANG_BG_AB_ALLY,_GetNodeNameId(node));
PlaySoundToAll(SOUND_NODE_CAPTURED_ALLIANCE);
}
else
{
// FIXME: team and node names not localized
SendMessage2ToAll(LANG_BG_AB_NODE_TAKEN,CHAT_MSG_BG_SYSTEM_HORDE,NULL,LANG_BG_AB_HORDE,_GetNodeNameId(node));
PlaySoundToAll(SOUND_NODE_CAPTURED_HORDE);
}
}
}
@ -182,22 +117,22 @@ void BattleGroundAB::Update(uint32 diff)
m_TeamScores[team] += BG_AB_TickPoints[points];
m_HonorScoreTics[team] += BG_AB_TickPoints[points];
m_ReputationScoreTics[team] += BG_AB_TickPoints[points];
if( m_ReputationScoreTics[team] >= 200 )
if( m_ReputationScoreTics[team] >= m_ReputationTics )
{
(team == BG_TEAM_ALLIANCE) ? RewardReputationToTeam(509, 10, ALLIANCE) : RewardReputationToTeam(510, 10, HORDE);
m_ReputationScoreTics[team] -= 200;
m_ReputationScoreTics[team] -= m_ReputationTics;
}
if( m_HonorScoreTics[team] >= BG_HONOR_SCORE_TICKS )
if( m_HonorScoreTics[team] >= m_HonorTics )
{
(team == BG_TEAM_ALLIANCE) ? RewardHonorToTeam(20, ALLIANCE) : RewardHonorToTeam(20, HORDE);
m_HonorScoreTics[team] -= BG_HONOR_SCORE_TICKS;
RewardHonorToTeam(GetBonusHonorFromKill(1), (team == BG_TEAM_ALLIANCE) ? ALLIANCE : HORDE);
m_HonorScoreTics[team] -= m_HonorTics;
}
if( !m_IsInformedNearVictory && m_TeamScores[team] > 1800 )
{
if( team == BG_TEAM_ALLIANCE )
SendMessageToAll(GetMangosString(LANG_BG_AB_A_NEAR_VICTORY));
SendMessageToAll(LANG_BG_AB_A_NEAR_VICTORY, CHAT_MSG_BG_SYSTEM_NEUTRAL);
else
SendMessageToAll(GetMangosString(LANG_BG_AB_H_NEAR_VICTORY));
SendMessageToAll(LANG_BG_AB_H_NEAR_VICTORY, CHAT_MSG_BG_SYSTEM_NEUTRAL);
PlaySoundToAll(SOUND_NEAR_VICTORY);
m_IsInformedNearVictory = true;
}
@ -219,6 +154,40 @@ void BattleGroundAB::Update(uint32 diff)
}
}
void BattleGroundAB::StartingEventCloseDoors()
{
// despawn banners, auras and buffs
for (int obj = BG_AB_OBJECT_BANNER_NEUTRAL; obj < BG_AB_DYNAMIC_NODES_COUNT * 8; ++obj)
SpawnBGObject(obj, RESPAWN_ONE_DAY);
for (int i = 0; i < BG_AB_DYNAMIC_NODES_COUNT * 3; ++i)
SpawnBGObject(BG_AB_OBJECT_SPEEDBUFF_STABLES + i, RESPAWN_ONE_DAY);
// Starting doors
DoorClose(BG_AB_OBJECT_GATE_A);
DoorClose(BG_AB_OBJECT_GATE_H);
SpawnBGObject(BG_AB_OBJECT_GATE_A, RESPAWN_IMMEDIATELY);
SpawnBGObject(BG_AB_OBJECT_GATE_H, RESPAWN_IMMEDIATELY);
// Starting base spirit guides
_NodeOccupied(BG_AB_SPIRIT_ALIANCE,ALLIANCE);
_NodeOccupied(BG_AB_SPIRIT_HORDE,HORDE);
}
void BattleGroundAB::StartingEventOpenDoors()
{
// spawn neutral banners
for (int banner = BG_AB_OBJECT_BANNER_NEUTRAL, i = 0; i < 5; banner += 8, ++i)
SpawnBGObject(banner, RESPAWN_IMMEDIATELY);
for (int i = 0; i < BG_AB_DYNAMIC_NODES_COUNT; ++i)
{
//randomly select buff to spawn
uint8 buff = urand(0, 2);
SpawnBGObject(BG_AB_OBJECT_SPEEDBUFF_STABLES + buff + i * 3, RESPAWN_IMMEDIATELY);
}
DoorOpen(BG_AB_OBJECT_GATE_A);
DoorOpen(BG_AB_OBJECT_GATE_H);
}
void BattleGroundAB::AddPlayer(Player *plr)
{
BattleGround::AddPlayer(plr);
@ -303,24 +272,19 @@ void BattleGroundAB::_DelBanner(uint8 node, uint8 type, uint8 teamIndex)
SpawnBGObject(obj, RESPAWN_ONE_DAY);
}
const char* BattleGroundAB::_GetNodeName(uint8 node)
int32 BattleGroundAB::_GetNodeNameId(uint8 node)
{
switch (node)
{
case BG_AB_NODE_STABLES:
return GetMangosString(LANG_BG_AB_NODE_STABLES);
case BG_AB_NODE_BLACKSMITH:
return GetMangosString(LANG_BG_AB_NODE_BLACKSMITH);
case BG_AB_NODE_FARM:
return GetMangosString(LANG_BG_AB_NODE_FARM);
case BG_AB_NODE_LUMBER_MILL:
return GetMangosString(LANG_BG_AB_NODE_LUMBER_MILL);
case BG_AB_NODE_GOLD_MINE:
return GetMangosString(LANG_BG_AB_NODE_GOLD_MINE);
case BG_AB_NODE_STABLES: return LANG_BG_AB_NODE_STABLES;
case BG_AB_NODE_BLACKSMITH: return LANG_BG_AB_NODE_BLACKSMITH;
case BG_AB_NODE_FARM: return LANG_BG_AB_NODE_FARM;
case BG_AB_NODE_LUMBER_MILL:return LANG_BG_AB_NODE_LUMBER_MILL;
case BG_AB_NODE_GOLD_MINE: return LANG_BG_AB_NODE_GOLD_MINE;
default:
ASSERT(0);
}
return "";
return 0;
}
void BattleGroundAB::FillInitialWorldStates(WorldPacket& data)
@ -451,10 +415,6 @@ void BattleGroundAB::EventPlayerClickedOnFlag(Player *source, GameObject* /*targ
uint8 teamIndex = GetTeamIndexByTeamId(source->GetTeam());
// Message to chatlog
char buf[256];
uint8 type = (teamIndex == 0) ? CHAT_MSG_BG_SYSTEM_ALLIANCE : CHAT_MSG_BG_SYSTEM_HORDE;
// Check if player really could use this banner, not cheated
if( !(m_Nodes[node] == 0 || teamIndex == m_Nodes[node]%2) )
return;
@ -473,7 +433,13 @@ void BattleGroundAB::EventPlayerClickedOnFlag(Player *source, GameObject* /*targ
_CreateBanner(node, BG_AB_NODE_TYPE_CONTESTED, teamIndex, true);
_SendNodeUpdate(node);
m_NodeTimers[node] = BG_AB_FLAG_CAPTURING_TIME;
sprintf(buf, GetMangosString(LANG_BG_AB_NODE_CLAIMED), _GetNodeName(node), (teamIndex == 0) ? GetMangosString(LANG_BG_AB_ALLY) : GetMangosString(LANG_BG_AB_HORDE));
// FIXME: team and node names not localized
if(teamIndex == 0)
SendMessage2ToAll(LANG_BG_AB_NODE_CLAIMED,CHAT_MSG_BG_SYSTEM_ALLIANCE, source, _GetNodeNameId(node), LANG_BG_AB_ALLY);
else
SendMessage2ToAll(LANG_BG_AB_NODE_CLAIMED,CHAT_MSG_BG_SYSTEM_HORDE, source, _GetNodeNameId(node), LANG_BG_AB_HORDE);
sound = SOUND_NODE_CLAIMED;
}
// If node is contested
@ -491,7 +457,12 @@ void BattleGroundAB::EventPlayerClickedOnFlag(Player *source, GameObject* /*targ
_CreateBanner(node, BG_AB_NODE_TYPE_CONTESTED, teamIndex, true);
_SendNodeUpdate(node);
m_NodeTimers[node] = BG_AB_FLAG_CAPTURING_TIME;
sprintf(buf, GetMangosString(LANG_BG_AB_NODE_ASSAULTED), _GetNodeName(node));
// FIXME: node names not localized
if(teamIndex == 0)
SendMessage2ToAll(LANG_BG_AB_NODE_ASSAULTED,CHAT_MSG_BG_SYSTEM_ALLIANCE, source, _GetNodeNameId(node));
else
SendMessage2ToAll(LANG_BG_AB_NODE_ASSAULTED,CHAT_MSG_BG_SYSTEM_HORDE, source, _GetNodeNameId(node));
}
// If contested, change back to occupied
else
@ -506,7 +477,12 @@ void BattleGroundAB::EventPlayerClickedOnFlag(Player *source, GameObject* /*targ
_SendNodeUpdate(node);
m_NodeTimers[node] = 0;
_NodeOccupied(node,(teamIndex == 0) ? ALLIANCE:HORDE);
sprintf(buf, GetMangosString(LANG_BG_AB_NODE_DEFENDED), _GetNodeName(node));
// FIXME: node names not localized
if(teamIndex == 0)
SendMessage2ToAll(LANG_BG_AB_NODE_DEFENDED,CHAT_MSG_BG_SYSTEM_ALLIANCE, source, _GetNodeNameId(node));
else
SendMessage2ToAll(LANG_BG_AB_NODE_DEFENDED,CHAT_MSG_BG_SYSTEM_HORDE, source, _GetNodeNameId(node));
}
sound = (teamIndex == 0) ? SOUND_NODE_ASSAULTED_ALLIANCE : SOUND_NODE_ASSAULTED_HORDE;
}
@ -523,18 +499,24 @@ void BattleGroundAB::EventPlayerClickedOnFlag(Player *source, GameObject* /*targ
_SendNodeUpdate(node);
_NodeDeOccupied(node);
m_NodeTimers[node] = BG_AB_FLAG_CAPTURING_TIME;
sprintf(buf, GetMangosString(LANG_BG_AB_NODE_ASSAULTED), _GetNodeName(node));
// FIXME: node names not localized
if(teamIndex == 0)
SendMessage2ToAll(LANG_BG_AB_NODE_ASSAULTED,CHAT_MSG_BG_SYSTEM_ALLIANCE, source, _GetNodeNameId(node));
else
SendMessage2ToAll(LANG_BG_AB_NODE_ASSAULTED,CHAT_MSG_BG_SYSTEM_HORDE, source, _GetNodeNameId(node));
sound = (teamIndex == 0) ? SOUND_NODE_ASSAULTED_ALLIANCE : SOUND_NODE_ASSAULTED_HORDE;
}
WorldPacket data;
ChatHandler::FillMessageData(&data, source->GetSession(), type, LANG_UNIVERSAL, NULL, source->GetGUID(), buf, NULL);
SendPacketToAll(&data);
// If node is occupied again, send "X has taken the Y" msg.
if( m_Nodes[node] >= BG_AB_NODE_TYPE_OCCUPIED )
{
sprintf(buf, GetMangosString(LANG_BG_AB_NODE_TAKEN), (teamIndex == 0) ? GetMangosString(LANG_BG_AB_ALLY) : GetMangosString(LANG_BG_AB_HORDE), _GetNodeName(node));
ChatHandler::FillMessageData(&data, NULL, type, LANG_UNIVERSAL, NULL, 0, buf, NULL);
SendPacketToAll(&data);
// FIXME: team and node names not localized
if(teamIndex == 0)
SendMessage2ToAll(LANG_BG_AB_NODE_TAKEN,CHAT_MSG_BG_SYSTEM_ALLIANCE, NULL, LANG_BG_AB_ALLY, _GetNodeNameId(node));
else
SendMessage2ToAll(LANG_BG_AB_NODE_TAKEN,CHAT_MSG_BG_SYSTEM_HORDE, NULL, LANG_BG_AB_HORDE, _GetNodeNameId(node));
}
PlaySoundToAll(sound);
}
@ -591,6 +573,10 @@ void BattleGroundAB::Reset()
m_ReputationScoreTics[BG_TEAM_ALLIANCE] = 0;
m_ReputationScoreTics[BG_TEAM_HORDE] = 0;
m_IsInformedNearVictory = false;
bool isBGWeekend = false; //TODO FIXME - call sBattleGroundMgr.IsBGWeekend(m_TypeID); - you must also implement that call!
m_HonorTics = (isBGWeekend) ? BG_AB_ABBGWeekendHonorTicks : BG_AB_NotABBGWeekendHonorTicks;
m_ReputationTics = (isBGWeekend) ? BG_AB_ABBGWeekendReputationTicks : BG_AB_NotABBGWeekendReputationTicks;
for (uint8 i = 0; i < BG_AB_DYNAMIC_NODES_COUNT; ++i)
{
m_Nodes[i] = 0;
@ -604,6 +590,20 @@ void BattleGroundAB::Reset()
DelCreature(i);
}
void BattleGroundAB::EndBattleGround(uint32 winner)
{
//win reward
if( winner == ALLIANCE )
RewardHonorToTeam(GetBonusHonorFromKill(1), ALLIANCE);
if( winner == HORDE )
RewardHonorToTeam(GetBonusHonorFromKill(1), HORDE);
//complete map_end rewards (even if no team wins)
RewardHonorToTeam(GetBonusHonorFromKill(1), HORDE);
RewardHonorToTeam(GetBonusHonorFromKill(1), ALLIANCE);
BattleGround::EndBattleGround(winner);
}
WorldSafeLocsEntry const* BattleGroundAB::GetClosestGraveYard(Player* player)
{
uint8 teamIndex = GetTeamIndexByTeamId(player->GetTeam());

View file

@ -170,6 +170,11 @@ enum BG_AB_Sounds
SOUND_NEAR_VICTORY = 8456
};
#define BG_AB_NotABBGWeekendHonorTicks 330
#define BG_AB_ABBGWeekendHonorTicks 200
#define BG_AB_NotABBGWeekendReputationTicks 200
#define BG_AB_ABBGWeekendReputationTicks 150
// x, y, z, o
const float BG_AB_NodePositions[BG_AB_DYNAMIC_NODES_COUNT][4] = {
{1166.785f, 1200.132f, -56.70859f, 0.9075713f}, // stables
@ -238,10 +243,13 @@ class BattleGroundAB : public BattleGround
void Update(uint32 diff);
void AddPlayer(Player *plr);
virtual void StartingEventCloseDoors();
virtual void StartingEventOpenDoors();
void RemovePlayer(Player *plr,uint64 guid);
void HandleAreaTrigger(Player *Source, uint32 Trigger);
virtual bool SetupBattleGround();
virtual void Reset();
void EndBattleGround(uint32 winner);
virtual WorldSafeLocsEntry const* GetClosestGraveYard(Player* player);
/* Scorekeeping */
@ -263,7 +271,7 @@ class BattleGroundAB : public BattleGround
void _NodeOccupied(uint8 node,Team team);
void _NodeDeOccupied(uint8 node);
const char* _GetNodeName(uint8 node);
int32 _GetNodeNameId(uint8 node);
/* Nodes info:
0: neutral
@ -271,14 +279,18 @@ class BattleGroundAB : public BattleGround
2: horde contested
3: ally occupied
4: horde occupied */
uint8 m_Nodes[BG_AB_DYNAMIC_NODES_COUNT];
uint8 m_prevNodes[BG_AB_DYNAMIC_NODES_COUNT];
BG_AB_BannerTimer m_BannerTimers[BG_AB_DYNAMIC_NODES_COUNT];
int32 m_NodeTimers[BG_AB_DYNAMIC_NODES_COUNT];
uint32 m_TeamScores[2];
uint32 m_lastTick[2];
uint32 m_HonorScoreTics[2];
uint32 m_ReputationScoreTics[2];
bool m_IsInformedNearVictory;
uint8 m_Nodes[BG_AB_DYNAMIC_NODES_COUNT];
uint8 m_prevNodes[BG_AB_DYNAMIC_NODES_COUNT];
BG_AB_BannerTimer m_BannerTimers[BG_AB_DYNAMIC_NODES_COUNT];
int32 m_NodeTimers[BG_AB_DYNAMIC_NODES_COUNT];
uint32 m_TeamScores[2];
uint32 m_lastTick[2];
uint32 m_HonorScoreTics[2];
uint32 m_ReputationScoreTics[2];
bool m_IsInformedNearVictory;
uint32 m_HonorTics;
uint32 m_ReputationTics;
};
#endif

View file

@ -20,13 +20,16 @@
#include "Player.h"
#include "BattleGround.h"
#include "BattleGroundAV.h"
#include "Creature.h"
#include "MapManager.h"
#include "Language.h"
BattleGroundAV::BattleGroundAV()
{
//TODO FIX ME!
m_StartMessageIds[BG_STARTING_EVENT_FIRST] = LANG_BG_EY_START_TWO_MINUTES;
m_StartMessageIds[BG_STARTING_EVENT_SECOND] = LANG_BG_EY_START_ONE_MINUTE;
m_StartMessageIds[BG_STARTING_EVENT_THIRD] = LANG_BG_EY_START_HALF_MINUTE;
m_StartMessageIds[BG_STARTING_EVENT_FOURTH] = LANG_BG_EY_HAS_BEGUN;
}
BattleGroundAV::~BattleGroundAV()
@ -39,6 +42,14 @@ void BattleGroundAV::Update(uint32 diff)
BattleGround::Update(diff);
}
void BattleGroundAV::StartingEventCloseDoors()
{
}
void BattleGroundAV::StartingEventOpenDoors()
{
}
void BattleGroundAV::AddPlayer(Player *plr)
{
BattleGround::AddPlayer(plr);

View file

@ -46,6 +46,8 @@ class BattleGroundAV : public BattleGround
/* inherited from BattlegroundClass */
virtual void AddPlayer(Player *plr);
virtual void StartingEventCloseDoors();
virtual void StartingEventOpenDoors();
void RemovePlayer(Player *plr,uint64 guid);
void HandleAreaTrigger(Player *Source, uint32 Trigger);

View file

@ -20,15 +20,23 @@
#include "Player.h"
#include "BattleGround.h"
#include "BattleGroundBE.h"
#include "Creature.h"
#include "ObjectMgr.h"
#include "MapManager.h"
#include "WorldPacket.h"
#include "Language.h"
BattleGroundBE::BattleGroundBE()
{
m_BgObjects.resize(BG_BE_OBJECT_MAX);
m_StartDelayTimes[BG_STARTING_EVENT_FIRST] = BG_START_DELAY_1M;
m_StartDelayTimes[BG_STARTING_EVENT_SECOND] = BG_START_DELAY_30S;
m_StartDelayTimes[BG_STARTING_EVENT_THIRD] = BG_START_DELAY_15S;
m_StartDelayTimes[BG_STARTING_EVENT_FOURTH] = BG_START_DELAY_NONE;
//we must set messageIds
m_StartMessageIds[BG_STARTING_EVENT_FIRST] = LANG_ARENA_ONE_MINUTE;
m_StartMessageIds[BG_STARTING_EVENT_SECOND] = LANG_ARENA_THIRTY_SECONDS;
m_StartMessageIds[BG_STARTING_EVENT_THIRD] = LANG_ARENA_FIFTEEN_SECONDS;
m_StartMessageIds[BG_STARTING_EVENT_FOURTH] = LANG_ARENA_HAS_BEGUN;
}
BattleGroundBE::~BattleGroundBE()
@ -40,73 +48,30 @@ void BattleGroundBE::Update(uint32 diff)
{
BattleGround::Update(diff);
// after bg start we get there
if (GetStatus() == STATUS_WAIT_JOIN && GetPlayersSize())
{
ModifyStartDelayTime(diff);
if (!(m_Events & 0x01))
{
m_Events |= 0x01;
// setup here, only when at least one player has ported to the map
if(!SetupBattleGround())
{
EndNow();
return;
}
for(uint32 i = BG_BE_OBJECT_DOOR_1; i <= BG_BE_OBJECT_DOOR_4; i++)
SpawnBGObject(i, RESPAWN_IMMEDIATELY);
for(uint32 i = BG_BE_OBJECT_BUFF_1; i <= BG_BE_OBJECT_BUFF_2; i++)
SpawnBGObject(i, RESPAWN_ONE_DAY);
SetStartDelayTime(START_DELAY1);
SendMessageToAll(LANG_ARENA_ONE_MINUTE);
}
// After 30 seconds, warning is signalled
else if (GetStartDelayTime() <= START_DELAY2 && !(m_Events & 0x04))
{
m_Events |= 0x04;
SendMessageToAll(LANG_ARENA_THIRTY_SECONDS);
}
// After 15 seconds, warning is signalled
else if (GetStartDelayTime() <= START_DELAY3 && !(m_Events & 0x08))
{
m_Events |= 0x08;
SendMessageToAll(LANG_ARENA_FIFTEEN_SECONDS);
}
// delay expired (1 minute)
else if (GetStartDelayTime() <= 0 && !(m_Events & 0x10))
{
m_Events |= 0x10;
for(uint32 i = BG_BE_OBJECT_DOOR_1; i <= BG_BE_OBJECT_DOOR_2; i++)
DoorOpen(i);
for(uint32 i = BG_BE_OBJECT_BUFF_1; i <= BG_BE_OBJECT_BUFF_2; i++)
SpawnBGObject(i, 60);
SendMessageToAll(LANG_ARENA_BEGUN);
SetStatus(STATUS_IN_PROGRESS);
SetStartDelayTime(0);
for(BattleGroundPlayerMap::const_iterator itr = GetPlayers().begin(); itr != GetPlayers().end(); ++itr)
if(Player *plr = objmgr.GetPlayer(itr->first))
plr->RemoveAurasDueToSpell(SPELL_ARENA_PREPARATION);
if(!GetPlayersCountByTeam(ALLIANCE) && GetPlayersCountByTeam(HORDE))
EndBattleGround(HORDE);
else if(GetPlayersCountByTeam(ALLIANCE) && !GetPlayersCountByTeam(HORDE))
EndBattleGround(ALLIANCE);
}
}
/*if(GetStatus() == STATUS_IN_PROGRESS)
{
// update something
}*/
}
void BattleGroundBE::StartingEventCloseDoors()
{
for(uint32 i = BG_BE_OBJECT_DOOR_1; i <= BG_BE_OBJECT_DOOR_4; i++)
SpawnBGObject(i, RESPAWN_IMMEDIATELY);
for(uint32 i = BG_BE_OBJECT_BUFF_1; i <= BG_BE_OBJECT_BUFF_2; i++)
SpawnBGObject(i, RESPAWN_ONE_DAY);
}
void BattleGroundBE::StartingEventOpenDoors()
{
for(uint32 i = BG_BE_OBJECT_DOOR_1; i <= BG_BE_OBJECT_DOOR_2; i++)
DoorOpen(i);
for(uint32 i = BG_BE_OBJECT_BUFF_1; i <= BG_BE_OBJECT_BUFF_2; i++)
SpawnBGObject(i, 60);
}
void BattleGroundBE::AddPlayer(Player *plr)
{
BattleGround::AddPlayer(plr);
@ -127,10 +92,7 @@ void BattleGroundBE::RemovePlayer(Player* /*plr*/, uint64 /*guid*/)
UpdateWorldState(0x9f1, GetAlivePlayersCountByTeam(ALLIANCE));
UpdateWorldState(0x9f0, GetAlivePlayersCountByTeam(HORDE));
if(!GetAlivePlayersCountByTeam(ALLIANCE) && GetPlayersCountByTeam(HORDE))
EndBattleGround(HORDE);
else if(GetPlayersCountByTeam(ALLIANCE) && !GetAlivePlayersCountByTeam(HORDE))
EndBattleGround(ALLIANCE);
CheckArenaWinConditions();
}
void BattleGroundBE::HandleKillPlayer(Player *player, Player *killer)
@ -149,16 +111,7 @@ void BattleGroundBE::HandleKillPlayer(Player *player, Player *killer)
UpdateWorldState(0x9f1, GetAlivePlayersCountByTeam(ALLIANCE));
UpdateWorldState(0x9f0, GetAlivePlayersCountByTeam(HORDE));
if(!GetAlivePlayersCountByTeam(ALLIANCE))
{
// all opponents killed
EndBattleGround(HORDE);
}
else if(!GetAlivePlayersCountByTeam(HORDE))
{
// all opponents killed
EndBattleGround(ALLIANCE);
}
CheckArenaWinConditions();
}
bool BattleGroundBE::HandlePlayerUnderMap(Player *player)

View file

@ -59,6 +59,8 @@ class BattleGroundBE : public BattleGround
/* inherited from BattlegroundClass */
virtual void AddPlayer(Player *plr);
virtual void StartingEventCloseDoors();
virtual void StartingEventOpenDoors();
void RemovePlayer(Player *plr, uint64 guid);
void HandleAreaTrigger(Player *Source, uint32 Trigger);

View file

@ -19,10 +19,20 @@
#include "Player.h"
#include "BattleGround.h"
#include "BattleGroundDS.h"
#include "Language.h"
BattleGroundDS::BattleGroundDS()
{
m_StartDelayTimes[BG_STARTING_EVENT_FIRST] = BG_START_DELAY_1M;
m_StartDelayTimes[BG_STARTING_EVENT_SECOND] = BG_START_DELAY_30S;
m_StartDelayTimes[BG_STARTING_EVENT_THIRD] = BG_START_DELAY_15S;
m_StartDelayTimes[BG_STARTING_EVENT_FOURTH] = BG_START_DELAY_NONE;
//we must set messageIds
m_StartMessageIds[BG_STARTING_EVENT_FIRST] = LANG_ARENA_ONE_MINUTE;
m_StartMessageIds[BG_STARTING_EVENT_SECOND] = LANG_ARENA_THIRTY_SECONDS;
m_StartMessageIds[BG_STARTING_EVENT_THIRD] = LANG_ARENA_FIFTEEN_SECONDS;
m_StartMessageIds[BG_STARTING_EVENT_FOURTH] = LANG_ARENA_HAS_BEGUN;
}
BattleGroundDS::~BattleGroundDS()
@ -35,6 +45,14 @@ void BattleGroundDS::Update(uint32 diff)
BattleGround::Update(diff);
}
void BattleGroundDS::StartingEventCloseDoors()
{
}
void BattleGroundDS::StartingEventOpenDoors()
{
}
void BattleGroundDS::AddPlayer(Player *plr)
{
BattleGround::AddPlayer(plr);

View file

@ -39,6 +39,9 @@ class BattleGroundDS : public BattleGround
/* inherited from BattlegroundClass */
virtual void AddPlayer(Player *plr);
virtual void StartingEventCloseDoors();
virtual void StartingEventOpenDoors();
void RemovePlayer(Player *plr, uint64 guid);
void HandleAreaTrigger(Player *Source, uint32 Trigger);
bool SetupBattleGround();

View file

@ -21,9 +21,7 @@
#include "BattleGround.h"
#include "BattleGroundEY.h"
#include "Creature.h"
#include "Chat.h"
#include "ObjectMgr.h"
#include "MapManager.h"
#include "Language.h"
#include "WorldPacket.h"
#include "Util.h"
@ -37,6 +35,11 @@ BattleGroundEY::BattleGroundEY()
m_Points_Trigger[BLOOD_ELF] = TR_BLOOD_ELF_BUFF;
m_Points_Trigger[DRAENEI_RUINS] = TR_DRAENEI_RUINS_BUFF;
m_Points_Trigger[MAGE_TOWER] = TR_MAGE_TOWER_BUFF;
m_StartMessageIds[BG_STARTING_EVENT_FIRST] = LANG_BG_EY_START_TWO_MINUTES;
m_StartMessageIds[BG_STARTING_EVENT_SECOND] = LANG_BG_EY_START_ONE_MINUTE;
m_StartMessageIds[BG_STARTING_EVENT_THIRD] = LANG_BG_EY_START_HALF_MINUTE;
m_StartMessageIds[BG_STARTING_EVENT_FOURTH] = LANG_BG_EY_HAS_BEGUN;
}
BattleGroundEY::~BattleGroundEY()
@ -46,71 +49,8 @@ BattleGroundEY::~BattleGroundEY()
void BattleGroundEY::Update(uint32 diff)
{
BattleGround::Update(diff);
// after bg start we get there (once)
if (GetStatus() == STATUS_WAIT_JOIN && GetPlayersSize())
{
ModifyStartDelayTime(diff);
if(!(m_Events & 0x01))
{
m_Events |= 0x01;
// setup here, only when at least one player has ported to the map
if(!SetupBattleGround())
{
EndNow();
return;
}
SpawnBGObject(BG_EY_OBJECT_DOOR_A, RESPAWN_IMMEDIATELY);
SpawnBGObject(BG_EY_OBJECT_DOOR_H, RESPAWN_IMMEDIATELY);
// SpawnBGCreature(EY_SPIRIT_MAIN_ALLIANCE, RESPAWN_IMMEDIATELY);
// SpawnBGCreature(EY_SPIRIT_MAIN_HORDE, RESPAWN_IMMEDIATELY);
for(uint32 i = BG_EY_OBJECT_A_BANNER_FEL_REALVER_CENTER; i < BG_EY_OBJECT_MAX; ++i)
SpawnBGObject(i, RESPAWN_ONE_DAY);
SetStartDelayTime(START_DELAY0);
}
// After 1 minute, warning is signalled
else if(GetStartDelayTime() <= START_DELAY1 && !(m_Events & 0x04))
{
m_Events |= 0x04;
SendMessageToAll(GetMangosString(LANG_BG_EY_ONE_MINUTE));
}
// After 1,5 minute, warning is signalled
else if(GetStartDelayTime() <= START_DELAY2 && !(m_Events & 0x08))
{
m_Events |= 0x08;
SendMessageToAll(GetMangosString(LANG_BG_EY_HALF_MINUTE));
}
// After 2 minutes, gates OPEN ! x)
else if(GetStartDelayTime() < 0 && !(m_Events & 0x10))
{
m_Events |= 0x10;
SpawnBGObject(BG_EY_OBJECT_DOOR_A, RESPAWN_ONE_DAY);
SpawnBGObject(BG_EY_OBJECT_DOOR_H, RESPAWN_ONE_DAY);
for(uint32 i = BG_EY_OBJECT_N_BANNER_FEL_REALVER_CENTER; i <= BG_EY_OBJECT_FLAG_NETHERSTORM; ++i)
SpawnBGObject(i, RESPAWN_IMMEDIATELY);
for(uint32 i = 0; i < EY_POINTS_MAX; ++i)
{
//randomly spawn buff
uint8 buff = urand(0, 2);
SpawnBGObject(BG_EY_OBJECT_SPEEDBUFF_FEL_REALVER + buff + i * 3, RESPAWN_IMMEDIATELY);
}
SendMessageToAll(GetMangosString(LANG_BG_EY_BEGIN));
PlaySoundToAll(SOUND_BG_START);
SetStatus(STATUS_IN_PROGRESS);
for(BattleGroundPlayerMap::const_iterator itr = GetPlayers().begin(); itr != GetPlayers().end(); ++itr)
if(Player *plr = objmgr.GetPlayer(itr->first))
plr->RemoveAurasDueToSpell(SPELL_PREPARATION);
}
}
else if(GetStatus() == STATUS_IN_PROGRESS)
if( GetStatus() == STATUS_IN_PROGRESS )
{
m_PointAddingTimer -= diff;
if(m_PointAddingTimer <= 0)
@ -152,15 +92,39 @@ void BattleGroundEY::Update(uint32 diff)
}
}
void BattleGroundEY::StartingEventCloseDoors()
{
SpawnBGObject(BG_EY_OBJECT_DOOR_A, RESPAWN_IMMEDIATELY);
SpawnBGObject(BG_EY_OBJECT_DOOR_H, RESPAWN_IMMEDIATELY);
for(uint32 i = BG_EY_OBJECT_A_BANNER_FEL_REALVER_CENTER; i < BG_EY_OBJECT_MAX; ++i)
SpawnBGObject(i, RESPAWN_ONE_DAY);
}
void BattleGroundEY::StartingEventOpenDoors()
{
SpawnBGObject(BG_EY_OBJECT_DOOR_A, RESPAWN_ONE_DAY);
SpawnBGObject(BG_EY_OBJECT_DOOR_H, RESPAWN_ONE_DAY);
for(uint32 i = BG_EY_OBJECT_N_BANNER_FEL_REALVER_CENTER; i <= BG_EY_OBJECT_FLAG_NETHERSTORM; ++i)
SpawnBGObject(i, RESPAWN_IMMEDIATELY);
for(uint32 i = 0; i < EY_POINTS_MAX; ++i)
{
//randomly spawn buff
uint8 buff = urand(0, 2);
SpawnBGObject(BG_EY_OBJECT_SPEEDBUFF_FEL_REALVER + buff + i * 3, RESPAWN_IMMEDIATELY);
}
}
void BattleGroundEY::AddPoints(uint32 Team, uint32 Points)
{
uint8 team_index = GetTeamIndexByTeamId(Team);
m_TeamScores[team_index] += Points;
m_HonorScoreTics[team_index] += Points;
if (m_HonorScoreTics[team_index] >= BG_HONOR_SCORE_TICKS)
if (m_HonorScoreTics[team_index] >= m_HonorTics )
{
RewardHonorToTeam(20, Team);
m_HonorScoreTics[team_index] -= BG_HONOR_SCORE_TICKS;
RewardHonorToTeam(GetBonusHonorFromKill(1), Team);
m_HonorScoreTics[team_index] -= m_HonorTics;
}
UpdateTeamScore(Team);
}
@ -183,7 +147,7 @@ void BattleGroundEY::CheckSomeoneJoinedPoint()
++j;
continue;
}
if (plr->isAllowUseBattleGroundObject() && plr->IsWithinDistInMap(obj, BG_EY_POINT_RADIUS))
if (plr->CanCaptureTowerPoint() && plr->IsWithinDistInMap(obj, BG_EY_POINT_RADIUS))
{
//player joined point!
//show progress bar
@ -226,7 +190,7 @@ void BattleGroundEY::CheckSomeoneLeftPoint()
++j;
continue;
}
if (!plr->isAllowUseBattleGroundObject() || !plr->IsWithinDistInMap(obj, BG_EY_POINT_RADIUS))
if (!plr->CanCaptureTowerPoint() || !plr->IsWithinDistInMap(obj, BG_EY_POINT_RADIUS))
//move player out of point (add him to players that are out of points
{
m_PlayersNearPoint[EY_POINTS_MAX].push_back(m_PlayersNearPoint[i][j]);
@ -306,6 +270,20 @@ void BattleGroundEY::UpdateTeamScore(uint32 Team)
UpdateWorldState(EY_HORDE_RESOURCES, score);
}
void BattleGroundEY::EndBattleGround(uint32 winner)
{
//win reward
if( winner == ALLIANCE )
RewardHonorToTeam(GetBonusHonorFromKill(1), ALLIANCE);
if( winner == HORDE )
RewardHonorToTeam(GetBonusHonorFromKill(1), HORDE);
//complete map reward
RewardHonorToTeam(GetBonusHonorFromKill(1), ALLIANCE);
RewardHonorToTeam(GetBonusHonorFromKill(1), HORDE);
BattleGround::EndBattleGround(winner);
}
void BattleGroundEY::UpdatePointsCount(uint32 Team)
{
if(Team == ALLIANCE)
@ -530,6 +508,8 @@ void BattleGroundEY::Reset()
m_DroppedFlagGUID = 0;
m_PointAddingTimer = 0;
m_TowerCapCheckTimer = 0;
bool isBGWeekend = false; //TODO FIXME - call sBattleGroundMgr.IsBGWeekend(m_TypeID); - you must also implement that call!
uint32 m_HonorTics = (isBGWeekend) ? BG_EY_EYWeekendHonorTicks : BG_EY_NotEYWeekendHonorTicks;
for(uint8 i = 0; i < EY_POINTS_MAX; ++i)
{
@ -554,7 +534,7 @@ void BattleGroundEY::RespawnFlag(bool send_message)
if(send_message)
{
SendMessageToAll(GetMangosString(LANG_BG_EY_RESETED_FLAG));
SendMessageToAll(LANG_BG_EY_RESETED_FLAG, CHAT_MSG_BG_SYSTEM_NEUTRAL);
PlaySoundToAll(BG_EY_SOUND_FLAG_RESET); // flags respawned sound...
}
@ -603,32 +583,20 @@ void BattleGroundEY::EventPlayerDroppedFlag(Player *Source)
if(GetFlagPickerGUID() != Source->GetGUID())
return;
const char *message = "";
uint8 type = 0;
SetFlagPicker(0);
Source->RemoveAurasDueToSpell(BG_EY_NETHERSTORM_FLAG_SPELL);
m_FlagState = BG_EY_FLAG_STATE_ON_GROUND;
m_FlagsTimer = BG_EY_FLAG_RESPAWN_TIME;
Source->CastSpell(Source, SPELL_RECENTLY_DROPPED_FLAG, true);
Source->CastSpell(Source, BG_EY_PLAYER_DROPPED_FLAG_SPELL, true);
if(Source->GetTeam() == ALLIANCE)
{
message = GetMangosString(LANG_BG_EY_DROPPED_FLAG);
type = CHAT_MSG_BG_SYSTEM_ALLIANCE;
}
else
{
message = GetMangosString(LANG_BG_EY_DROPPED_FLAG);
type = CHAT_MSG_BG_SYSTEM_HORDE;
}
//this does not work correctly :( (it should remove flag carrier name)
UpdateWorldState(NETHERSTORM_FLAG_STATE_HORDE, BG_EY_FLAG_STATE_WAIT_RESPAWN);
UpdateWorldState(NETHERSTORM_FLAG_STATE_ALLIANCE, BG_EY_FLAG_STATE_WAIT_RESPAWN);
WorldPacket data;
ChatHandler::FillMessageData(&data, Source->GetSession(), type, LANG_UNIVERSAL, NULL, Source->GetGUID(), message, NULL);
SendPacketToAll(&data);
if(Source->GetTeam() == ALLIANCE)
SendMessageToAll(LANG_BG_EY_DROPPED_FLAG,CHAT_MSG_BG_SYSTEM_ALLIANCE, Source);
else
SendMessageToAll(LANG_BG_EY_DROPPED_FLAG,CHAT_MSG_BG_SYSTEM_HORDE, Source);
}
void BattleGroundEY::EventPlayerClickedOnFlag(Player *Source, GameObject* target_obj)
@ -636,20 +604,14 @@ void BattleGroundEY::EventPlayerClickedOnFlag(Player *Source, GameObject* target
if(GetStatus() != STATUS_IN_PROGRESS || IsFlagPickedup() || !Source->IsWithinDistInMap(target_obj, 10))
return;
const char *message;
uint8 type = 0;
message = GetMangosString(LANG_BG_EY_HAS_TAKEN_FLAG);
if(Source->GetTeam() == ALLIANCE)
{
UpdateWorldState(NETHERSTORM_FLAG_STATE_ALLIANCE, BG_EY_FLAG_STATE_ON_PLAYER);
type = CHAT_MSG_BG_SYSTEM_ALLIANCE;
PlaySoundToAll(BG_EY_SOUND_FLAG_PICKED_UP_ALLIANCE);
}
else
{
UpdateWorldState(NETHERSTORM_FLAG_STATE_HORDE, BG_EY_FLAG_STATE_ON_PLAYER);
type = CHAT_MSG_BG_SYSTEM_HORDE;
PlaySoundToAll(BG_EY_SOUND_FLAG_PICKED_UP_HORDE);
}
@ -663,9 +625,10 @@ void BattleGroundEY::EventPlayerClickedOnFlag(Player *Source, GameObject* target
Source->CastSpell(Source, BG_EY_NETHERSTORM_FLAG_SPELL, true);
Source->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_ENTER_PVP_COMBAT);
WorldPacket data;
ChatHandler::FillMessageData(&data, Source->GetSession(), type, LANG_UNIVERSAL, NULL, Source->GetGUID(), message, NULL);
SendPacketToAll(&data);
if(Source->GetTeam() == ALLIANCE)
SendMessageToAll(LANG_BG_EY_HAS_TAKEN_FLAG,CHAT_MSG_BG_SYSTEM_ALLIANCE, Source);
else
SendMessageToAll(LANG_BG_EY_HAS_TAKEN_FLAG,CHAT_MSG_BG_SYSTEM_HORDE, Source);
}
void BattleGroundEY::EventTeamLostPoint(Player *Source, uint32 Point)
@ -674,8 +637,6 @@ void BattleGroundEY::EventTeamLostPoint(Player *Source, uint32 Point)
return;
//Natural point
uint8 message_type = 0;
const char *message = "";
uint32 Team = m_PointOwnedByTeam[Point];
if(!Team)
@ -684,8 +645,6 @@ void BattleGroundEY::EventTeamLostPoint(Player *Source, uint32 Point)
if (Team == ALLIANCE)
{
m_TeamPointsCount[BG_TEAM_ALLIANCE]--;
message_type = CHAT_MSG_BG_SYSTEM_ALLIANCE;
message = GetMangosString(m_LoosingPointTypes[Point].MessageIdAlliance);
SpawnBGObject(m_LoosingPointTypes[Point].DespawnObjectTypeAlliance, RESPAWN_ONE_DAY);
SpawnBGObject(m_LoosingPointTypes[Point].DespawnObjectTypeAlliance + 1, RESPAWN_ONE_DAY);
SpawnBGObject(m_LoosingPointTypes[Point].DespawnObjectTypeAlliance + 2, RESPAWN_ONE_DAY);
@ -693,8 +652,6 @@ void BattleGroundEY::EventTeamLostPoint(Player *Source, uint32 Point)
else
{
m_TeamPointsCount[BG_TEAM_HORDE]--;
message_type = CHAT_MSG_BG_SYSTEM_HORDE;
message = GetMangosString(m_LoosingPointTypes[Point].MessageIdHorde);
SpawnBGObject(m_LoosingPointTypes[Point].DespawnObjectTypeHorde, RESPAWN_ONE_DAY);
SpawnBGObject(m_LoosingPointTypes[Point].DespawnObjectTypeHorde + 1, RESPAWN_ONE_DAY);
SpawnBGObject(m_LoosingPointTypes[Point].DespawnObjectTypeHorde + 2, RESPAWN_ONE_DAY);
@ -709,9 +666,10 @@ void BattleGroundEY::EventTeamLostPoint(Player *Source, uint32 Point)
m_PointOwnedByTeam[Point] = EY_POINT_NO_OWNER;
m_PointState[Point] = EY_POINT_NO_OWNER;
WorldPacket data;
ChatHandler::FillMessageData(&data, Source->GetSession(), message_type, LANG_UNIVERSAL, NULL, Source->GetGUID(), message, NULL);
SendPacketToAll(&data);
if (Team == ALLIANCE)
SendMessageToAll(m_LoosingPointTypes[Point].MessageIdAlliance,CHAT_MSG_BG_SYSTEM_ALLIANCE, Source);
else
SendMessageToAll(m_LoosingPointTypes[Point].MessageIdHorde,CHAT_MSG_BG_SYSTEM_HORDE, Source);
UpdatePointsIcons(Team, Point);
UpdatePointsCount(Team);
@ -722,8 +680,6 @@ void BattleGroundEY::EventTeamCapturedPoint(Player *Source, uint32 Point)
if(GetStatus() != STATUS_IN_PROGRESS)
return;
uint8 type = 0;
const char *message = "";
uint32 Team = Source->GetTeam();
SpawnBGObject(m_CapturingPointTypes[Point].DespawnNeutralObjectType, RESPAWN_ONE_DAY);
@ -733,8 +689,6 @@ void BattleGroundEY::EventTeamCapturedPoint(Player *Source, uint32 Point)
if (Team == ALLIANCE)
{
m_TeamPointsCount[BG_TEAM_ALLIANCE]++;
type = CHAT_MSG_BG_SYSTEM_ALLIANCE;
message = GetMangosString(m_CapturingPointTypes[Point].MessageIdAlliance);
SpawnBGObject(m_CapturingPointTypes[Point].SpawnObjectTypeAlliance, RESPAWN_IMMEDIATELY);
SpawnBGObject(m_CapturingPointTypes[Point].SpawnObjectTypeAlliance + 1, RESPAWN_IMMEDIATELY);
SpawnBGObject(m_CapturingPointTypes[Point].SpawnObjectTypeAlliance + 2, RESPAWN_IMMEDIATELY);
@ -742,8 +696,6 @@ void BattleGroundEY::EventTeamCapturedPoint(Player *Source, uint32 Point)
else
{
m_TeamPointsCount[BG_TEAM_HORDE]++;
type = CHAT_MSG_BG_SYSTEM_HORDE;
message = GetMangosString(m_CapturingPointTypes[Point].MessageIdHorde);
SpawnBGObject(m_CapturingPointTypes[Point].SpawnObjectTypeHorde, RESPAWN_IMMEDIATELY);
SpawnBGObject(m_CapturingPointTypes[Point].SpawnObjectTypeHorde + 1, RESPAWN_IMMEDIATELY);
SpawnBGObject(m_CapturingPointTypes[Point].SpawnObjectTypeHorde + 2, RESPAWN_IMMEDIATELY);
@ -754,9 +706,10 @@ void BattleGroundEY::EventTeamCapturedPoint(Player *Source, uint32 Point)
m_PointOwnedByTeam[Point] = Team;
m_PointState[Point] = EY_POINT_UNDER_CONTROL;
WorldPacket data;
ChatHandler::FillMessageData(&data, Source->GetSession(), type, LANG_UNIVERSAL, NULL, Source->GetGUID(), message, NULL);
SendPacketToAll(&data);
if (Team == ALLIANCE)
SendMessageToAll(m_CapturingPointTypes[Point].MessageIdAlliance,CHAT_MSG_BG_SYSTEM_ALLIANCE, Source);
else
SendMessageToAll(m_CapturingPointTypes[Point].MessageIdHorde,CHAT_MSG_BG_SYSTEM_HORDE, Source);
if(m_BgCreatures[Point])
DelCreature(Point);
@ -778,38 +731,33 @@ void BattleGroundEY::EventPlayerCapturedFlag(Player *Source, uint32 BgObjectType
if(GetStatus() != STATUS_IN_PROGRESS || GetFlagPickerGUID() != Source->GetGUID())
return;
uint8 type = 0;
uint8 team_id = 0;
const char *message = "";
SetFlagPicker(0);
m_FlagState = BG_EY_FLAG_STATE_WAIT_RESPAWN;
Source->RemoveAurasDueToSpell(BG_EY_NETHERSTORM_FLAG_SPELL);
Source->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_ENTER_PVP_COMBAT);
if(Source->GetTeam() == ALLIANCE)
{
PlaySoundToAll(BG_EY_SOUND_FLAG_CAPTURED_ALLIANCE);
team_id = BG_TEAM_ALLIANCE;
message = GetMangosString(LANG_BG_EY_CAPTURED_FLAG_A);
type = CHAT_MSG_BG_SYSTEM_ALLIANCE;
}
else
{
PlaySoundToAll(BG_EY_SOUND_FLAG_CAPTURED_HORDE);
team_id = BG_TEAM_HORDE;
message = GetMangosString(LANG_BG_EY_CAPTURED_FLAG_H);
type = CHAT_MSG_BG_SYSTEM_HORDE;
}
SpawnBGObject(BgObjectType, RESPAWN_IMMEDIATELY);
m_FlagsTimer = BG_EY_FLAG_RESPAWN_TIME;
m_FlagCapturedBgObjectType = BgObjectType;
WorldPacket data;
ChatHandler::FillMessageData(&data, Source->GetSession(), type, LANG_UNIVERSAL, NULL, Source->GetGUID(), message, NULL);
SendPacketToAll(&data);
uint8 team_id = 0;
if(Source->GetTeam() == ALLIANCE)
{
team_id = BG_TEAM_ALLIANCE;
SendMessageToAll(LANG_BG_EY_CAPTURED_FLAG_A, CHAT_MSG_BG_SYSTEM_ALLIANCE, Source);
}
else
{
team_id = BG_TEAM_HORDE;
SendMessageToAll(LANG_BG_EY_CAPTURED_FLAG_H, CHAT_MSG_BG_SYSTEM_HORDE, Source);
}
if(m_TeamPointsCount[team_id] > 0)
AddPoints(Source->GetTeam(), BG_EY_FlagPoints[m_TeamPointsCount[team_id] - 1]);

View file

@ -210,6 +210,9 @@ enum EYBattleGroundObjectTypes
BG_EY_OBJECT_MAX = 59
};
#define BG_EY_NotEYWeekendHonorTicks 330
#define BG_EY_EYWeekendHonorTicks 200
enum BG_EY_FlagState
{
BG_EY_FLAG_STATE_ON_BASE = 0,
@ -302,6 +305,8 @@ class BattleGroundEY : public BattleGround
/* inherited from BattlegroundClass */
virtual void AddPlayer(Player *plr);
virtual void StartingEventCloseDoors();
virtual void StartingEventOpenDoors();
/* BG Flags */
uint64 GetFlagPickerGUID() const { return m_FlagKeeper; }
@ -319,6 +324,7 @@ class BattleGroundEY : public BattleGround
virtual bool SetupBattleGround();
virtual void Reset();
void UpdateTeamScore(uint32 Team);
void EndBattleGround(uint32 winner);
void UpdatePlayerScore(Player *Source, uint32 type, uint32 value);
virtual void FillInitialWorldStates(WorldPacket& data);
void SetDroppedFlagGUID(uint64 guid) { m_DroppedFlagGUID = guid;}
@ -368,5 +374,6 @@ class BattleGroundEY : public BattleGround
uint8 m_CurrentPointPlayersCount[2*EY_POINTS_MAX];
int32 m_PointAddingTimer;
uint32 m_HonorTics;
};
#endif

View file

@ -23,7 +23,6 @@
#include "Player.h"
#include "ObjectMgr.h"
#include "WorldSession.h"
#include "MapManager.h"
#include "ObjectAccessor.h"
#include "Object.h"
#include "Chat.h"
@ -111,9 +110,9 @@ void WorldSession::HandleBattleGroundJoinOpcode( WorldPacket & recv_data )
return;
// get bg instance or bg template if instance not found
BattleGround * bg = 0;
BattleGround * bg = NULL;
if(instanceId)
BattleGround *bg = sBattleGroundMgr.GetBattleGround(instanceId, bgTypeId);
BattleGround *bg = sBattleGroundMgr.GetBattleGroundThroughClientInstance(instanceId, bgTypeId, _player->GetBattleGroundQueueIdFromLevel(bgTypeId));
if(!bg && !(bg = sBattleGroundMgr.GetBattleGroundTemplate(bgTypeId)))
{
@ -157,10 +156,11 @@ void WorldSession::HandleBattleGroundJoinOpcode( WorldPacket & recv_data )
// if we're here, then the conditions to join a bg are met. We can proceed in joining.
// _player->GetGroup() was already checked, grp is already initialized
GroupQueueInfo * ginfo = sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].AddGroup(_player, bgTypeId, 0, false, isPremade, 0);
uint32 avgTime = sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].GetAverageQueueWaitTime(ginfo, _player->GetBattleGroundQueueIdFromLevel(bgTypeId));
if(joinAsGroup /* && _player->GetGroup()*/)
{
sLog.outDebug("Battleground: the following players are joining as group:");
GroupQueueInfo * ginfo = sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].AddGroup(_player, bgTypeId, 0, false, isPremade, 0);
for(GroupReference *itr = grp->GetFirstMember(); itr != NULL; itr = itr->next())
{
Player *member = itr->getSource();
@ -173,7 +173,7 @@ void WorldSession::HandleBattleGroundJoinOpcode( WorldPacket & recv_data )
WorldPacket data;
// send status packet (in queue)
sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, member->GetTeam(), queueSlot, STATUS_WAIT_QUEUE, 0, 0);
sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, queueSlot, STATUS_WAIT_QUEUE, avgTime, 0);
member->GetSession()->SendPacket(&data);
sBattleGroundMgr.BuildGroupJoinedBattlegroundPacket(&data, bgTypeId);
member->GetSession()->SendPacket(&data);
@ -181,9 +181,6 @@ void WorldSession::HandleBattleGroundJoinOpcode( WorldPacket & recv_data )
sLog.outDebug("Battleground: player joined queue for bg queue type %u bg type %u: GUID %u, NAME %s",bgQueueTypeId,bgTypeId,member->GetGUIDLow(), member->GetName());
}
sLog.outDebug("Battleground: group end");
sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].Update(bgTypeId, _player->GetBattleGroundQueueIdFromLevel(bgTypeId));
if(!ginfo->IsInvitedToBGInstanceGUID)
sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].AnnounceWorld(ginfo, _player->GetGUID(), true);
}
else
{
@ -194,16 +191,15 @@ void WorldSession::HandleBattleGroundJoinOpcode( WorldPacket & recv_data )
WorldPacket data;
// send status packet (in queue)
sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, _player->GetTeam(), queueSlot, STATUS_WAIT_QUEUE, 0, 0);
sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, queueSlot, STATUS_WAIT_QUEUE, avgTime, 0);
SendPacket(&data);
GroupQueueInfo * ginfo = sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].AddGroup(_player, bgTypeId, 0, false, false, 0);
sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].AddPlayer(_player, ginfo);
sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].Update(bgTypeId, _player->GetBattleGroundQueueIdFromLevel(bgTypeId));
if(!ginfo->IsInvitedToBGInstanceGUID)
sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].AnnounceWorld(ginfo, _player->GetGUID(), true);
sLog.outDebug("Battleground: player joined queue for bg queue type %u bg type %u: GUID %u, NAME %s",bgQueueTypeId,bgTypeId,_player->GetGUIDLow(), _player->GetName());
}
sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].Update(bgTypeId, _player->GetBattleGroundQueueIdFromLevel(bgTypeId));
if(!ginfo->IsInvitedToBGInstanceGUID)
sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].AnnounceWorld(ginfo, _player->GetGUID(), true);
}
void WorldSession::HandleBattleGroundPlayerPositionsOpcode( WorldPacket & /*recv_data*/ )
@ -323,22 +319,16 @@ void WorldSession::HandleBattleGroundPlayerPortOpcode( WorldPacket &recv_data )
BattleGroundTypeId bgTypeId = BattleGroundMgr::BGTemplateId(bgQueueTypeId);
BattleGroundQueue::QueuedPlayersMap& qpMap = sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].m_QueuedPlayers;
BattleGroundQueue::QueuedPlayersMap::iterator itrPlayerStatus = qpMap.find(_player->GetGUID());
// if the player is not in queue, continue
if(itrPlayerStatus == qpMap.end())
continue;
// no group information, this should never happen
if(!itrPlayerStatus->second.GroupInfo)
// if the player is not in queue, continue or no group information - this should never happen
if(itrPlayerStatus == qpMap.end() || !itrPlayerStatus->second.GroupInfo)
continue;
BattleGround * bg = NULL;
// get possibly needed data from groupinfo
uint8 arenatype = itrPlayerStatus->second.GroupInfo->ArenaType;
uint8 israted = itrPlayerStatus->second.GroupInfo->IsRated;
uint8 status = 0;
if(!itrPlayerStatus->second.GroupInfo->IsInvitedToBGInstanceGUID)
{
// not invited to bg, get template
@ -362,7 +352,7 @@ void WorldSession::HandleBattleGroundPlayerPortOpcode( WorldPacket &recv_data )
// re - invite player with proper data
WorldPacket data;
sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, itrPlayerStatus->second.GroupInfo->Team?itrPlayerStatus->second.GroupInfo->Team:_player->GetTeam(), i, status, INVITE_ACCEPT_WAIT_TIME, 0, arenatype, israted);
sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, i, status, INVITE_ACCEPT_WAIT_TIME, 0, arenatype);
SendPacket(&data);
}
}
@ -429,6 +419,12 @@ void WorldSession::HandleBattleGroundPlayerPortOpcode( WorldPacket &recv_data )
sLog.outError("Battleground: Invalid player queue info!");
return;
}
//if player is trying to enter battleground (not arena!) and he has deserter debuff, we must just remove him from queue
if( arenatype == 0 && !_player->CanJoinToBattleground() )
{
sLog.outDebug("Battleground: player %s (%u) has a deserter debuff, do not port him to battleground!", _player->GetName(), _player->GetGUIDLow());
action = 0;
}
WorldPacket data;
switch(action)
{
@ -449,7 +445,7 @@ void WorldSession::HandleBattleGroundPlayerPortOpcode( WorldPacket &recv_data )
}
_player->RemoveFromGroup();
queueSlot = _player->GetBattleGroundQueueIndex(bgQueueTypeId);
sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, _player->GetTeam(), queueSlot, STATUS_IN_PROGRESS, 0, bg->GetStartTime());
sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, queueSlot, STATUS_IN_PROGRESS, 0, bg->GetStartTime());
_player->GetSession()->SendPacket(&data);
// remove battleground queue status from BGmgr
sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].RemovePlayer(_player->GetGUID(), false);
@ -484,7 +480,7 @@ void WorldSession::HandleBattleGroundPlayerPortOpcode( WorldPacket &recv_data )
}
}
_player->RemoveBattleGroundQueueId(bgQueueTypeId); // must be called this way, because if you move this call to queue->removeplayer, it causes bugs
sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, _player->GetTeam(), queueSlot, STATUS_NONE, 0, 0);
sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, queueSlot, STATUS_NONE, 0, 0);
sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].RemovePlayer(_player->GetGUID(), true);
// player left queue, we should update it, maybe now his group fits in
sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].Update(bgTypeId,_player->GetBattleGroundQueueIdFromLevel(bgTypeId),arenatype,israted,rating);
@ -528,84 +524,41 @@ void WorldSession::HandleBattlefieldStatusOpcode( WorldPacket & /*recv_data*/ )
sLog.outDebug( "WORLD: Battleground status" );
WorldPacket data;
uint32 queueSlot = PLAYER_MAX_BATTLEGROUND_QUEUES;
// TODO: we must put player back to battleground in case disconnect (< 5 minutes offline time) or teleport player on login(!) from battleground map to entry point
if(_player->InBattleGround())
{
BattleGround *bg = _player->GetBattleGround();
if(bg)
if(!bg)
return;
BattleGroundQueueTypeId bgQueueTypeId_tmp = BattleGroundMgr::BGQueueTypeId(bg->GetTypeID(), bg->GetArenaType());
queueSlot = _player->GetBattleGroundQueueIndex(bgQueueTypeId_tmp);
if((bg->GetStatus() <= STATUS_IN_PROGRESS))
{
BattleGroundQueueTypeId bgQueueTypeId_tmp = BattleGroundMgr::BGQueueTypeId(bg->GetTypeID(), bg->GetArenaType());
uint32 queueSlot = _player->GetBattleGroundQueueIndex(bgQueueTypeId_tmp);
if((bg->GetStatus() <= STATUS_IN_PROGRESS))
{
sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, _player->GetTeam(), queueSlot, STATUS_IN_PROGRESS, 0, bg->GetStartTime());
SendPacket(&data);
}
for (uint32 i = 0; i < PLAYER_MAX_BATTLEGROUND_QUEUES; i++)
{
BattleGroundQueueTypeId bgQueueTypeId = _player->GetBattleGroundQueueTypeId(i);
if (i == queueSlot || !bgQueueTypeId)
continue;
BattleGroundTypeId bgTypeId = BattleGroundMgr::BGTemplateId(bgQueueTypeId);
uint8 arenatype = BattleGroundMgr::BGArenaType(bgQueueTypeId);
uint8 isRated = 0;
BattleGroundQueue::QueuedPlayersMap& qpMap = sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].m_QueuedPlayers;
BattleGroundQueue::QueuedPlayersMap::iterator itrPlayerStatus = qpMap.find(_player->GetGUID());
if(itrPlayerStatus == qpMap.end())
continue;
if(itrPlayerStatus->second.GroupInfo)
{
arenatype = itrPlayerStatus->second.GroupInfo->ArenaType;
isRated = itrPlayerStatus->second.GroupInfo->IsRated;
}
BattleGround *bg2 = sBattleGroundMgr.GetBattleGroundTemplate(bgTypeId);
if(bg2)
{
//in this call is small bug, this call should be filled by player's waiting time in queue
//this call nulls all timers for client :
sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg2, _player->GetTeam(), i, STATUS_WAIT_QUEUE, 0, 0,arenatype,isRated);
SendPacket(&data);
}
}
}
}
else
{
// we should update all queues? .. i'm not sure if this code is correct
for (uint32 i = 0; i < PLAYER_MAX_BATTLEGROUND_QUEUES; i++)
{
BattleGroundQueueTypeId bgQueueTypeId = _player->GetBattleGroundQueueTypeId(i);
if(!bgQueueTypeId)
continue;
BattleGroundTypeId bgTypeId = BattleGroundMgr::BGTemplateId(bgQueueTypeId);
uint8 arenatype = BattleGroundMgr::BGArenaType(bgQueueTypeId);
uint8 isRated = 0;
BattleGround *bg = sBattleGroundMgr.GetBattleGroundTemplate(bgTypeId);
BattleGroundQueue::QueuedPlayersMap& qpMap = sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].m_QueuedPlayers;
BattleGroundQueue::QueuedPlayersMap::iterator itrPlayerStatus = qpMap.find(_player->GetGUID());
if(itrPlayerStatus == qpMap.end())
continue;
if(itrPlayerStatus->second.GroupInfo)
{
arenatype = itrPlayerStatus->second.GroupInfo->ArenaType;
isRated = itrPlayerStatus->second.GroupInfo->IsRated;
}
if(bg)
{
sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, _player->GetTeam(), i, STATUS_WAIT_QUEUE, 0, 0, arenatype, isRated);
SendPacket(&data);
}
}
}
/* else // not sure if it needed...
{
for (uint32 i = 0; i < PLAYER_MAX_BATTLEGROUND_QUEUES; i++)
{
sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, NULL, _player->GetTeam(),i , STATUS_NONE, 0, 0);
sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, queueSlot, STATUS_IN_PROGRESS, 0, bg->GetStartTime());
SendPacket(&data);
}
}*/
}
// we should update all queues? .. i'm not sure if this code is correct
for (uint32 i = 0; i < PLAYER_MAX_BATTLEGROUND_QUEUES; i++)
{
BattleGroundQueueTypeId bgQueueTypeId = _player->GetBattleGroundQueueTypeId(i);
if(!bgQueueTypeId || i == queueSlot) //queueslot check in case we already send it in the above code
continue;
BattleGroundTypeId bgTypeId = BattleGroundMgr::BGTemplateId(bgQueueTypeId);
uint8 arenatype = BattleGroundMgr::BGArenaType(bgQueueTypeId);
BattleGround *bg = sBattleGroundMgr.GetBattleGroundTemplate(bgTypeId);
if(!bg)
continue;
BattleGroundQueue::QueuedPlayersMap& qpMap = sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].m_QueuedPlayers;
BattleGroundQueue::QueuedPlayersMap::iterator itrPlayerStatus = qpMap.find(_player->GetGUID());
if(itrPlayerStatus == qpMap.end() || !itrPlayerStatus->second.GroupInfo)
continue;
arenatype = itrPlayerStatus->second.GroupInfo->ArenaType;
uint32 avgTime = sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].GetAverageQueueWaitTime(itrPlayerStatus->second.GroupInfo, _player->GetBattleGroundQueueIdFromLevel(bgTypeId));
sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, i, STATUS_WAIT_QUEUE, avgTime, getMSTime()-itrPlayerStatus->second.GroupInfo->JoinTime, arenatype);
SendPacket(&data);
}
}
void WorldSession::HandleAreaSpiritHealerQueryOpcode( WorldPacket & recv_data )
@ -768,9 +721,10 @@ void WorldSession::HandleBattleGroundArenaJoin( WorldPacket & recv_data )
arenaRating = avg_pers_rating;
}
GroupQueueInfo * ginfo = sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].AddGroup(_player, bgTypeId, arenatype, isRated, false, arenaRating, ateamId);
uint32 avgTime = sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].GetAverageQueueWaitTime(ginfo, _player->GetBattleGroundQueueIdFromLevel(bgTypeId));
if(asGroup)
{
GroupQueueInfo * ginfo = sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].AddGroup(_player, bgTypeId, arenatype, isRated, false, arenaRating, ateamId);
sLog.outDebug("Battleground: arena join as group start");
if(isRated)
sLog.outDebug("Battleground: arena team id %u, leader %s queued with rating %u for type %u",_player->GetArenaTeamId(arenaslot),_player->GetName(),arenaRating,arenatype);
@ -786,7 +740,7 @@ void WorldSession::HandleBattleGroundArenaJoin( WorldPacket & recv_data )
WorldPacket data;
// send status packet (in queue)
sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, member->GetTeam(), queueSlot, STATUS_WAIT_QUEUE, 0, 0, arenatype, isRated);
sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, queueSlot, STATUS_WAIT_QUEUE, avgTime, 0, arenatype);
member->GetSession()->SendPacket(&data);
sBattleGroundMgr.BuildGroupJoinedBattlegroundPacket(&data, bgTypeId);
member->GetSession()->SendPacket(&data);
@ -794,7 +748,6 @@ void WorldSession::HandleBattleGroundArenaJoin( WorldPacket & recv_data )
sLog.outDebug("Battleground: player joined queue for arena as group bg queue type %u bg type %u: GUID %u, NAME %s",bgQueueTypeId,bgTypeId,member->GetGUIDLow(), member->GetName());
}
sLog.outDebug("Battleground: arena join as group end");
sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].Update(bgTypeId, _player->GetBattleGroundQueueIdFromLevel(bgTypeId), arenatype, isRated, arenaRating);
if(isRated)
sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].AnnounceWorld(ginfo, _player->GetGUID(), true);
}
@ -807,13 +760,12 @@ void WorldSession::HandleBattleGroundArenaJoin( WorldPacket & recv_data )
WorldPacket data;
// send status packet (in queue)
sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, _player->GetTeam(), queueSlot, STATUS_WAIT_QUEUE, 0, 0, arenatype, isRated);
sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, queueSlot, STATUS_WAIT_QUEUE, avgTime, 0, arenatype);
SendPacket(&data);
GroupQueueInfo * ginfo = sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].AddGroup(_player, bgTypeId, arenatype, isRated, false, arenaRating);
sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].AddPlayer(_player, ginfo);
sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].Update(bgTypeId, _player->GetBattleGroundQueueIdFromLevel(bgTypeId), arenatype, isRated, arenaRating);
sLog.outDebug("Battleground: player joined queue for arena, skirmish, bg queue type %u bg type %u: GUID %u, NAME %s",bgQueueTypeId,bgTypeId,_player->GetGUIDLow(), _player->GetName());
}
sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].Update(bgTypeId, _player->GetBattleGroundQueueIdFromLevel(bgTypeId), arenatype, isRated, arenaRating);
}
void WorldSession::HandleBattleGroundReportAFK( WorldPacket & recv_data )

View file

@ -52,6 +52,16 @@ INSTANTIATE_SINGLETON_1( BattleGroundMgr );
BattleGroundQueue::BattleGroundQueue()
{
for(uint32 i = 0; i < BG_TEAMS_COUNT; i++)
{
for(uint32 j = 0; j < MAX_BATTLEGROUND_QUEUES; j++)
{
m_SumOfWaitTimes[i][j] = 0;
m_WaitTimeLastPlayer[i][j] = 0;
for(uint32 k = 0; k < COUNT_OF_PLAYERS_TO_AVERAGE_WAIT_TIME; k++)
m_WaitTimes[i][j][k] = 0;
}
}
}
BattleGroundQueue::~BattleGroundQueue()
@ -81,7 +91,7 @@ void BattleGroundQueue::SelectionPool::Init()
// remove group info from selection pool
// returns true when we need to try to add new group to selection pool
// or false when pool is ok
// returns false when selection pool is ok or when we kicked smaller group than we need to kick
// sometimes it can be called on empty selection pool
bool BattleGroundQueue::SelectionPool::KickGroup(uint32 size)
{
@ -105,7 +115,8 @@ bool BattleGroundQueue::SelectionPool::KickGroup(uint32 size)
GroupQueueInfo* ginfo = (*groupToKick);
SelectedGroups.erase(groupToKick);
PlayerCount -= ginfo->Players.size();
if (abs((int32)(ginfo->Players.size() - size)) <= 1)
//return false if we kicked smaller group or there are enough players in selection pool
if (ginfo->Players.size() <= size + 1)
return false;
}
return true;
@ -113,8 +124,8 @@ bool BattleGroundQueue::SelectionPool::KickGroup(uint32 size)
// add group to selection pool
// used when building selection pools
// returns true if we can invite more players
// returns false when selection pool is set
// returns true if we can invite more players, or when we added group to selection pool
// returns false when selection pool is full
bool BattleGroundQueue::SelectionPool::AddGroup(GroupQueueInfo *ginfo, uint32 desiredCount)
{
//if group is larger than desired count - don't allow to add it to pool
@ -123,6 +134,7 @@ bool BattleGroundQueue::SelectionPool::AddGroup(GroupQueueInfo *ginfo, uint32 de
SelectedGroups.push_back(ginfo);
// increase selected players count
PlayerCount += ginfo->Players.size();
return true;
}
if( PlayerCount < desiredCount )
return true;
@ -147,7 +159,7 @@ GroupQueueInfo * BattleGroundQueue::AddGroup(Player *leader, BattleGroundTypeId
ginfo->ArenaTeamId = arenateamid;
ginfo->IsRated = isRated;
ginfo->IsInvitedToBGInstanceGUID = 0;
ginfo->JoinTime = getMSTime();
ginfo->JoinTime = sWorld.GetGameTime() * IN_MILISECONDS;
ginfo->Team = leader->GetTeam();
ginfo->ArenaTeamRating = arenaRating;
ginfo->OpponentsTeamRating = 0;
@ -173,8 +185,6 @@ void BattleGroundQueue::AddPlayer(Player *plr, GroupQueueInfo *ginfo)
{
//if player isn't in queue, he is added, if already is, then values are overwritten, no memory leak
PlayerQueueInfo& info = m_QueuedPlayers[plr->GetGUID()];
info.InviteTime = 0;
info.LastInviteTime = 0;
info.LastOnlineTime = getMSTime();
info.GroupInfo = ginfo;
@ -182,6 +192,55 @@ void BattleGroundQueue::AddPlayer(Player *plr, GroupQueueInfo *ginfo)
ginfo->Players[plr->GetGUID()] = &info;
}
void BattleGroundQueue::PlayerInvitedToBGUpdateAverageWaitTime(GroupQueueInfo* ginfo, BGQueueIdBasedOnLevel queue_id)
{
uint32 timeInQueue = (sWorld.GetGameTime() * IN_MILISECONDS) - ginfo->JoinTime;
uint8 team_index = BG_TEAM_ALLIANCE; //default set to BG_TEAM_ALLIANCE - or non rated arenas!
if( !ginfo->ArenaType )
{
if( ginfo->Team == HORDE )
team_index = BG_TEAM_HORDE;
}
else
{
if( ginfo->IsRated )
team_index = BG_TEAM_HORDE; //for rated arenas use BG_TEAM_HORDE
}
//store pointer to arrayindex of player that was added first
uint32* lastPlayerAddedPointer = &(m_WaitTimeLastPlayer[team_index][queue_id]);
//remove his time from sum
m_SumOfWaitTimes[team_index][queue_id] -= m_WaitTimes[team_index][queue_id][(*lastPlayerAddedPointer)];
//set average time to new
m_WaitTimes[team_index][queue_id][(*lastPlayerAddedPointer)] = timeInQueue;
//add new time to sum
m_SumOfWaitTimes[team_index][queue_id] += timeInQueue;
//set index of last player added to next one
(*lastPlayerAddedPointer)++;
(*lastPlayerAddedPointer) %= COUNT_OF_PLAYERS_TO_AVERAGE_WAIT_TIME;
}
uint32 BattleGroundQueue::GetAverageQueueWaitTime(GroupQueueInfo* ginfo, BGQueueIdBasedOnLevel queue_id)
{
uint8 team_index = BG_TEAM_ALLIANCE; //default set to BG_TEAM_ALLIANCE - or non rated arenas!
if( !ginfo->ArenaType )
{
if( ginfo->Team == HORDE )
team_index = BG_TEAM_HORDE;
}
else
{
if( ginfo->IsRated )
team_index = BG_TEAM_HORDE; //for rated arenas use BG_TEAM_HORDE
}
//check if there is enought values(we always add values > 0)
if(m_WaitTimes[team_index][queue_id][COUNT_OF_PLAYERS_TO_AVERAGE_WAIT_TIME - 1] )
return (m_SumOfWaitTimes[team_index][queue_id] / COUNT_OF_PLAYERS_TO_AVERAGE_WAIT_TIME);
else
//if there aren't enough values return 0 - not available
return 0;
}
//remove player from queue and from group info, if group info is empty then remove it too
void BattleGroundQueue::RemovePlayer(const uint64& guid, bool decreaseInvitedCount)
{
@ -232,7 +291,7 @@ void BattleGroundQueue::RemovePlayer(const uint64& guid, bool decreaseInvitedCou
}
sLog.outDebug("BattleGroundQueue: Removing player GUID %u, from queue_id %u", GUID_LOPART(guid), (uint32)queue_id);
// ALL variables are corrcetly set
// ALL variables are correctly set
// We can ignore leveling up in queue - it should not cause crash
// remove player from group
// if only one player there, remove group
@ -257,6 +316,22 @@ void BattleGroundQueue::RemovePlayer(const uint64& guid, bool decreaseInvitedCou
if( (decreaseInvitedCount && !group->ArenaType) || (group->ArenaType && group->IsRated && group->Players.empty()) )
AnnounceWorld(group, guid, false);
//if player leaves queue and he is invited to rated arena match, then he have to loose
if( group->IsInvitedToBGInstanceGUID && group->IsRated && decreaseInvitedCount )
{
ArenaTeam * at = objmgr.GetArenaTeamById(group->ArenaTeamId);
if( at )
{
sLog.outDebug("UPDATING memberLost's personal arena rating for %u by opponents rating: %u", GUID_LOPART(guid), group->OpponentsTeamRating);
Player *plr = objmgr.GetPlayer(guid);
if( plr )
at->MemberLost(plr, group->OpponentsTeamRating);
else
at->OfflineMemberLost(guid, group->OpponentsTeamRating);
at->SaveToDB();
}
}
// remove group queue info if needed
if( group->Players.empty() )
{
@ -278,7 +353,7 @@ void BattleGroundQueue::RemovePlayer(const uint64& guid, bool decreaseInvitedCou
plr2->RemoveBattleGroundQueueId(bgQueueTypeId); // must be called this way, because if you move this call to
// queue->removeplayer, it causes bugs
WorldPacket data;
sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, plr2->GetTeam(), queueSlot, STATUS_NONE, 0, 0);
sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, queueSlot, STATUS_NONE, 0, 0);
plr2->GetSession()->SendPacket(&data);
}
// then actually delete, this may delete the group as well!
@ -355,13 +430,10 @@ bool BattleGroundQueue::InviteGroupToBG(GroupQueueInfo * ginfo, BattleGround * b
// set invitation
ginfo->IsInvitedToBGInstanceGUID = bg->GetInstanceID();
BattleGroundQueueTypeId bgQueueTypeId = BattleGroundMgr::BGQueueTypeId(bg->GetTypeID(), bg->GetArenaType());
BGQueueIdBasedOnLevel queue_id = bg->GetQueueId();
// loop through the players
for(std::map<uint64,PlayerQueueInfo*>::iterator itr = ginfo->Players.begin(); itr != ginfo->Players.end(); ++itr)
{
// set status
itr->second->InviteTime = getMSTime();
itr->second->LastInviteTime = getMSTime();
// get the player
Player* plr = objmgr.GetPlayer(itr->first);
// if offline, skip him, this should not happen - player is removed from queue when he logs out
@ -369,6 +441,7 @@ bool BattleGroundQueue::InviteGroupToBG(GroupQueueInfo * ginfo, BattleGround * b
continue;
// invite the player
PlayerInvitedToBGUpdateAverageWaitTime(ginfo, queue_id);
sBattleGroundMgr.InvitePlayer(plr, bg->GetInstanceID(), bg->GetTypeID(), ginfo->Team);
WorldPacket data;
@ -378,7 +451,7 @@ bool BattleGroundQueue::InviteGroupToBG(GroupQueueInfo * ginfo, BattleGround * b
sLog.outDebug("Battleground: invited plr %s (%u) to BG instance %u queueindex %u bgtype %u, I can't help it if they don't press the enter battle button.",plr->GetName(),plr->GetGUIDLow(),bg->GetInstanceID(),queueSlot,bg->GetTypeID());
// send status packet
sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, side?side:plr->GetTeam(), queueSlot, STATUS_WAIT_JOIN, INVITE_ACCEPT_WAIT_TIME, 0);
sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, queueSlot, STATUS_WAIT_JOIN, INVITE_ACCEPT_WAIT_TIME, 0);
plr->GetSession()->SendPacket(&data);
}
return true;
@ -410,7 +483,6 @@ void BattleGroundQueue::BGEndedRemoveInvites(BattleGround *bg)
{
// after removing this much playerinfos, the ginfo will be deleted, so we'll use a for loop
uint32 to_remove = ginfo->Players.size();
uint32 team = ginfo->Team;
for(uint32 j = 0; j < to_remove; j++)
{
// always remove the first one in the group
@ -436,7 +508,7 @@ void BattleGroundQueue::BGEndedRemoveInvites(BattleGround *bg)
// remove player from queue, this might delete the ginfo as well! don't use that pointer after this!
RemovePlayer(itr2->first, true);
WorldPacket data;
sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, team, queueSlot, STATUS_NONE, 0, 0);
sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, queueSlot, STATUS_NONE, 0, 0);
plr->GetSession()->SendPacket(&data);
}
}
@ -499,7 +571,7 @@ void BattleGroundQueue::FillPlayersToBG(BattleGround* bg, BGQueueIdBasedOnLevel
//if ali selection is already empty, then kick horde group, but if there are less horde than ali in bg - break;
if( !m_SelectionPools[BG_TEAM_ALLIANCE].GetPlayerCount() )
{
if( aliFree <= diffHorde - 1 )
if( aliFree <= diffHorde + 1 )
break;
m_SelectionPools[BG_TEAM_HORDE].KickGroup(diffHorde - diffAli);
}
@ -514,7 +586,7 @@ void BattleGroundQueue::FillPlayersToBG(BattleGround* bg, BGQueueIdBasedOnLevel
}
if( !m_SelectionPools[BG_TEAM_HORDE].GetPlayerCount() )
{
if( hordeFree <= diffAli - 1 )
if( hordeFree <= diffAli + 1 )
break;
m_SelectionPools[BG_TEAM_ALLIANCE].KickGroup(diffAli - diffHorde);
}
@ -622,7 +694,7 @@ bool BattleGroundQueue::CheckNormalMatch(BattleGround* bg_template, BGQueueIdBas
return false;
}
//allow 1v0 if debug bg
if( sBattleGroundMgr.isTesting() && (m_SelectionPools[BG_TEAM_ALLIANCE].GetPlayerCount() || m_SelectionPools[BG_TEAM_HORDE].GetPlayerCount()) )
if( sBattleGroundMgr.isTesting() && bg_template->isBattleGround() && (m_SelectionPools[BG_TEAM_ALLIANCE].GetPlayerCount() || m_SelectionPools[BG_TEAM_HORDE].GetPlayerCount()) )
return true;
//return true if there are enough players in selection pools - enable to work .debug bg command correctly
return m_SelectionPools[BG_TEAM_ALLIANCE].GetPlayerCount() >= minPlayers && m_SelectionPools[BG_TEAM_HORDE].GetPlayerCount() >= minPlayers;
@ -995,7 +1067,7 @@ bool BGQueueInviteEvent::Execute(uint64 /*e_time*/, uint32 /*p_time*/)
if (qItr != qpMap.end() && qItr->second.GroupInfo->IsInvitedToBGInstanceGUID == m_BgInstanceGUID)
{
WorldPacket data;
sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, qItr->second.GroupInfo->Team, queueSlot, STATUS_WAIT_JOIN, INVITATION_REMIND_TIME, 0);
sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, queueSlot, STATUS_WAIT_JOIN, INVITATION_REMIND_TIME, 0);
plr->GetSession()->SendPacket(&data);
}
}
@ -1030,21 +1102,11 @@ bool BGQueueRemoveEvent::Execute(uint64 /*e_time*/, uint32 /*p_time*/)
BattleGroundQueue::QueuedPlayersMap::iterator qMapItr = qpMap.find(m_PlayerGuid);
if (qMapItr != qpMap.end() && qMapItr->second.GroupInfo && qMapItr->second.GroupInfo->IsInvitedToBGInstanceGUID == m_BgInstanceGUID)
{
if (qMapItr->second.GroupInfo->IsRated)
{
ArenaTeam * at = objmgr.GetArenaTeamById(qMapItr->second.GroupInfo->ArenaTeamId);
if (at)
{
sLog.outDebug("UPDATING memberLost's personal arena rating for %u by opponents rating: %u", GUID_LOPART(plr->GetGUID()), qMapItr->second.GroupInfo->OpponentsTeamRating);
at->MemberLost(plr, qMapItr->second.GroupInfo->OpponentsTeamRating);
at->SaveToDB();
}
}
plr->RemoveBattleGroundQueueId(bgQueueTypeId);
sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].RemovePlayer(m_PlayerGuid, true);
sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].Update(bg->GetTypeID(), bg->GetQueueId());
WorldPacket data;
sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, m_PlayersTeam, queueSlot, STATUS_NONE, 0, 0);
sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, queueSlot, STATUS_NONE, 0, 0);
plr->GetSession()->SendPacket(&data);
}
}
@ -1075,10 +1137,10 @@ BattleGroundMgr::BattleGroundMgr() : m_AutoDistributionTimeChecker(0), m_ArenaTe
BattleGroundMgr::~BattleGroundMgr()
{
DeleteAlllBattleGrounds();
DeleteAllBattleGrounds();
}
void BattleGroundMgr::DeleteAlllBattleGrounds()
void BattleGroundMgr::DeleteAllBattleGrounds()
{
for(uint32 i = BATTLEGROUND_TYPE_NONE; i < MAX_BATTLEGROUND_TYPE_ID; i++)
{
@ -1086,6 +1148,8 @@ void BattleGroundMgr::DeleteAlllBattleGrounds()
{
BattleGround * bg = itr->second;
m_BattleGrounds[i].erase(itr++);
if(!m_ClientBattleGroundIds[i][bg->GetQueueId()].empty())
m_ClientBattleGroundIds[i][bg->GetQueueId()].erase(bg->GetClientInstanceID());
delete bg;
}
}
@ -1120,6 +1184,8 @@ void BattleGroundMgr::Update(uint32 diff)
{
BattleGround * bg = itr->second;
m_BattleGrounds[i].erase(itr);
if(!m_ClientBattleGroundIds[i][bg->GetQueueId()].empty())
m_ClientBattleGroundIds[i][bg->GetQueueId()].erase(bg->GetClientInstanceID());
delete bg;
}
}
@ -1160,7 +1226,7 @@ void BattleGroundMgr::Update(uint32 diff)
}
}
void BattleGroundMgr::BuildBattleGroundStatusPacket(WorldPacket *data, BattleGround *bg, uint32 team, uint8 QueueSlot, uint8 StatusID, uint32 Time1, uint32 Time2, uint32 arenatype, uint8 israted)
void BattleGroundMgr::BuildBattleGroundStatusPacket(WorldPacket *data, BattleGround *bg, uint8 QueueSlot, uint8 StatusID, uint32 Time1, uint32 Time2, uint32 arenatype)
{
// we can be in 3 queues in same time...
if(StatusID == 0)
@ -1175,9 +1241,10 @@ void BattleGroundMgr::BuildBattleGroundStatusPacket(WorldPacket *data, BattleGro
*data << uint32(QueueSlot); // queue id (0...2) - player can be in 3 queues in time
// uint64 in client
*data << uint64( uint64(arenatype ? arenatype : bg->GetArenaType()) | (uint64(0x0D) << 8) | (uint64(bg->GetTypeID()) << 16) | (uint64(0x1F90) << 48) );
*data << uint32(0); // unknown
*data << uint32(bg->GetClientInstanceID());
// alliance/horde for BG and skirmish/rated for Arenas
*data << uint8(bg->isArena() ? ( israted ? israted : bg->isRated() ) : bg->GetTeamIndexByTeamId(team));
// following displays the minimap-icon 0 = faction icon 1 = arenaicon
*data << uint8(bg->isArena());
/* *data << uint8(arenatype ? arenatype : bg->GetArenaType()); // team type (0=BG, 2=2x2, 3=3x3, 5=5x5), for arenas // NOT PROPER VALUE IF ARENA ISN'T RUNNING YET!!!!
switch(bg->GetTypeID()) // value depends on bg id
{
@ -1227,10 +1294,7 @@ void BattleGroundMgr::BuildBattleGroundStatusPacket(WorldPacket *data, BattleGro
*data << uint16(0x1F90); // unk value 8080
*data << uint32(bg->GetInstanceID()); // instance id
if(bg->isBattleGround())
*data << uint8(bg->GetTeamIndexByTeamId(team)); // team
else
*data << uint8(israted?israted:bg->isRated()); // is rated battle
*data << uint8(bg->isArena()); // minimap-icon 0=faction 1=arena
*/
*data << uint32(StatusID); // status
switch(StatusID)
@ -1386,10 +1450,10 @@ void BattleGroundMgr::BuildPlaySoundPacket(WorldPacket *data, uint32 soundid)
*data << uint32(soundid);
}
void BattleGroundMgr::BuildPlayerLeftBattleGroundPacket(WorldPacket *data, Player *plr)
void BattleGroundMgr::BuildPlayerLeftBattleGroundPacket(WorldPacket *data, const uint64& guid)
{
data->Initialize(SMSG_BATTLEGROUND_PLAYER_LEFT, 8);
*data << uint64(plr->GetGUID());
*data << uint64(guid);
}
void BattleGroundMgr::BuildPlayerJoinedBattleGroundPacket(WorldPacket *data, Player *plr)
@ -1435,6 +1499,25 @@ void BattleGroundMgr::InvitePlayer(Player* plr, uint32 bgInstanceGUID, BattleGro
plr->m_Events.AddEvent(removeEvent, plr->m_Events.CalculateTime(INVITE_ACCEPT_WAIT_TIME));
}
BattleGround * BattleGroundMgr::GetBattleGroundThroughClientInstance(uint32 instanceId, BattleGroundTypeId bgTypeId, BGQueueIdBasedOnLevel queue_id)
{
//cause at HandleBattleGroundJoinOpcode the clients sends the instanceid he gets from
//SMSG_BATTLEFIELD_LIST we need to find the battleground with this clientinstance-id
BattleGround* bg = GetBattleGroundTemplate(bgTypeId);
if( !bg )
return NULL;
if(bg->isArena())
return GetBattleGround(instanceId, bgTypeId);
for(BattleGroundSet::iterator itr = m_BattleGrounds[bgTypeId].begin(); itr != m_BattleGrounds[bgTypeId].end(); ++itr)
{
if(itr->second->GetClientInstanceID() == instanceId)
return itr->second;
}
return NULL;
}
BattleGround * BattleGroundMgr::GetBattleGround(uint32 InstanceID, BattleGroundTypeId bgTypeId)
{
//search if needed
@ -1459,6 +1542,28 @@ BattleGround * BattleGroundMgr::GetBattleGroundTemplate(BattleGroundTypeId bgTyp
return m_BattleGrounds[bgTypeId].empty() ? NULL : m_BattleGrounds[bgTypeId].begin()->second;
}
uint32 BattleGroundMgr::CreateClientVisibleInstanceId(BattleGroundTypeId bgTypeId, BGQueueIdBasedOnLevel queue_id)
{
if( IsArenaType(bgTypeId) )
return 0; //arenas don't have client-instanceids
// we create here an instanceid, which is just for
// displaying this to the client and without any other use..
// the client-instanceIds are unique for each battleground-type
// the instance-id just needs to be as low as possible, beginning with 1
// the following works, because std::set is default ordered with "<"
// the optimalization would be to use as bitmask std::vector<uint32> - but that would only make code unreadable
uint32 lastId = 0;
for(std::set<uint32>::iterator itr = m_ClientBattleGroundIds[bgTypeId][queue_id].begin(); itr != m_ClientBattleGroundIds[bgTypeId][queue_id].end();)
{
if( (++lastId) != *itr) //if there is a gap between the ids, we will break..
break;
lastId = *itr;
}
m_ClientBattleGroundIds[bgTypeId][queue_id].insert(lastId + 1);
return lastId + 1;
}
// create a new battleground that will really be used to play
BattleGround * BattleGroundMgr::CreateNewBattleGround(BattleGroundTypeId bgTypeId, BGQueueIdBasedOnLevel queue_id, uint8 arenaType, bool isRated)
{
@ -1528,6 +1633,7 @@ BattleGround * BattleGroundMgr::CreateNewBattleGround(BattleGroundTypeId bgTypeI
// generate a new instance id
bg->SetInstanceID(MapManager::Instance().GenerateInstanceId()); // set instance id
bg->SetClientInstanceID(CreateClientVisibleInstanceId(bgTypeId, queue_id));
// reset the new bg (set status to status_wait_queue from status_none)
bg->Reset();
@ -1752,7 +1858,7 @@ void BattleGroundMgr::DistributeArenaPoints()
for (std::map<uint32, uint32>::iterator plr_itr = PlayerPoints.begin(); plr_itr != PlayerPoints.end(); ++plr_itr)
{
//update to database
CharacterDatabase.PExecute("UPDATE characters SET arena_pending_points = '%u' WHERE `guid` = '%u'", plr_itr->second, plr_itr->first);
CharacterDatabase.PExecute("UPDATE characters SET arena_pending_points = '%u' WHERE guid = '%u'", plr_itr->second, plr_itr->first);
//add points if player is online
Player* pl = objmgr.GetPlayer(plr_itr->first);
if (pl)
@ -1803,16 +1909,11 @@ void BattleGroundMgr::BuildBattleGroundListPacket(WorldPacket *data, const uint6
uint32 count = 0;
*data << uint32(0x00); // number of bg instances
for(BattleGroundSet::iterator itr = m_BattleGrounds[bgTypeId].begin(); itr != m_BattleGrounds[bgTypeId].end(); ++itr)
uint32 queue_id = plr->GetBattleGroundQueueIdFromLevel(bgTypeId);
for(std::set<uint32>::iterator itr = m_ClientBattleGroundIds[bgTypeId][queue_id].begin(); itr != m_ClientBattleGroundIds[bgTypeId][queue_id].end();++itr)
{
// skip sending battleground template
if( itr == m_BattleGrounds[bgTypeId].begin() )
continue;
if( PlayerLevel >= itr->second->GetMinLevel() && PlayerLevel <= itr->second->GetMaxLevel() )
{
*data << uint32(itr->second->GetInstanceID());
++count;
}
*data << uint32(*itr);
++count;
}
data->put<uint32>( count_pos , count);
}

View file

@ -30,12 +30,11 @@ typedef std::list<BattleGround*> BGFreeSlotQueueType;
typedef UNORDERED_MAP<uint32, BattleGroundTypeId> BattleMastersMap;
#define BATTLEGROUND_ARENA_POINT_DISTRIBUTION_DAY 86400 // seconds in a day
#define COUNT_OF_PLAYERS_TO_AVERAGE_WAIT_TIME 10
struct GroupQueueInfo; // type predefinition
struct PlayerQueueInfo // stores information for players in queue
{
uint32 InviteTime; // first invite time
uint32 LastInviteTime; // last invite time
uint32 LastOnlineTime; // for tracking and removing offline players from queue after 5 minutes
GroupQueueInfo * GroupInfo; // pointer to the associated groupqueueinfo
};
@ -79,6 +78,9 @@ class BattleGroundQueue
GroupQueueInfo * AddGroup(Player * leader, BattleGroundTypeId bgTypeId, uint8 ArenaType, bool isRated, bool isPremade, uint32 ArenaRating, uint32 ArenaTeamId = 0);
void AddPlayer(Player *plr, GroupQueueInfo *ginfo);
void RemovePlayer(const uint64& guid, bool decreaseInvitedCount);
void PlayerInvitedToBGUpdateAverageWaitTime(GroupQueueInfo* ginfo, BGQueueIdBasedOnLevel queue_id);
uint32 GetAverageQueueWaitTime(GroupQueueInfo* ginfo, BGQueueIdBasedOnLevel queue_id);
void DecreaseGroupLength(uint32 queueId, uint32 AsGroup);
void BGEndedRemoveInvites(BattleGround * bg);
void AnnounceWorld(GroupQueueInfo *ginfo, const uint64& playerGUID, bool isAddedToQueue);
@ -120,6 +122,9 @@ class BattleGroundQueue
private:
bool InviteGroupToBG(GroupQueueInfo * ginfo, BattleGround * bg, uint32 side);
uint32 m_WaitTimes[BG_TEAMS_COUNT][MAX_BATTLEGROUND_QUEUES][COUNT_OF_PLAYERS_TO_AVERAGE_WAIT_TIME];
uint32 m_WaitTimeLastPlayer[BG_TEAMS_COUNT][MAX_BATTLEGROUND_QUEUES];
uint32 m_SumOfWaitTimes[BG_TEAMS_COUNT][MAX_BATTLEGROUND_QUEUES];
};
/*
@ -174,12 +179,12 @@ class BattleGroundMgr
/* Packet Building */
void BuildPlayerJoinedBattleGroundPacket(WorldPacket *data, Player *plr);
void BuildPlayerLeftBattleGroundPacket(WorldPacket *data, Player *plr);
void BuildPlayerLeftBattleGroundPacket(WorldPacket *data, const uint64& guid);
void BuildBattleGroundListPacket(WorldPacket *data, const uint64& guid, Player *plr, BattleGroundTypeId bgTypeId);
void BuildGroupJoinedBattlegroundPacket(WorldPacket *data, BattleGroundTypeId bgTypeId);
void BuildUpdateWorldStatePacket(WorldPacket *data, uint32 field, uint32 value);
void BuildPvpLogDataPacket(WorldPacket *data, BattleGround *bg);
void BuildBattleGroundStatusPacket(WorldPacket *data, BattleGround *bg, uint32 team, uint8 QueueSlot, uint8 StatusID, uint32 Time1, uint32 Time2, uint32 arenatype = 0, uint8 israted = 0);
void BuildBattleGroundStatusPacket(WorldPacket *data, BattleGround *bg, uint8 QueueSlot, uint8 StatusID, uint32 Time1, uint32 Time2, uint32 arenatype = 0);
void BuildPlaySoundPacket(WorldPacket *data, uint32 soundid);
void SendAreaSpiritHealerQueryOpcode(Player *pl, BattleGround *bg, const uint64& guid);
@ -188,18 +193,20 @@ class BattleGroundMgr
void InvitePlayer(Player* plr, uint32 bgInstanceGUID, BattleGroundTypeId bgTypeId, uint32 team);
/* Battlegrounds */
BattleGround* GetBattleGroundThroughClientInstance(uint32 instanceId, BattleGroundTypeId bgTypeId, BGQueueIdBasedOnLevel queue_id);
BattleGround* GetBattleGround(uint32 InstanceID, BattleGroundTypeId bgTypeId); //there must be uint32 because MAX_BATTLEGROUND_TYPE_ID means unknown
BattleGround * GetBattleGroundTemplate(BattleGroundTypeId bgTypeId);
BattleGround * CreateNewBattleGround(BattleGroundTypeId bgTypeId, BGQueueIdBasedOnLevel queue_id, uint8 arenaType, bool isRated);
BattleGround* GetBattleGroundTemplate(BattleGroundTypeId bgTypeId);
BattleGround* CreateNewBattleGround(BattleGroundTypeId bgTypeId, BGQueueIdBasedOnLevel queue_id, uint8 arenaType, bool isRated);
uint32 CreateBattleGround(BattleGroundTypeId bgTypeId, bool IsArena, uint32 MinPlayersPerTeam, uint32 MaxPlayersPerTeam, uint32 LevelMin, uint32 LevelMax, char* BattleGroundName, uint32 MapID, float Team1StartLocX, float Team1StartLocY, float Team1StartLocZ, float Team1StartLocO, float Team2StartLocX, float Team2StartLocY, float Team2StartLocZ, float Team2StartLocO);
void AddBattleGround(uint32 InstanceID, BattleGroundTypeId bgTypeId, BattleGround* BG) { m_BattleGrounds[bgTypeId][InstanceID] = BG; };
void RemoveBattleGround(uint32 instanceID, BattleGroundTypeId bgTypeId) { m_BattleGrounds[bgTypeId].erase(instanceID); }
uint32 CreateClientVisibleInstanceId(BattleGroundTypeId bgTypeId, BGQueueIdBasedOnLevel queue_id);
void CreateInitialBattleGrounds();
void DeleteAlllBattleGrounds();
void DeleteAllBattleGrounds();
void SendToBattleGround(Player *pl, uint32 InstanceID, BattleGroundTypeId bgTypeId);
@ -240,6 +247,7 @@ class BattleGroundMgr
/* Battlegrounds */
BattleGroundSet m_BattleGrounds[MAX_BATTLEGROUND_TYPE_ID];
std::set<uint32> m_ClientBattleGroundIds[MAX_BATTLEGROUND_TYPE_ID][MAX_BATTLEGROUND_QUEUES]; //the instanceids just visible for the client
uint32 m_NextRatingDiscardUpdate;
uint64 m_NextAutoDistributionTime;
uint32 m_AutoDistributionTimeChecker;

View file

@ -20,15 +20,23 @@
#include "Player.h"
#include "BattleGround.h"
#include "BattleGroundNA.h"
#include "Creature.h"
#include "ObjectMgr.h"
#include "MapManager.h"
#include "WorldPacket.h"
#include "Language.h"
BattleGroundNA::BattleGroundNA()
{
m_BgObjects.resize(BG_NA_OBJECT_MAX);
m_StartDelayTimes[BG_STARTING_EVENT_FIRST] = BG_START_DELAY_1M;
m_StartDelayTimes[BG_STARTING_EVENT_SECOND] = BG_START_DELAY_30S;
m_StartDelayTimes[BG_STARTING_EVENT_THIRD] = BG_START_DELAY_15S;
m_StartDelayTimes[BG_STARTING_EVENT_FOURTH] = BG_START_DELAY_NONE;
//we must set messageIds
m_StartMessageIds[BG_STARTING_EVENT_FIRST] = LANG_ARENA_ONE_MINUTE;
m_StartMessageIds[BG_STARTING_EVENT_SECOND] = LANG_ARENA_THIRTY_SECONDS;
m_StartMessageIds[BG_STARTING_EVENT_THIRD] = LANG_ARENA_FIFTEEN_SECONDS;
m_StartMessageIds[BG_STARTING_EVENT_FOURTH] = LANG_ARENA_HAS_BEGUN;
}
BattleGroundNA::~BattleGroundNA()
@ -40,70 +48,27 @@ void BattleGroundNA::Update(uint32 diff)
{
BattleGround::Update(diff);
// after bg start we get there
if (GetStatus() == STATUS_WAIT_JOIN && GetPlayersSize())
{
ModifyStartDelayTime(diff);
if (!(m_Events & 0x01))
{
m_Events |= 0x01;
// setup here, only when at least one player has ported to the map
if(!SetupBattleGround())
{
EndNow();
return;
}
for(uint32 i = BG_NA_OBJECT_DOOR_1; i <= BG_NA_OBJECT_DOOR_4; i++)
SpawnBGObject(i, RESPAWN_IMMEDIATELY);
SetStartDelayTime(START_DELAY1);
SendMessageToAll(LANG_ARENA_ONE_MINUTE);
}
// After 30 seconds, warning is signalled
else if (GetStartDelayTime() <= START_DELAY2 && !(m_Events & 0x04))
{
m_Events |= 0x04;
SendMessageToAll(LANG_ARENA_THIRTY_SECONDS);
}
// After 15 seconds, warning is signalled
else if (GetStartDelayTime() <= START_DELAY3 && !(m_Events & 0x08))
{
m_Events |= 0x08;
SendMessageToAll(LANG_ARENA_FIFTEEN_SECONDS);
}
// delay expired (1 minute)
else if (GetStartDelayTime() <= 0 && !(m_Events & 0x10))
{
m_Events |= 0x10;
for(uint32 i = BG_NA_OBJECT_DOOR_1; i <= BG_NA_OBJECT_DOOR_2; i++)
DoorOpen(i);
for(uint32 i = BG_NA_OBJECT_BUFF_1; i <= BG_NA_OBJECT_BUFF_2; i++)
SpawnBGObject(i, 60);
SendMessageToAll(LANG_ARENA_BEGUN);
SetStatus(STATUS_IN_PROGRESS);
SetStartDelayTime(0);
for(BattleGroundPlayerMap::const_iterator itr = GetPlayers().begin(); itr != GetPlayers().end(); ++itr)
if(Player *plr = objmgr.GetPlayer(itr->first))
plr->RemoveAurasDueToSpell(SPELL_ARENA_PREPARATION);
if(!GetPlayersCountByTeam(ALLIANCE) && GetPlayersCountByTeam(HORDE))
EndBattleGround(HORDE);
else if(GetPlayersCountByTeam(ALLIANCE) && !GetPlayersCountByTeam(HORDE))
EndBattleGround(ALLIANCE);
}
}
/*if(GetStatus() == STATUS_IN_PROGRESS)
{
// update something
}*/
}
void BattleGroundNA::StartingEventCloseDoors()
{
for(uint32 i = BG_NA_OBJECT_DOOR_1; i <= BG_NA_OBJECT_DOOR_4; i++)
SpawnBGObject(i, RESPAWN_IMMEDIATELY);
}
void BattleGroundNA::StartingEventOpenDoors()
{
for(uint32 i = BG_NA_OBJECT_DOOR_1; i <= BG_NA_OBJECT_DOOR_2; i++)
DoorOpen(i);
for(uint32 i = BG_NA_OBJECT_BUFF_1; i <= BG_NA_OBJECT_BUFF_2; i++)
SpawnBGObject(i, 60);
}
void BattleGroundNA::AddPlayer(Player *plr)
{
BattleGround::AddPlayer(plr);
@ -124,10 +89,7 @@ void BattleGroundNA::RemovePlayer(Player* /*plr*/, uint64 /*guid*/)
UpdateWorldState(0xa0f, GetAlivePlayersCountByTeam(ALLIANCE));
UpdateWorldState(0xa10, GetAlivePlayersCountByTeam(HORDE));
if(!GetAlivePlayersCountByTeam(ALLIANCE) && GetPlayersCountByTeam(HORDE))
EndBattleGround(HORDE);
else if(GetPlayersCountByTeam(ALLIANCE) && !GetAlivePlayersCountByTeam(HORDE))
EndBattleGround(ALLIANCE);
CheckArenaWinConditions();
}
void BattleGroundNA::HandleKillPlayer(Player *player, Player *killer)
@ -146,16 +108,7 @@ void BattleGroundNA::HandleKillPlayer(Player *player, Player *killer)
UpdateWorldState(0xa0f, GetAlivePlayersCountByTeam(ALLIANCE));
UpdateWorldState(0xa10, GetAlivePlayersCountByTeam(HORDE));
if(!GetAlivePlayersCountByTeam(ALLIANCE))
{
// all opponents killed
EndBattleGround(HORDE);
}
else if(!GetAlivePlayersCountByTeam(HORDE))
{
// all opponents killed
EndBattleGround(ALLIANCE);
}
CheckArenaWinConditions();
}
bool BattleGroundNA::HandlePlayerUnderMap(Player *player)

View file

@ -60,6 +60,8 @@ class BattleGroundNA : public BattleGround
/* inherited from BattlegroundClass */
virtual void AddPlayer(Player *plr);
virtual void StartingEventCloseDoors();
virtual void StartingEventOpenDoors();
void RemovePlayer(Player *plr, uint64 guid);
void HandleAreaTrigger(Player *Source, uint32 Trigger);

View file

@ -20,15 +20,23 @@
#include "Player.h"
#include "BattleGround.h"
#include "BattleGroundRL.h"
#include "Creature.h"
#include "ObjectMgr.h"
#include "MapManager.h"
#include "Language.h"
#include "WorldPacket.h"
BattleGroundRL::BattleGroundRL()
{
m_BgObjects.resize(BG_RL_OBJECT_MAX);
m_StartDelayTimes[BG_STARTING_EVENT_FIRST] = BG_START_DELAY_1M;
m_StartDelayTimes[BG_STARTING_EVENT_SECOND] = BG_START_DELAY_30S;
m_StartDelayTimes[BG_STARTING_EVENT_THIRD] = BG_START_DELAY_15S;
m_StartDelayTimes[BG_STARTING_EVENT_FOURTH] = BG_START_DELAY_NONE;
//we must set messageIds
m_StartMessageIds[BG_STARTING_EVENT_FIRST] = LANG_ARENA_ONE_MINUTE;
m_StartMessageIds[BG_STARTING_EVENT_SECOND] = LANG_ARENA_THIRTY_SECONDS;
m_StartMessageIds[BG_STARTING_EVENT_THIRD] = LANG_ARENA_FIFTEEN_SECONDS;
m_StartMessageIds[BG_STARTING_EVENT_FOURTH] = LANG_ARENA_HAS_BEGUN;
}
BattleGroundRL::~BattleGroundRL()
@ -40,71 +48,27 @@ void BattleGroundRL::Update(uint32 diff)
{
BattleGround::Update(diff);
if (GetStatus() == STATUS_WAIT_JOIN && GetPlayersSize())
{
ModifyStartDelayTime(diff);
if (!(m_Events & 0x01))
{
m_Events |= 0x01;
// setup here, only when at least one player has ported to the map
if(!SetupBattleGround())
{
EndNow();
return;
}
for(uint32 i = BG_RL_OBJECT_DOOR_1; i <= BG_RL_OBJECT_DOOR_2; i++)
SpawnBGObject(i, RESPAWN_IMMEDIATELY);
SetStartDelayTime(START_DELAY1);
SendMessageToAll(LANG_ARENA_ONE_MINUTE);
}
// After 30 seconds, warning is signalled
else if (GetStartDelayTime() <= START_DELAY2 && !(m_Events & 0x04))
{
m_Events |= 0x04;
SendMessageToAll(LANG_ARENA_THIRTY_SECONDS);
}
// After 15 seconds, warning is signalled
else if (GetStartDelayTime() <= START_DELAY3 && !(m_Events & 0x08))
{
m_Events |= 0x08;
SendMessageToAll(LANG_ARENA_FIFTEEN_SECONDS);
}
// delay expired (1 minute)
else if (GetStartDelayTime() <= 0 && !(m_Events & 0x10))
{
m_Events |= 0x10;
for(uint32 i = BG_RL_OBJECT_DOOR_1; i <= BG_RL_OBJECT_DOOR_2; i++)
DoorOpen(i);
for(uint32 i = BG_RL_OBJECT_BUFF_1; i <= BG_RL_OBJECT_BUFF_2; i++)
SpawnBGObject(i, 60);
SendMessageToAll(LANG_ARENA_BEGUN);
SetStatus(STATUS_IN_PROGRESS);
SetStartDelayTime(0);
for(BattleGroundPlayerMap::const_iterator itr = GetPlayers().begin(); itr != GetPlayers().end(); ++itr)
if(Player *plr = objmgr.GetPlayer(itr->first))
plr->RemoveAurasDueToSpell(SPELL_ARENA_PREPARATION);
if(!GetPlayersCountByTeam(ALLIANCE) && GetPlayersCountByTeam(HORDE))
EndBattleGround(HORDE);
else if(GetPlayersCountByTeam(ALLIANCE) && !GetPlayersCountByTeam(HORDE))
EndBattleGround(ALLIANCE);
}
}
/*if(GetStatus() == STATUS_IN_PROGRESS)
{
// update something
}*/
}
void BattleGroundRL::StartingEventCloseDoors()
{
for(uint32 i = BG_RL_OBJECT_DOOR_1; i <= BG_RL_OBJECT_DOOR_2; i++)
SpawnBGObject(i, RESPAWN_IMMEDIATELY);
}
void BattleGroundRL::StartingEventOpenDoors()
{
for(uint32 i = BG_RL_OBJECT_DOOR_1; i <= BG_RL_OBJECT_DOOR_2; i++)
DoorOpen(i);
for(uint32 i = BG_RL_OBJECT_BUFF_1; i <= BG_RL_OBJECT_BUFF_2; i++)
SpawnBGObject(i, 60);
}
void BattleGroundRL::AddPlayer(Player *plr)
{
BattleGround::AddPlayer(plr);
@ -125,10 +89,7 @@ void BattleGroundRL::RemovePlayer(Player* /*plr*/, uint64 /*guid*/)
UpdateWorldState(0xbb8, GetAlivePlayersCountByTeam(ALLIANCE));
UpdateWorldState(0xbb9, GetAlivePlayersCountByTeam(HORDE));
if(!GetAlivePlayersCountByTeam(ALLIANCE) && GetPlayersCountByTeam(HORDE))
EndBattleGround(HORDE);
else if(GetPlayersCountByTeam(ALLIANCE) && !GetAlivePlayersCountByTeam(HORDE))
EndBattleGround(ALLIANCE);
CheckArenaWinConditions();
}
void BattleGroundRL::HandleKillPlayer(Player *player, Player *killer)
@ -147,16 +108,7 @@ void BattleGroundRL::HandleKillPlayer(Player *player, Player *killer)
UpdateWorldState(0xbb8, GetAlivePlayersCountByTeam(ALLIANCE));
UpdateWorldState(0xbb9, GetAlivePlayersCountByTeam(HORDE));
if(!GetAlivePlayersCountByTeam(ALLIANCE))
{
// all opponents killed
EndBattleGround(HORDE);
}
else if(!GetAlivePlayersCountByTeam(HORDE))
{
// all opponents killed
EndBattleGround(ALLIANCE);
}
CheckArenaWinConditions();
}
bool BattleGroundRL::HandlePlayerUnderMap(Player *player)

View file

@ -58,6 +58,8 @@ class BattleGroundRL : public BattleGround
virtual void AddPlayer(Player *plr);
virtual void Reset();
virtual void FillInitialWorldStates(WorldPacket &d);
virtual void StartingEventCloseDoors();
virtual void StartingEventOpenDoors();
void RemovePlayer(Player *plr, uint64 guid);
void HandleAreaTrigger(Player *Source, uint32 Trigger);

View file

@ -19,10 +19,20 @@
#include "Player.h"
#include "BattleGround.h"
#include "BattleGroundRV.h"
#include "Language.h"
BattleGroundRV::BattleGroundRV()
{
m_StartDelayTimes[BG_STARTING_EVENT_FIRST] = BG_START_DELAY_1M;
m_StartDelayTimes[BG_STARTING_EVENT_SECOND] = BG_START_DELAY_30S;
m_StartDelayTimes[BG_STARTING_EVENT_THIRD] = BG_START_DELAY_15S;
m_StartDelayTimes[BG_STARTING_EVENT_FOURTH] = BG_START_DELAY_NONE;
//we must set messageIds
m_StartMessageIds[BG_STARTING_EVENT_FIRST] = LANG_ARENA_ONE_MINUTE;
m_StartMessageIds[BG_STARTING_EVENT_SECOND] = LANG_ARENA_THIRTY_SECONDS;
m_StartMessageIds[BG_STARTING_EVENT_THIRD] = LANG_ARENA_FIFTEEN_SECONDS;
m_StartMessageIds[BG_STARTING_EVENT_FOURTH] = LANG_ARENA_HAS_BEGUN;
}
BattleGroundRV::~BattleGroundRV()
@ -35,6 +45,14 @@ void BattleGroundRV::Update(uint32 diff)
BattleGround::Update(diff);
}
void BattleGroundRV::StartingEventCloseDoors()
{
}
void BattleGroundRV::StartingEventOpenDoors()
{
}
void BattleGroundRV::AddPlayer(Player *plr)
{
BattleGround::AddPlayer(plr);

View file

@ -39,6 +39,9 @@ class BattleGroundRV : public BattleGround
/* inherited from BattlegroundClass */
virtual void AddPlayer(Player *plr);
virtual void StartingEventCloseDoors();
virtual void StartingEventOpenDoors();
void RemovePlayer(Player *plr, uint64 guid);
void HandleAreaTrigger(Player *Source, uint32 Trigger);
bool SetupBattleGround();

View file

@ -16,13 +16,18 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "Player.h"
#include "BattleGround.h"
#include "BattleGroundSA.h"
#include "Player.h"
#include "Language.h"
BattleGroundSA::BattleGroundSA()
{
//TODO FIX ME!
m_StartMessageIds[BG_STARTING_EVENT_FIRST] = LANG_BG_WS_START_TWO_MINUTES;
m_StartMessageIds[BG_STARTING_EVENT_SECOND] = LANG_BG_WS_START_ONE_MINUTE;
m_StartMessageIds[BG_STARTING_EVENT_THIRD] = LANG_BG_WS_START_HALF_MINUTE;
m_StartMessageIds[BG_STARTING_EVENT_FOURTH] = LANG_BG_WS_HAS_BEGUN;
}
BattleGroundSA::~BattleGroundSA()
@ -35,6 +40,14 @@ void BattleGroundSA::Update(uint32 diff)
BattleGround::Update(diff);
}
void BattleGroundSA::StartingEventCloseDoors()
{
}
void BattleGroundSA::StartingEventOpenDoors()
{
}
void BattleGroundSA::AddPlayer(Player *plr)
{
BattleGround::AddPlayer(plr);

View file

@ -39,6 +39,8 @@ class BattleGroundSA : public BattleGround
/* inherited from BattlegroundClass */
virtual void AddPlayer(Player *plr);
virtual void StartingEventCloseDoors();
virtual void StartingEventOpenDoors();
void RemovePlayer(Player *plr,uint64 guid);
void HandleAreaTrigger(Player *Source, uint32 Trigger);

View file

@ -22,8 +22,6 @@
#include "BattleGroundWS.h"
#include "Creature.h"
#include "GameObject.h"
#include "Chat.h"
#include "MapManager.h"
#include "ObjectMgr.h"
#include "WorldPacket.h"
#include "Language.h"
@ -32,6 +30,11 @@ BattleGroundWS::BattleGroundWS()
{
m_BgObjects.resize(BG_WS_OBJECT_MAX);
m_BgCreatures.resize(BG_CREATURES_MAX_WS);
m_StartMessageIds[BG_STARTING_EVENT_FIRST] = LANG_BG_WS_START_TWO_MINUTES;
m_StartMessageIds[BG_STARTING_EVENT_SECOND] = LANG_BG_WS_START_ONE_MINUTE;
m_StartMessageIds[BG_STARTING_EVENT_THIRD] = LANG_BG_WS_START_HALF_MINUTE;
m_StartMessageIds[BG_STARTING_EVENT_FOURTH] = LANG_BG_WS_HAS_BEGUN;
}
BattleGroundWS::~BattleGroundWS()
@ -42,75 +45,7 @@ void BattleGroundWS::Update(uint32 diff)
{
BattleGround::Update(diff);
// after bg start we get there (once)
if (GetStatus() == STATUS_WAIT_JOIN && GetPlayersSize())
{
ModifyStartDelayTime(diff);
if(!(m_Events & 0x01))
{
m_Events |= 0x01;
// setup here, only when at least one player has ported to the map
if(!SetupBattleGround())
{
EndNow();
return;
}
// for(uint32 i = WS_SPIRIT_MAIN_ALLIANCE; i <= WS_SPIRIT_MAIN_HORDE; i++)
// SpawnBGCreature(i, RESPAWN_IMMEDIATELY);
for(uint32 i = BG_WS_OBJECT_DOOR_A_1; i <= BG_WS_OBJECT_DOOR_H_4; i++)
{
SpawnBGObject(i, RESPAWN_IMMEDIATELY);
DoorClose(i);
}
for(uint32 i = BG_WS_OBJECT_A_FLAG; i <= BG_WS_OBJECT_BERSERKBUFF_2; i++)
SpawnBGObject(i, RESPAWN_ONE_DAY);
SetStartDelayTime(START_DELAY0);
}
// After 1 minute, warning is signalled
else if(GetStartDelayTime() <= START_DELAY1 && !(m_Events & 0x04))
{
m_Events |= 0x04;
SendMessageToAll(GetMangosString(LANG_BG_WS_ONE_MINUTE));
}
// After 1,5 minute, warning is signalled
else if(GetStartDelayTime() <= START_DELAY2 && !(m_Events & 0x08))
{
m_Events |= 0x08;
SendMessageToAll(GetMangosString(LANG_BG_WS_HALF_MINUTE));
}
// After 2 minutes, gates OPEN ! x)
else if(GetStartDelayTime() < 0 && !(m_Events & 0x10))
{
m_Events |= 0x10;
for(uint32 i = BG_WS_OBJECT_DOOR_A_1; i <= BG_WS_OBJECT_DOOR_A_4; i++)
DoorOpen(i);
for(uint32 i = BG_WS_OBJECT_DOOR_H_1; i <= BG_WS_OBJECT_DOOR_H_2; i++)
DoorOpen(i);
SpawnBGObject(BG_WS_OBJECT_DOOR_A_5, RESPAWN_ONE_DAY);
SpawnBGObject(BG_WS_OBJECT_DOOR_A_6, RESPAWN_ONE_DAY);
SpawnBGObject(BG_WS_OBJECT_DOOR_H_3, RESPAWN_ONE_DAY);
SpawnBGObject(BG_WS_OBJECT_DOOR_H_4, RESPAWN_ONE_DAY);
for(uint32 i = BG_WS_OBJECT_A_FLAG; i <= BG_WS_OBJECT_BERSERKBUFF_2; i++)
SpawnBGObject(i, RESPAWN_IMMEDIATELY);
SendMessageToAll(GetMangosString(LANG_BG_WS_BEGIN));
PlaySoundToAll(SOUND_BG_START);
SetStatus(STATUS_IN_PROGRESS);
for(BattleGroundPlayerMap::const_iterator itr = GetPlayers().begin(); itr != GetPlayers().end(); ++itr)
if(Player* plr = objmgr.GetPlayer(itr->first))
plr->RemoveAurasDueToSpell(SPELL_PREPARATION);
}
}
else if(GetStatus() == STATUS_IN_PROGRESS)
if(GetStatus() == STATUS_IN_PROGRESS)
{
if(m_FlagState[BG_TEAM_ALLIANCE] == BG_WS_FLAG_STATE_WAIT_RESPAWN)
{
@ -155,6 +90,33 @@ void BattleGroundWS::Update(uint32 diff)
}
}
void BattleGroundWS::StartingEventCloseDoors()
{
for(uint32 i = BG_WS_OBJECT_DOOR_A_1; i <= BG_WS_OBJECT_DOOR_H_4; i++)
{
DoorClose(i);
SpawnBGObject(i, RESPAWN_IMMEDIATELY);
}
for(uint32 i = BG_WS_OBJECT_A_FLAG; i <= BG_WS_OBJECT_BERSERKBUFF_2; i++)
SpawnBGObject(i, RESPAWN_ONE_DAY);
}
void BattleGroundWS::StartingEventOpenDoors()
{
for(uint32 i = BG_WS_OBJECT_DOOR_A_1; i <= BG_WS_OBJECT_DOOR_A_4; i++)
DoorOpen(i);
for(uint32 i = BG_WS_OBJECT_DOOR_H_1; i <= BG_WS_OBJECT_DOOR_H_2; i++)
DoorOpen(i);
SpawnBGObject(BG_WS_OBJECT_DOOR_A_5, RESPAWN_ONE_DAY);
SpawnBGObject(BG_WS_OBJECT_DOOR_A_6, RESPAWN_ONE_DAY);
SpawnBGObject(BG_WS_OBJECT_DOOR_H_3, RESPAWN_ONE_DAY);
SpawnBGObject(BG_WS_OBJECT_DOOR_H_4, RESPAWN_ONE_DAY);
for(uint32 i = BG_WS_OBJECT_A_FLAG; i <= BG_WS_OBJECT_BERSERKBUFF_2; i++)
SpawnBGObject(i, RESPAWN_IMMEDIATELY);
}
void BattleGroundWS::AddPlayer(Player *plr)
{
BattleGround::AddPlayer(plr);
@ -182,7 +144,7 @@ void BattleGroundWS::RespawnFlag(uint32 Team, bool captured)
//when map_update will be allowed for battlegrounds this code will be useless
SpawnBGObject(BG_WS_OBJECT_H_FLAG, RESPAWN_IMMEDIATELY);
SpawnBGObject(BG_WS_OBJECT_A_FLAG, RESPAWN_IMMEDIATELY);
SendMessageToAll(GetMangosString(LANG_BG_WS_F_PLACED));
SendMessageToAll(LANG_BG_WS_F_PLACED, CHAT_MSG_BG_SYSTEM_NEUTRAL);
PlaySoundToAll(BG_WS_SOUND_FLAGS_RESPAWNED); // flag respawned sound...
}
}
@ -196,12 +158,12 @@ void BattleGroundWS::RespawnFlagAfterDrop(uint32 team)
if(team == ALLIANCE)
{
SpawnBGObject(BG_WS_OBJECT_A_FLAG, RESPAWN_IMMEDIATELY);
SendMessageToAll(GetMangosString(LANG_BG_WS_ALLIANCE_FLAG_RESPAWNED));
SendMessageToAll(LANG_BG_WS_ALLIANCE_FLAG_RESPAWNED, CHAT_MSG_BG_SYSTEM_NEUTRAL);
}
else
{
SpawnBGObject(BG_WS_OBJECT_H_FLAG, RESPAWN_IMMEDIATELY);
SendMessageToAll(GetMangosString(LANG_BG_WS_HORDE_FLAG_RESPAWNED));
SendMessageToAll(LANG_BG_WS_HORDE_FLAG_RESPAWNED, CHAT_MSG_BG_SYSTEM_NEUTRAL);
}
PlaySoundToAll(BG_WS_SOUND_FLAGS_RESPAWNED);
@ -220,11 +182,7 @@ void BattleGroundWS::EventPlayerCapturedFlag(Player *Source)
if(GetStatus() != STATUS_IN_PROGRESS)
return;
uint8 type = 0;
uint32 winner = 0;
const char *message = "";
//TODO FIX reputation and honor gains for low level players!
Source->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_ENTER_PVP_COMBAT);
if(Source->GetTeam() == ALLIANCE)
@ -236,13 +194,10 @@ void BattleGroundWS::EventPlayerCapturedFlag(Player *Source)
m_FlagState[BG_TEAM_HORDE] = BG_WS_FLAG_STATE_WAIT_RESPAWN;
// Drop Horde Flag from Player
Source->RemoveAurasDueToSpell(BG_WS_SPELL_WARSONG_FLAG);
message = GetMangosString(LANG_BG_WS_CAPTURED_HF);
type = CHAT_MSG_BG_SYSTEM_ALLIANCE;
if(GetTeamScore(ALLIANCE) < BG_WS_MAX_TEAM_SCORE)
AddPoint(ALLIANCE, 1);
PlaySoundToAll(BG_WS_SOUND_FLAG_CAPTURED_ALLIANCE);
RewardReputationToTeam(890, 35, ALLIANCE); // +35 reputation
RewardHonorToTeam(40, ALLIANCE); // +40 bonushonor
RewardReputationToTeam(890, m_ReputationCapture, ALLIANCE);
}
else
{
@ -253,26 +208,26 @@ void BattleGroundWS::EventPlayerCapturedFlag(Player *Source)
m_FlagState[BG_TEAM_ALLIANCE] = BG_WS_FLAG_STATE_WAIT_RESPAWN;
// Drop Alliance Flag from Player
Source->RemoveAurasDueToSpell(BG_WS_SPELL_SILVERWING_FLAG);
message = GetMangosString(LANG_BG_WS_CAPTURED_AF);
type = CHAT_MSG_BG_SYSTEM_HORDE;
if(GetTeamScore(HORDE) < BG_WS_MAX_TEAM_SCORE)
AddPoint(HORDE, 1);
PlaySoundToAll(BG_WS_SOUND_FLAG_CAPTURED_HORDE);
RewardReputationToTeam(889, 35, HORDE); // +35 reputation
RewardHonorToTeam(40, HORDE); // +40 bonushonor
RewardReputationToTeam(889, m_ReputationCapture, HORDE);
}
//for flag capture is reward 2 honorable kills
RewardHonorToTeam(GetBonusHonorFromKill(2), Source->GetTeam());
SpawnBGObject(BG_WS_OBJECT_H_FLAG, BG_WS_FLAG_RESPAWN_TIME);
SpawnBGObject(BG_WS_OBJECT_A_FLAG, BG_WS_FLAG_RESPAWN_TIME);
WorldPacket data;
ChatHandler::FillMessageData(&data, Source->GetSession(), type, LANG_UNIVERSAL, NULL, Source->GetGUID(), message, NULL);
SendPacketToAll(&data);
if(Source->GetTeam() == ALLIANCE)
SendMessageToAll(LANG_BG_WS_CAPTURED_HF, CHAT_MSG_BG_SYSTEM_ALLIANCE, Source);
else
SendMessageToAll(LANG_BG_WS_CAPTURED_AF, CHAT_MSG_BG_SYSTEM_HORDE, Source);
UpdateFlagState(Source->GetTeam(), 1); // flag state none
UpdateTeamScore(Source->GetTeam());
// only flag capture should be updated
UpdatePlayerScore(Source, SCORE_FLAG_CAPTURES, 1); // +1 flag captures...
UpdatePlayerScore(Source, SCORE_FLAG_CAPTURES, 1); // +1 flag captures
if(GetTeamScore(ALLIANCE) == BG_WS_MAX_TEAM_SCORE)
winner = ALLIANCE;
@ -324,8 +279,6 @@ void BattleGroundWS::EventPlayerDroppedFlag(Player *Source)
return;
}
const char *message = "";
uint8 type = 0;
bool set = false;
if(Source->GetTeam() == ALLIANCE)
@ -337,8 +290,6 @@ void BattleGroundWS::EventPlayerDroppedFlag(Player *Source)
SetHordeFlagPicker(0);
Source->RemoveAurasDueToSpell(BG_WS_SPELL_WARSONG_FLAG);
m_FlagState[BG_TEAM_HORDE] = BG_WS_FLAG_STATE_ON_GROUND;
message = GetMangosString(LANG_BG_WS_DROPPED_HF);
type = CHAT_MSG_BG_SYSTEM_HORDE;
Source->CastSpell(Source, BG_WS_SPELL_WARSONG_FLAG_DROPPED, true);
set = true;
}
@ -352,8 +303,6 @@ void BattleGroundWS::EventPlayerDroppedFlag(Player *Source)
SetAllianceFlagPicker(0);
Source->RemoveAurasDueToSpell(BG_WS_SPELL_SILVERWING_FLAG);
m_FlagState[BG_TEAM_ALLIANCE] = BG_WS_FLAG_STATE_ON_GROUND;
message = GetMangosString(LANG_BG_WS_DROPPED_AF);
type = CHAT_MSG_BG_SYSTEM_ALLIANCE;
Source->CastSpell(Source, BG_WS_SPELL_SILVERWING_FLAG_DROPPED, true);
set = true;
}
@ -364,14 +313,16 @@ void BattleGroundWS::EventPlayerDroppedFlag(Player *Source)
Source->CastSpell(Source, SPELL_RECENTLY_DROPPED_FLAG, true);
UpdateFlagState(Source->GetTeam(), 1);
WorldPacket data;
ChatHandler::FillMessageData(&data, Source->GetSession(), type, LANG_UNIVERSAL, NULL, Source->GetGUID(), message, NULL);
SendPacketToAll(&data);
if(Source->GetTeam() == ALLIANCE)
{
SendMessageToAll(LANG_BG_WS_DROPPED_HF, CHAT_MSG_BG_SYSTEM_HORDE, Source);
UpdateWorldState(BG_WS_FLAG_UNK_HORDE, uint32(-1));
}
else
{
SendMessageToAll(LANG_BG_WS_DROPPED_AF, CHAT_MSG_BG_SYSTEM_ALLIANCE, Source);
UpdateWorldState(BG_WS_FLAG_UNK_ALLIANCE, uint32(-1));
}
m_FlagsDropTimer[GetTeamIndexByTeamId(Source->GetTeam()) ? 0 : 1] = BG_WS_FLAG_DROP_TIME;
}
@ -382,14 +333,14 @@ void BattleGroundWS::EventPlayerClickedOnFlag(Player *Source, GameObject* target
if(GetStatus() != STATUS_IN_PROGRESS)
return;
const char *message = NULL;
uint8 type = 0;
int32 message_id = 0;
ChatMsg type;
//alliance flag picked up from base
if(Source->GetTeam() == HORDE && GetFlagState(ALLIANCE) == BG_WS_FLAG_STATE_ON_BASE
&& m_BgObjects[BG_WS_OBJECT_A_FLAG] == target_obj->GetGUID())
{
message = GetMangosString(LANG_BG_WS_PICKEDUP_AF);
message_id = LANG_BG_WS_PICKEDUP_AF;
type = CHAT_MSG_BG_SYSTEM_HORDE;
PlaySoundToAll(BG_WS_SOUND_ALLIANCE_FLAG_PICKED_UP);
SpawnBGObject(BG_WS_OBJECT_A_FLAG, RESPAWN_ONE_DAY);
@ -405,7 +356,7 @@ void BattleGroundWS::EventPlayerClickedOnFlag(Player *Source, GameObject* target
if (Source->GetTeam() == ALLIANCE && GetFlagState(HORDE) == BG_WS_FLAG_STATE_ON_BASE
&& m_BgObjects[BG_WS_OBJECT_H_FLAG] == target_obj->GetGUID())
{
message = GetMangosString(LANG_BG_WS_PICKEDUP_HF);
message_id = LANG_BG_WS_PICKEDUP_HF;
type = CHAT_MSG_BG_SYSTEM_ALLIANCE;
PlaySoundToAll(BG_WS_SOUND_HORDE_FLAG_PICKED_UP);
SpawnBGObject(BG_WS_OBJECT_H_FLAG, RESPAWN_ONE_DAY);
@ -422,7 +373,7 @@ void BattleGroundWS::EventPlayerClickedOnFlag(Player *Source, GameObject* target
{
if(Source->GetTeam() == ALLIANCE)
{
message = GetMangosString(LANG_BG_WS_RETURNED_AF);
message_id = LANG_BG_WS_RETURNED_AF;
type = CHAT_MSG_BG_SYSTEM_ALLIANCE;
UpdateFlagState(HORDE, BG_WS_FLAG_STATE_WAIT_RESPAWN);
RespawnFlag(ALLIANCE, false);
@ -432,7 +383,7 @@ void BattleGroundWS::EventPlayerClickedOnFlag(Player *Source, GameObject* target
}
else
{
message = GetMangosString(LANG_BG_WS_PICKEDUP_AF);
message_id = LANG_BG_WS_PICKEDUP_AF;
type = CHAT_MSG_BG_SYSTEM_HORDE;
PlaySoundToAll(BG_WS_SOUND_ALLIANCE_FLAG_PICKED_UP);
SpawnBGObject(BG_WS_OBJECT_A_FLAG, RESPAWN_ONE_DAY);
@ -451,7 +402,7 @@ void BattleGroundWS::EventPlayerClickedOnFlag(Player *Source, GameObject* target
{
if(Source->GetTeam() == HORDE)
{
message = GetMangosString(LANG_BG_WS_RETURNED_HF);
message_id = LANG_BG_WS_RETURNED_HF;
type = CHAT_MSG_BG_SYSTEM_HORDE;
UpdateFlagState(ALLIANCE, BG_WS_FLAG_STATE_WAIT_RESPAWN);
RespawnFlag(HORDE, false);
@ -461,7 +412,7 @@ void BattleGroundWS::EventPlayerClickedOnFlag(Player *Source, GameObject* target
}
else
{
message = GetMangosString(LANG_BG_WS_PICKEDUP_HF);
message_id = LANG_BG_WS_PICKEDUP_HF;
type = CHAT_MSG_BG_SYSTEM_ALLIANCE;
PlaySoundToAll(BG_WS_SOUND_HORDE_FLAG_PICKED_UP);
SpawnBGObject(BG_WS_OBJECT_H_FLAG, RESPAWN_ONE_DAY);
@ -475,12 +426,10 @@ void BattleGroundWS::EventPlayerClickedOnFlag(Player *Source, GameObject* target
//target_obj->Delete();
}
if (!type)
if (!message_id)
return;
WorldPacket data;
ChatHandler::FillMessageData(&data, Source->GetSession(), type, LANG_UNIVERSAL, NULL, Source->GetGUID(), message, NULL);
SendPacketToAll(&data);
SendMessageToAll(message_id, type, Source);
Source->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_ENTER_PVP_COMBAT);
}
@ -642,16 +591,33 @@ void BattleGroundWS::Reset()
m_FlagState[BG_TEAM_HORDE] = BG_WS_FLAG_STATE_ON_BASE;
m_TeamScores[BG_TEAM_ALLIANCE] = 0;
m_TeamScores[BG_TEAM_HORDE] = 0;
bool isBGWeekend = false; //TODO FIXME - call sBattleGroundMgr.IsBGWeekend(m_TypeID); - you must also implement that call!
m_ReputationCapture = (isBGWeekend) ? 45 : 35;
m_HonorWinKills = (isBGWeekend) ? 3 : 1;
m_HonorEndKills = (isBGWeekend) ? 4 : 2;
/* Spirit nodes is static at this BG and then not required deleting at BG reset.
if(m_BgCreatures[WS_SPIRIT_MAIN_ALLIANCE])
DelCreature(WS_SPIRIT_MAIN_ALLIANCE);
if(m_BgCreatures[WS_SPIRIT_MAIN_HORDE])
DelCreature(WS_SPIRIT_MAIN_HORDE);
*/
}
void BattleGroundWS::EndBattleGround(uint32 winner)
{
//win reward
if( winner == ALLIANCE )
RewardHonorToTeam(GetBonusHonorFromKill(m_HonorWinKills), ALLIANCE);
if( winner == HORDE )
RewardHonorToTeam(GetBonusHonorFromKill(m_HonorWinKills), HORDE);
//complete map_end rewards (even if no team wins)
RewardHonorToTeam(GetBonusHonorFromKill(m_HonorEndKills), ALLIANCE);
RewardHonorToTeam(GetBonusHonorFromKill(m_HonorEndKills), HORDE);
BattleGround::EndBattleGround(winner);
}
void BattleGroundWS::HandleKillPlayer(Player *player, Player *killer)
{
if(GetStatus() != STATUS_IN_PROGRESS)
@ -684,6 +650,29 @@ void BattleGroundWS::UpdatePlayerScore(Player *Source, uint32 type, uint32 value
}
}
WorldSafeLocsEntry const* BattleGroundWS::GetClosestGraveYard(Player* player)
{
//if status in progress, it returns main graveyards with spiritguides
//else it will return the graveyard in the flagroom - this is especially good
//if a player dies in preparation phase - then the player can't cheat
//and teleport to the graveyard outside the flagroom
//and start running around, while the doors are still closed
if(player->GetTeam() == ALLIANCE)
{
if(GetStatus() == STATUS_IN_PROGRESS)
return sWorldSafeLocsStore.LookupEntry(WS_GRAVEYARD_MAIN_ALLIANCE);
else
return sWorldSafeLocsStore.LookupEntry(WS_GRAVEYARD_FLAGROOM_ALLIANCE);
}
else
{
if(GetStatus() == STATUS_IN_PROGRESS)
return sWorldSafeLocsStore.LookupEntry(WS_GRAVEYARD_MAIN_HORDE);
else
return sWorldSafeLocsStore.LookupEntry(WS_GRAVEYARD_FLAGROOM_HORDE);
}
}
void BattleGroundWS::FillInitialWorldStates(WorldPacket& data)
{
data << uint32(BG_WS_FLAG_CAPTURES_ALLIANCE) << uint32(GetTeamScore(ALLIANCE));

View file

@ -105,8 +105,10 @@ enum BG_WS_FlagState
enum BG_WS_Graveyards
{
WS_GRAVEYARD_MAIN_ALLIANCE = 771,
WS_GRAVEYARD_MAIN_HORDE = 772
WS_GRAVEYARD_FLAGROOM_ALLIANCE = 769,
WS_GRAVEYARD_FLAGROOM_HORDE = 770,
WS_GRAVEYARD_MAIN_ALLIANCE = 771,
WS_GRAVEYARD_MAIN_HORDE = 772
};
enum BG_WS_CreatureTypes
@ -138,6 +140,8 @@ class BattleGroundWS : public BattleGround
/* inherited from BattlegroundClass */
virtual void AddPlayer(Player *plr);
virtual void StartingEventCloseDoors();
virtual void StartingEventOpenDoors();
/* BG Flags */
uint64 GetAllianceFlagPickerGUID() const { return m_FlagKeepers[BG_TEAM_ALLIANCE]; }
@ -160,6 +164,8 @@ class BattleGroundWS : public BattleGround
void HandleKillPlayer(Player *player, Player *killer);
bool SetupBattleGround();
virtual void Reset();
void EndBattleGround(uint32 winner);
virtual WorldSafeLocsEntry const* GetClosestGraveYard(Player* player);
void UpdateFlagState(uint32 team, uint32 value);
void UpdateTeamScore(uint32 team);
@ -181,5 +187,9 @@ class BattleGroundWS : public BattleGround
uint32 m_TeamScores[2];
int32 m_FlagsTimer[2];
int32 m_FlagsDropTimer[2];
uint32 m_ReputationCapture;
uint32 m_HonorWinKills;
uint32 m_HonorEndKills;
};
#endif

View file

@ -21,7 +21,6 @@
#include "Common.h"
#include "WorldPacket.h"
#include "WorldSession.h"
#include "Opcodes.h"
#include "Player.h"

View file

@ -29,7 +29,6 @@
#include "Guild.h"
#include "UpdateMask.h"
#include "Auth/md5.h"
#include "MapManager.h"
#include "ObjectAccessor.h"
#include "Group.h"
#include "Database/DatabaseImpl.h"

View file

@ -28,7 +28,6 @@
#include "Player.h"
#include "UpdateMask.h"
#include "Chat.h"
#include "MapManager.h"
#include "GridNotifiersImpl.h"
#include "CellImpl.h"
#include "AccountMgr.h"
@ -418,26 +417,25 @@ ChatCommand * ChatHandler::getCommandTable()
static ChatCommand npcCommandTable[] =
{
{ "say", SEC_MODERATOR, false, &ChatHandler::HandleNpcSayCommand, "", NULL },
{ "textemote", SEC_MODERATOR, false, &ChatHandler::HandleNpcTextEmoteCommand, "", NULL },
{ "add", SEC_GAMEMASTER, false, &ChatHandler::HandleNpcAddCommand, "", NULL },
{ "additem", SEC_GAMEMASTER, false, &ChatHandler::HandleNpcAddVendorItemCommand, "", NULL },
{ "addmove", SEC_GAMEMASTER, false, &ChatHandler::HandleNpcAddMoveCommand, "", NULL },
{ "changeentry", SEC_ADMINISTRATOR, false, &ChatHandler::HandleNpcChangeEntryCommand, "", NULL },
{ "changelevel", SEC_GAMEMASTER, false, &ChatHandler::HandleNpcChangeLevelCommand, "", NULL },
{ "delete", SEC_GAMEMASTER, false, &ChatHandler::HandleNpcDeleteCommand, "", NULL },
{ "factionid", SEC_GAMEMASTER, false, &ChatHandler::HandleNpcFactionIdCommand, "", NULL },
{ "flag", SEC_GAMEMASTER, false, &ChatHandler::HandleNpcFlagCommand, "", NULL },
{ "follow", SEC_GAMEMASTER, false, &ChatHandler::HandleNpcFollowCommand, "", NULL },
{ "info", SEC_ADMINISTRATOR, false, &ChatHandler::HandleNpcInfoCommand, "", NULL },
{ "move", SEC_GAMEMASTER, false, &ChatHandler::HandleNpcMoveCommand, "", NULL },
{ "playemote", SEC_ADMINISTRATOR, false, &ChatHandler::HandleNpcPlayEmoteCommand, "", NULL },
{ "setmodel", SEC_GAMEMASTER, false, &ChatHandler::HandleNpcSetModelCommand, "", NULL },
{ "setmovetype", SEC_GAMEMASTER, false, &ChatHandler::HandleNpcSetMoveTypeCommand, "", NULL },
{ "setphase", SEC_GAMEMASTER, false, &ChatHandler::HandleNpcSetPhaseCommand, "", NULL },
{ "spawndist", SEC_GAMEMASTER, false, &ChatHandler::HandleNpcSpawnDistCommand, "", NULL },
{ "spawntime", SEC_GAMEMASTER, false, &ChatHandler::HandleNpcSpawnTimeCommand, "", NULL },
{ "factionid", SEC_GAMEMASTER, false, &ChatHandler::HandleNpcFactionIdCommand, "", NULL },
{ "addmove", SEC_GAMEMASTER, false, &ChatHandler::HandleNpcAddMoveCommand, "", NULL },
{ "setmovetype", SEC_GAMEMASTER, false, &ChatHandler::HandleNpcSetMoveTypeCommand, "", NULL },
{ "move", SEC_GAMEMASTER, false, &ChatHandler::HandleNpcMoveCommand, "", NULL },
{ "changelevel", SEC_GAMEMASTER, false, &ChatHandler::HandleChangeLevelCommand, "", NULL },
{ "setmodel", SEC_GAMEMASTER, false, &ChatHandler::HandleNpcSetModelCommand, "", NULL },
{ "additem", SEC_GAMEMASTER, false, &ChatHandler::HandleAddVendorItemCommand, "", NULL },
{ "delitem", SEC_GAMEMASTER, false, &ChatHandler::HandleDelVendorItemCommand, "", NULL },
{ "flag", SEC_GAMEMASTER, false, &ChatHandler::HandleNpcFlagCommand, "", NULL },
{ "changeentry", SEC_ADMINISTRATOR, false, &ChatHandler::HandleNpcChangeEntryCommand, "", NULL },
{ "info", SEC_ADMINISTRATOR, false, &ChatHandler::HandleNpcInfoCommand, "", NULL },
{ "playemote", SEC_ADMINISTRATOR, false, &ChatHandler::HandleNpcPlayEmoteCommand, "", NULL },
{ "follow", SEC_GAMEMASTER, false, &ChatHandler::HandleNpcFollowCommand, "", NULL },
{ "setphase", SEC_GAMEMASTER, false, &ChatHandler::HandleNpcSetPhaseCommand, "", NULL },
{ "say", SEC_MODERATOR, false, &ChatHandler::HandleNpcSayCommand, "", NULL },
{ "textemote", SEC_MODERATOR, false, &ChatHandler::HandleNpcTextEmoteCommand, "", NULL },
{ "unfollow", SEC_GAMEMASTER, false, &ChatHandler::HandleNpcUnFollowCommand, "", NULL },
{ "whisper", SEC_MODERATOR, false, &ChatHandler::HandleNpcWhisperCommand, "", NULL },
{ "yell", SEC_MODERATOR, false, &ChatHandler::HandleNpcYellCommand, "", NULL },
@ -445,9 +443,9 @@ ChatCommand * ChatHandler::getCommandTable()
{ "setdeathstate", SEC_GAMEMASTER, false, &ChatHandler::HandleNpcSetDeathStateCommand, "", NULL },
//{ TODO: fix or remove this commands
{ "name", SEC_GAMEMASTER, false, &ChatHandler::HandleNameCommand, "", NULL },
{ "subname", SEC_GAMEMASTER, false, &ChatHandler::HandleSubNameCommand, "", NULL },
{ "addweapon", SEC_ADMINISTRATOR, false, &ChatHandler::HandleAddWeaponCommand, "", NULL },
{ "addweapon", SEC_ADMINISTRATOR, false, &ChatHandler::HandleNpcAddWeaponCommand, "", NULL },
{ "name", SEC_GAMEMASTER, false, &ChatHandler::HandleNpcNameCommand, "", NULL },
{ "subname", SEC_GAMEMASTER, false, &ChatHandler::HandleNpcSubNameCommand, "", NULL },
//}
{ NULL, 0, false, NULL, "", NULL }

View file

@ -176,10 +176,14 @@ class ChatHandler
bool HandleModifyPhaseCommand(const char* args);
bool HandleModifyGenderCommand(const char* args);
//-----------------------Npc Commands-----------------------
bool HandleNpcAddCommand(const char* args);
bool HandleNpcAddMoveCommand(const char* args);
bool HandleNpcAddVendorItemCommand(const char* args);
bool HandleNpcChangeEntryCommand(const char *args);
bool HandleNpcChangeLevelCommand(const char* args);
bool HandleNpcDeleteCommand(const char* args);
bool HandleNpcDelVendorItemCommand(const char* args);
bool HandleNpcFactionIdCommand(const char* args);
bool HandleNpcFlagCommand(const char* args);
bool HandleNpcFollowCommand(const char* args);
@ -187,6 +191,7 @@ class ChatHandler
bool HandleNpcMoveCommand(const char* args);
bool HandleNpcPlayEmoteCommand(const char* args);
bool HandleNpcSayCommand(const char* args);
bool HandleNpcSetDeathStateCommand(const char* args);
bool HandleNpcSetModelCommand(const char* args);
bool HandleNpcSetMoveTypeCommand(const char* args);
bool HandleNpcSetPhaseCommand(const char* args);
@ -197,7 +202,12 @@ class ChatHandler
bool HandleNpcUnFollowCommand(const char* args);
bool HandleNpcWhisperCommand(const char* args);
bool HandleNpcYellCommand(const char* args);
bool HandleNpcSetDeathStateCommand(const char* args);
//TODO: NpcCommands that needs to be fixed :
bool HandleNpcAddWeaponCommand(const char* args);
bool HandleNpcNameCommand(const char* args);
bool HandleNpcSubNameCommand(const char* args);
//----------------------------------------------------------
bool HandleReloadAllCommand(const char* args);
bool HandleReloadAllAreaCommand(const char* args);
@ -300,13 +310,8 @@ class ChatHandler
bool HandleDebugSpellFailCommand(const char* args);
bool HandleGUIDCommand(const char* args);
bool HandleNameCommand(const char* args);
bool HandleSubNameCommand(const char* args);
bool HandleItemMoveCommand(const char* args);
bool HandleDeMorphCommand(const char* args);
bool HandleAddVendorItemCommand(const char* args);
bool HandleDelVendorItemCommand(const char* args);
bool HandleChangeLevelCommand(const char* args);
bool HandleSetPoiCommand(const char* args);
bool HandleEquipErrorCommand(const char* args);
bool HandleGoCreatureCommand(const char* args);
@ -341,7 +346,6 @@ class ChatHandler
bool HandleGoXYZCommand(const char* args);
bool HandleGoZoneXYCommand(const char* args);
bool HandleGoGridCommand(const char* args);
bool HandleAddWeaponCommand(const char* args);
bool HandleAllowMovementCommand(const char* args);
bool HandleGoCommand(const char* args);

View file

@ -28,7 +28,6 @@
#include "ChannelMgr.h"
#include "Group.h"
#include "Guild.h"
#include "MapManager.h"
#include "ObjectAccessor.h"
#include "ScriptCalls.h"
#include "Player.h"
@ -522,44 +521,42 @@ void WorldSession::HandleTextEmoteOpcode( WorldPacket & recv_data )
}
EmotesTextEntry const *em = sEmotesTextStore.LookupEntry(text_emote);
if (em)
if (!em)
return;
GetPlayer()->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_DO_EMOTE, text_emote, 0, unit);
uint32 emote_anim = em->textid;
WorldPacket data;
switch(emote_anim)
{
uint32 emote_anim = em->textid;
WorldPacket data;
switch(emote_anim)
{
case EMOTE_STATE_SLEEP:
case EMOTE_STATE_SIT:
case EMOTE_STATE_KNEEL:
case EMOTE_ONESHOT_NONE:
break;
default:
GetPlayer()->HandleEmoteCommand(emote_anim);
break;
}
data.Initialize(SMSG_TEXT_EMOTE, (20+namlen));
data << GetPlayer()->GetGUID();
data << (uint32)text_emote;
data << emoteNum;
data << (uint32)namlen;
if( namlen > 1 )
{
data.append(nam, namlen);
}
else
{
data << (uint8)0x00;
}
GetPlayer()->SendMessageToSetInRange(&data,sWorld.getConfig(CONFIG_LISTEN_RANGE_TEXTEMOTE),true);
//Send scripted event call
if (pCreature && Script)
Script->ReceiveEmote(GetPlayer(),pCreature,text_emote);
case EMOTE_STATE_SLEEP:
case EMOTE_STATE_SIT:
case EMOTE_STATE_KNEEL:
case EMOTE_ONESHOT_NONE:
break;
default:
GetPlayer()->HandleEmoteCommand(emote_anim);
break;
}
data.Initialize(SMSG_TEXT_EMOTE, (20+namlen));
data << GetPlayer()->GetGUID();
data << (uint32)text_emote;
data << emoteNum;
data << (uint32)namlen;
if( namlen > 1 )
data.append(nam, namlen);
else
data << (uint8)0x00;
GetPlayer()->SendMessageToSetInRange(&data,sWorld.getConfig(CONFIG_LISTEN_RANGE_TEXTEMOTE),true);
//Send scripted event call
if (pCreature && Script)
Script->ReceiveEmote(GetPlayer(),pCreature,text_emote);
}
void WorldSession::HandleChatIgnoredOpcode(WorldPacket& recv_data )

View file

@ -20,7 +20,6 @@
#include "Log.h"
#include "WorldPacket.h"
#include "WorldSession.h"
#include "World.h"
#include "ObjectAccessor.h"
#include "CreatureAI.h"
#include "ObjectDefines.h"

View file

@ -20,12 +20,9 @@
#include "Corpse.h"
#include "Player.h"
#include "UpdateMask.h"
#include "MapManager.h"
#include "ObjectAccessor.h"
#include "Database/DatabaseEnv.h"
#include "Opcodes.h"
#include "WorldSession.h"
#include "WorldPacket.h"
#include "GossipDef.h"
#include "World.h"

View file

@ -19,7 +19,6 @@
#include "Common.h"
#include "Database/DatabaseEnv.h"
#include "WorldPacket.h"
#include "WorldSession.h"
#include "World.h"
#include "ObjectMgr.h"
#include "SpellMgr.h"
@ -35,7 +34,6 @@
#include "CreatureAI.h"
#include "CreatureAISelector.h"
#include "Formulas.h"
#include "SpellAuras.h"
#include "WaypointMovementGenerator.h"
#include "InstanceData.h"
#include "BattleGroundMgr.h"
@ -1564,7 +1562,7 @@ SpellEntry const *Creature::reachWithSpellAttack(Unit *pVictim)
SpellEntry const *spellInfo = sSpellStore.LookupEntry(m_spells[i] );
if(!spellInfo)
{
sLog.outError("WORLD: unknown spell id %i\n", m_spells[i]);
sLog.outError("WORLD: unknown spell id %i", m_spells[i]);
continue;
}
@ -1614,7 +1612,7 @@ SpellEntry const *Creature::reachWithSpellCure(Unit *pVictim)
SpellEntry const *spellInfo = sSpellStore.LookupEntry(m_spells[i] );
if(!spellInfo)
{
sLog.outError("WORLD: unknown spell id %i\n", m_spells[i]);
sLog.outError("WORLD: unknown spell id %i", m_spells[i]);
continue;
}
@ -2117,4 +2115,4 @@ void Creature::SetActiveObjectState( bool on )
if(world)
map->Add(this);
}
}

View file

@ -16,7 +16,6 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "CreatureAIRegistry.h"
#include "NullCreatureAI.h"
#include "ReactorAI.h"
#include "AggressorAI.h"
@ -26,7 +25,6 @@
#include "RandomMovementGenerator.h"
#include "CreatureAIImpl.h"
#include "MovementGeneratorImpl.h"
#include "MapManager.h"
#include "CreatureAIRegistry.h"
#include "WaypointMovementGenerator.h"

View file

@ -19,7 +19,6 @@
#ifndef MANGOS_DESTINATIONHOLDERIMP_H
#define MANGOS_DESTINATIONHOLDERIMP_H
#include "Creature.h"
#include "MapManager.h"
#include "DestinationHolder.h"

View file

@ -19,11 +19,9 @@
#include "Common.h"
#include "WorldPacket.h"
#include "WorldSession.h"
#include "World.h"
#include "Log.h"
#include "Opcodes.h"
#include "UpdateData.h"
#include "MapManager.h"
#include "Player.h"
void WorldSession::HandleDuelAcceptedOpcode(WorldPacket& recvPacket)

View file

@ -17,16 +17,11 @@
*/
#include "Common.h"
#include "GameObject.h"
#include "UpdateMask.h"
#include "Opcodes.h"
#include "WorldPacket.h"
#include "WorldSession.h"
#include "World.h"
#include "ObjectAccessor.h"
#include "Database/DatabaseEnv.h"
#include "SpellAuras.h"
#include "MapManager.h"
#include "GridNotifiers.h"
#include "CellImpl.h"
#include "GridNotifiersImpl.h"

View file

@ -22,7 +22,6 @@
#include "MovementGenerator.h"
#include "DestinationHolder.h"
#include "Traveller.h"
#include "MapManager.h"
template<class T>
class MANGOS_DLL_SPEC FleeingMovementGenerator

View file

@ -119,7 +119,7 @@ void WorldSession::HandleGMTicketCreateOpcode( WorldPacket & recv_data )
data.Initialize( SMSG_GMTICKET_CREATE, 4 );
data << uint32(2);
SendPacket( &data );
DEBUG_LOG("update the ticket\n");
DEBUG_LOG("update the ticket");
//TODO: Guard player map
HashMapHolder<Player>::MapType &m = ObjectAccessor::Instance().GetPlayers();

View file

@ -16,7 +16,7 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "GameEvent.h"
#include "GameEventMgr.h"
#include "World.h"
#include "ObjectMgr.h"
#include "PoolHandler.h"
@ -26,9 +26,9 @@
#include "MapManager.h"
#include "Policies/SingletonImp.h"
INSTANTIATE_SINGLETON_1(GameEvent);
INSTANTIATE_SINGLETON_1(GameEventMgr);
bool GameEvent::CheckOneGameEvent(uint16 entry) const
bool GameEventMgr::CheckOneGameEvent(uint16 entry) const
{
// Get the event information
time_t currenttime = time(NULL);
@ -39,7 +39,7 @@ bool GameEvent::CheckOneGameEvent(uint16 entry) const
return false;
}
uint32 GameEvent::NextCheck(uint16 entry) const
uint32 GameEventMgr::NextCheck(uint16 entry) const
{
time_t currenttime = time(NULL);
@ -65,7 +65,7 @@ uint32 GameEvent::NextCheck(uint16 entry) const
return delay;
}
void GameEvent::StartEvent( uint16 event_id, bool overwrite )
void GameEventMgr::StartEvent( uint16 event_id, bool overwrite )
{
AddActiveEvent(event_id);
ApplyNewEvent(event_id);
@ -77,7 +77,7 @@ void GameEvent::StartEvent( uint16 event_id, bool overwrite )
}
}
void GameEvent::StopEvent( uint16 event_id, bool overwrite )
void GameEventMgr::StopEvent( uint16 event_id, bool overwrite )
{
RemoveActiveEvent(event_id);
UnApplyEvent(event_id);
@ -89,7 +89,7 @@ void GameEvent::StopEvent( uint16 event_id, bool overwrite )
}
}
void GameEvent::LoadFromDB()
void GameEventMgr::LoadFromDB()
{
{
QueryResult *result = WorldDatabase.Query("SELECT MAX(entry) FROM game_event");
@ -108,7 +108,7 @@ void GameEvent::LoadFromDB()
mGameEvent.resize(max_event_id+1);
}
QueryResult *result = WorldDatabase.Query("SELECT entry,UNIX_TIMESTAMP(start_time),UNIX_TIMESTAMP(end_time),occurence,length,description FROM game_event");
QueryResult *result = WorldDatabase.Query("SELECT entry,UNIX_TIMESTAMP(start_time),UNIX_TIMESTAMP(end_time),occurence,length,holiday,description FROM game_event");
if( !result )
{
mGameEvent.clear();
@ -142,6 +142,8 @@ void GameEvent::LoadFromDB()
pGameEvent.end = time_t(endtime);
pGameEvent.occurence = fields[3].GetUInt32();
pGameEvent.length = fields[4].GetUInt32();
pGameEvent.holiday_id = fields[5].GetUInt32();
if(pGameEvent.length==0) // length>0 is validity check
{
@ -149,7 +151,16 @@ void GameEvent::LoadFromDB()
continue;
}
pGameEvent.description = fields[5].GetCppString();
if(pGameEvent.holiday_id)
{
if(!sHolidaysStore.LookupEntry(pGameEvent.holiday_id))
{
sLog.outErrorDb("`game_event` game event id (%i) have not existed holiday id %u.",event_id,pGameEvent.holiday_id);
pGameEvent.holiday_id = 0;
}
}
pGameEvent.description = fields[6].GetCppString();
} while( result->NextRow() );
delete result;
@ -405,7 +416,7 @@ void GameEvent::LoadFromDB()
}
}
uint32 GameEvent::Initialize() // return the next event delay in ms
uint32 GameEventMgr::Initialize() // return the next event delay in ms
{
m_ActiveEvents.clear();
uint32 delay = Update();
@ -414,7 +425,7 @@ uint32 GameEvent::Initialize() // return the next e
return delay;
}
uint32 GameEvent::Update() // return the next event delay in ms
uint32 GameEventMgr::Update() // return the next event delay in ms
{
uint32 nextEventDelay = max_ge_check_delay; // 1 day
uint32 calcDelay;
@ -450,7 +461,7 @@ uint32 GameEvent::Update() // return the next e
return (nextEventDelay + 1) * IN_MILISECONDS; // Add 1 second to be sure event has started/stopped at next call
}
void GameEvent::UnApplyEvent(uint16 event_id)
void GameEventMgr::UnApplyEvent(uint16 event_id)
{
sLog.outString("GameEvent %u \"%s\" removed.", event_id, mGameEvent[event_id].description.c_str());
// un-spawn positive event tagged objects
@ -464,7 +475,7 @@ void GameEvent::UnApplyEvent(uint16 event_id)
UpdateEventQuests(event_id, false);
}
void GameEvent::ApplyNewEvent(uint16 event_id)
void GameEventMgr::ApplyNewEvent(uint16 event_id)
{
switch(sWorld.getConfig(CONFIG_EVENT_ANNOUNCE))
{
@ -487,13 +498,13 @@ void GameEvent::ApplyNewEvent(uint16 event_id)
UpdateEventQuests(event_id, true);
}
void GameEvent::GameEventSpawn(int16 event_id)
void GameEventMgr::GameEventSpawn(int16 event_id)
{
int32 internal_event_id = mGameEvent.size() + event_id - 1;
if(internal_event_id < 0 || internal_event_id >= mGameEventCreatureGuids.size())
{
sLog.outError("GameEvent::GameEventSpawn attempt access to out of range mGameEventCreatureGuids element %i (size: %u)",internal_event_id,mGameEventCreatureGuids.size());
sLog.outError("GameEventMgr::GameEventSpawn attempt access to out of range mGameEventCreatureGuids element %i (size: %u)",internal_event_id,mGameEventCreatureGuids.size());
return;
}
@ -526,7 +537,7 @@ void GameEvent::GameEventSpawn(int16 event_id)
if(internal_event_id < 0 || internal_event_id >= mGameEventGameobjectGuids.size())
{
sLog.outError("GameEvent::GameEventSpawn attempt access to out of range mGameEventGameobjectGuids element %i (size: %u)",internal_event_id,mGameEventGameobjectGuids.size());
sLog.outError("GameEventMgr::GameEventSpawn attempt access to out of range mGameEventGameobjectGuids element %i (size: %u)",internal_event_id,mGameEventGameobjectGuids.size());
return;
}
@ -560,7 +571,7 @@ void GameEvent::GameEventSpawn(int16 event_id)
if(internal_event_id < 0 || internal_event_id >= mGameEventPoolIds.size())
{
sLog.outError("GameEvent::GameEventSpawn attempt access to out of range mGameEventPoolIds element %i (size: %u)",internal_event_id,mGameEventPoolIds.size());
sLog.outError("GameEventMgr::GameEventSpawn attempt access to out of range mGameEventPoolIds element %i (size: %u)",internal_event_id,mGameEventPoolIds.size());
return;
}
@ -570,13 +581,13 @@ void GameEvent::GameEventSpawn(int16 event_id)
}
}
void GameEvent::GameEventUnspawn(int16 event_id)
void GameEventMgr::GameEventUnspawn(int16 event_id)
{
int32 internal_event_id = mGameEvent.size() + event_id - 1;
if(internal_event_id < 0 || internal_event_id >= mGameEventCreatureGuids.size())
{
sLog.outError("GameEvent::GameEventUnspawn attempt access to out of range mGameEventCreatureGuids element %i (size: %u)",internal_event_id,mGameEventCreatureGuids.size());
sLog.outError("GameEventMgr::GameEventUnspawn attempt access to out of range mGameEventCreatureGuids element %i (size: %u)",internal_event_id,mGameEventCreatureGuids.size());
return;
}
@ -597,7 +608,7 @@ void GameEvent::GameEventUnspawn(int16 event_id)
if(internal_event_id < 0 || internal_event_id >= mGameEventGameobjectGuids.size())
{
sLog.outError("GameEvent::GameEventUnspawn attempt access to out of range mGameEventGameobjectGuids element %i (size: %u)",internal_event_id,mGameEventGameobjectGuids.size());
sLog.outError("GameEventMgr::GameEventUnspawn attempt access to out of range mGameEventGameobjectGuids element %i (size: %u)",internal_event_id,mGameEventGameobjectGuids.size());
return;
}
@ -614,7 +625,7 @@ void GameEvent::GameEventUnspawn(int16 event_id)
}
if(internal_event_id < 0 || internal_event_id >= mGameEventPoolIds.size())
{
sLog.outError("GameEvent::GameEventUnspawn attempt access to out of range mGameEventPoolIds element %i (size: %u)",internal_event_id,mGameEventPoolIds.size());
sLog.outError("GameEventMgr::GameEventUnspawn attempt access to out of range mGameEventPoolIds element %i (size: %u)",internal_event_id,mGameEventPoolIds.size());
return;
}
@ -624,7 +635,7 @@ void GameEvent::GameEventUnspawn(int16 event_id)
}
}
void GameEvent::ChangeEquipOrModel(int16 event_id, bool activate)
void GameEventMgr::ChangeEquipOrModel(int16 event_id, bool activate)
{
for(ModelEquipList::iterator itr = mGameEventModelEquip[event_id].begin();itr != mGameEventModelEquip[event_id].end();++itr)
{
@ -703,7 +714,7 @@ void GameEvent::ChangeEquipOrModel(int16 event_id, bool activate)
}
}
void GameEvent::UpdateEventQuests(uint16 event_id, bool Activate)
void GameEventMgr::UpdateEventQuests(uint16 event_id, bool Activate)
{
QuestRelList::iterator itr;
for (itr = mGameEventQuests[event_id].begin();itr != mGameEventQuests[event_id].end();++itr)
@ -729,7 +740,19 @@ void GameEvent::UpdateEventQuests(uint16 event_id, bool Activate)
}
}
GameEvent::GameEvent()
GameEventMgr::GameEventMgr()
{
isSystemInit = false;
}
MANGOS_DLL_SPEC bool IsHolidayActive( HolidayIds id )
{
GameEventMgr::GameEventDataMap const& events = gameeventmgr.GetEventMap();
GameEventMgr::ActiveEvents const& ae = gameeventmgr.GetActiveEventList();
for(GameEventMgr::ActiveEvents::const_iterator itr = ae.begin(); itr != ae.end(); ++itr)
if(events[id].holiday_id==id)
return true;
return false;
}

View file

@ -16,15 +16,18 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef MANGOS_GAMEEVENT_H
#define MANGOS_GAMEEVENT_H
#ifndef MANGOS_GAMEEVENT_MGR_H
#define MANGOS_GAMEEVENT_MGR_H
#include "Common.h"
#include "SharedDefines.h"
#include "Platform/Define.h"
#include "Creature.h"
#include "GameObject.h"
#define max_ge_check_delay 86400 // 1 day in seconds
class Creature;
class GameObject;
struct GameEventData
{
GameEventData() : start(1),end(0),occurence(0),length(0) {}
@ -32,6 +35,7 @@ struct GameEventData
time_t end;
uint32 occurence;
uint32 length;
uint32 holiday_id;
std::string description;
bool isValid() const { return length > 0; }
@ -45,11 +49,11 @@ struct ModelEquip
uint32 equipement_id_prev;
};
class GameEvent
class GameEventMgr
{
public:
GameEvent();
~GameEvent() {};
GameEventMgr();
~GameEventMgr() {};
typedef std::set<uint16> ActiveEvents;
typedef std::vector<GameEventData> GameEventDataMap;
ActiveEvents const& GetActiveEventList() const { return m_ActiveEvents; }
@ -92,5 +96,8 @@ class GameEvent
bool isSystemInit;
};
#define gameeventmgr MaNGOS::Singleton<GameEvent>::Instance()
#define gameeventmgr MaNGOS::Singleton<GameEventMgr>::Instance()
MANGOS_DLL_SPEC bool IsHolidayActive(HolidayIds id);
#endif

View file

@ -26,10 +26,8 @@
#include "UpdateMask.h"
#include "Opcodes.h"
#include "WorldPacket.h"
#include "WorldSession.h"
#include "World.h"
#include "Database/DatabaseEnv.h"
#include "MapManager.h"
#include "LootMgr.h"
#include "GridNotifiers.h"
#include "GridNotifiersImpl.h"
@ -472,14 +470,15 @@ void GameObject::getFishLoot(Loot *fishloot, Player* loot_owner)
{
fishloot->clear();
uint32 subzone = GetAreaId();
uint32 zone, subzone;
GetZoneAndAreaId(zone,subzone);
// if subzone loot exist use it
if(LootTemplates_Fishing.HaveLootFor(subzone))
fishloot->FillLoot(subzone, LootTemplates_Fishing, loot_owner,true);
// else use zone loot
else
fishloot->FillLoot(GetZoneId(), LootTemplates_Fishing, loot_owner,true);
fishloot->FillLoot(zone, LootTemplates_Fishing, loot_owner,true);
}
void GameObject::SaveToDB()
@ -1000,11 +999,12 @@ void GameObject::Use(Unit* user)
// 2) if skill == base_zone_skill => 5% chance
// 3) chance is linear dependence from (base_zone_skill-skill)
uint32 subzone = GetAreaId();
uint32 zone, subzone;
GetZoneAndAreaId(zone,subzone);
int32 zone_skill = objmgr.GetFishingBaseSkillLevel( subzone );
if(!zone_skill)
zone_skill = objmgr.GetFishingBaseSkillLevel( GetZoneId() );
zone_skill = objmgr.GetFishingBaseSkillLevel( zone );
//provide error, no fishable zone or area should be 0
if(!zone_skill)
@ -1174,7 +1174,7 @@ void GameObject::Use(Unit* user)
Player* player = (Player*)user;
if( player->isAllowUseBattleGroundObject() )
if( player->CanUseBattleGroundObject() )
{
// in battleground check
BattleGround *bg = player->GetBattleGround();
@ -1199,7 +1199,7 @@ void GameObject::Use(Unit* user)
Player* player = (Player*)user;
if( player->isAllowUseBattleGroundObject() )
if( player->CanUseBattleGroundObject() )
{
// in battleground check
BattleGround *bg = player->GetBattleGround();

View file

@ -22,7 +22,6 @@
#include "UpdateData.h"
#include "Item.h"
#include "Map.h"
#include "MapManager.h"
#include "Transports.h"
#include "ObjectAccessor.h"

View file

@ -862,6 +862,27 @@ namespace MaNGOS
std::vector<WorldPacket*> i_data_cache; // 0 = default, i => i-1 locale index
};
// Prepare using Builder localized packets with caching and send to player
template<class Builder>
class LocalizedPacketListDo
{
public:
typedef std::vector<WorldPacket*> WorldPacketList;
explicit LocalizedPacketListDo(Builder& builder) : i_builder(builder) {}
~LocalizedPacketListDo()
{
for(size_t i = 0; i < i_data_cache.size(); ++i)
for(int j = 0; j < i_data_cache[i].size(); ++j)
delete i_data_cache[i][j];
}
void operator()( Player* p );
private:
Builder& i_builder;
std::vector<WorldPacketList> i_data_cache;
// 0 = default, i => i-1 locale index
};
#ifndef WIN32
template<> void PlayerRelocationNotifier::Visit<Creature>(CreatureMapType &);

View file

@ -562,4 +562,28 @@ void MaNGOS::LocalizedPacketDo<Builder>::operator()( Player* p )
p->SendDirectMessage(data);
}
template<class Builder>
void MaNGOS::LocalizedPacketListDo<Builder>::operator()( Player* p )
{
uint32 loc_idx = p->GetSession()->GetSessionDbLocaleIndex();
uint32 cache_idx = loc_idx+1;
WorldPacketList* data_list;
// create if not cached yet
if(i_data_cache.size() < cache_idx+1 || i_data_cache[cache_idx].empty())
{
if(i_data_cache.size() < cache_idx+1)
i_data_cache.resize(cache_idx+1);
data_list = &i_data_cache[cache_idx];
i_builder(*data_list,loc_idx);
}
else
data_list = &i_data_cache[cache_idx];
for(size_t i = 0; i < data_list->size(); ++i)
p->SendDirectMessage((*data_list)[i]);
}
#endif // MANGOS_GRIDNOTIFIERSIMPL_H

View file

@ -18,7 +18,6 @@
#include "GridStates.h"
#include "GridNotifiers.h"
#include "ObjectAccessor.h"
#include "GameSystem/Grid.h"
#include "Log.h"

View file

@ -26,8 +26,6 @@
#include "ObjectMgr.h"
#include "Player.h"
#include "Group.h"
#include "ObjectAccessor.h"
#include "MapManager.h"
#include "SocialMgr.h"
#include "Util.h"
@ -215,26 +213,16 @@ void WorldSession::HandleGroupDeclineOpcode( WorldPacket & /*recv_data*/ )
Group *group = GetPlayer()->GetGroupInvite();
if (!group) return;
// remember leader if online
Player *leader = objmgr.GetPlayer(group->GetLeaderGUID());
/** error handling **/
// uninvite, group can be deleted
GetPlayer()->UninviteFromGroup();
if(!leader || !leader->GetSession())
return;
/********************/
// everything's fine, do it
if(!group->IsCreated())
{
// note: this means that if you invite more than one person
// and one of them declines before the first one accepts
// all invites will be cleared
// fixme: is that ok ?
group->RemoveAllInvites();
delete group;
}
GetPlayer()->SetGroupInvite(NULL);
// report
WorldPacket data( SMSG_GROUP_DECLINE, 10 ); // guess size
data << GetPlayer()->GetName();
leader->GetSession()->SendPacket( &data );

View file

@ -19,7 +19,6 @@
#include "Database/DatabaseEnv.h"
#include "WorldPacket.h"
#include "WorldSession.h"
#include "MapManager.h"
#include "Player.h"
#include "Opcodes.h"
#include "ObjectMgr.h"
@ -27,6 +26,7 @@
#include "Chat.h"
#include "SocialMgr.h"
#include "Util.h"
#include "Language.h"
Guild::Guild()
{
@ -50,27 +50,25 @@ Guild::~Guild()
}
bool Guild::create(uint64 lGuid, std::string gname)
bool Guild::create(Player* leader, std::string gname)
{
std::string rname;
std::string lName;
if(!objmgr.GetPlayerNameByGUID(lGuid, lName))
return false;
if(objmgr.GetGuildByName(gname))
return false;
sLog.outDebug("GUILD: creating guild %s to leader: %u", gname.c_str(), GUID_LOPART(lGuid));
WorldSession* lSession = leader->GetSession();
if(!lSession)
return false;
leaderGuid = lGuid;
leaderGuid = leader->GetGUID();
name = gname;
GINFO = "";
MOTD = "No message set.";
guildbank_money = 0;
purchased_tabs = 0;
Id = objmgr.GenerateGuildId();
sLog.outDebug("GUILD: creating guild %s to leader: %u", gname.c_str(), GUID_LOPART(leaderGuid));
// gname already assigned to Guild::name, use it to encode string for DB
CharacterDatabase.escape_string(gname);
@ -88,18 +86,13 @@ bool Guild::create(uint64 lGuid, std::string gname)
Id, gname.c_str(), GUID_LOPART(leaderGuid), dbGINFO.c_str(), dbMOTD.c_str(), EmblemStyle, EmblemColor, BorderStyle, BorderColor, BackgroundColor, guildbank_money);
CharacterDatabase.CommitTransaction();
rname = "Guild Master";
CreateRank(rname,GR_RIGHT_ALL);
rname = "Officer";
CreateRank(rname,GR_RIGHT_ALL);
rname = "Veteran";
CreateRank(rname,GR_RIGHT_GCHATLISTEN | GR_RIGHT_GCHATSPEAK);
rname = "Member";
CreateRank(rname,GR_RIGHT_GCHATLISTEN | GR_RIGHT_GCHATSPEAK);
rname = "Initiate";
CreateRank(rname,GR_RIGHT_GCHATLISTEN | GR_RIGHT_GCHATSPEAK);
CreateRank(lSession->GetMangosString(LANG_GUILD_MASTER), GR_RIGHT_ALL);
CreateRank(lSession->GetMangosString(LANG_GUILD_OFFICER), GR_RIGHT_ALL);
CreateRank(lSession->GetMangosString(LANG_GUILD_VETERAN), GR_RIGHT_GCHATLISTEN | GR_RIGHT_GCHATSPEAK);
CreateRank(lSession->GetMangosString(LANG_GUILD_MEMBER), GR_RIGHT_GCHATLISTEN | GR_RIGHT_GCHATSPEAK);
CreateRank(lSession->GetMangosString(LANG_GUILD_INITIATE),GR_RIGHT_GCHATLISTEN | GR_RIGHT_GCHATSPEAK);
return AddMember(lGuid, (uint32)GR_GUILDMASTER);
return AddMember(leaderGuid, (uint32)GR_GUILDMASTER);
}
bool Guild::AddMember(uint64 plGuid, uint32 plRank)

View file

@ -267,7 +267,7 @@ class Guild
Guild();
~Guild();
bool create(uint64 lGuid, std::string gname);
bool create(Player* leader, std::string gname);
void Disband();
typedef std::map<uint32, MemberSlot> MemberList;

View file

@ -24,7 +24,6 @@
#include "Log.h"
#include "Opcodes.h"
#include "Guild.h"
#include "MapManager.h"
#include "GossipDef.h"
#include "SocialMgr.h"
@ -63,7 +62,7 @@ void WorldSession::HandleGuildCreateOpcode(WorldPacket& recvPacket)
return;
Guild *guild = new Guild;
if(!guild->create(GetPlayer()->GetGUID(),gname))
if(!guild->create(GetPlayer(),gname))
{
delete guild;
return;

View file

@ -20,8 +20,6 @@
#include "Creature.h"
#include "CreatureAI.h"
#include "Traveller.h"
#include "MapManager.h"
#include "ObjectAccessor.h"
#include "DestinationHolderImp.h"
#include "ObjectMgr.h"
#include "WorldPacket.h"

View file

@ -17,7 +17,7 @@
*/
#include "IdleMovementGenerator.h"
#include "Creature.h"
#include "Unit.h"
IdleMovementGenerator si_idleMovement;

View file

@ -16,13 +16,11 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "InstanceSaveMgr.h"
#include "Common.h"
#include "Database/SQLStorage.h"
#include "Player.h"
#include "GridNotifiers.h"
#include "WorldSession.h"
#include "Log.h"
#include "GridStates.h"
#include "CellImpl.h"
@ -34,7 +32,6 @@
#include "GridNotifiersImpl.h"
#include "Config/ConfigEnv.h"
#include "Transports.h"
#include "ObjectAccessor.h"
#include "ObjectMgr.h"
#include "World.h"
#include "Group.h"

View file

@ -19,7 +19,6 @@
#include "Common.h"
#include "WorldPacket.h"
#include "WorldSession.h"
#include "World.h"
#include "Opcodes.h"
#include "Log.h"
#include "ObjectMgr.h"

View file

@ -170,7 +170,8 @@ enum MangosStrings
LANG_CONSOLE_COMMAND = 172,
LANG_YOU_CHANGE_RUNIC_POWER = 173,
LANG_YOURS_RUNIC_POWER_CHANGED = 174,
// Room for more level 1 175-199 not used
LANG_LIQUID_STATUS = 175,
// Room for more level 1 176-199 not used
// level 2 chat
LANG_NO_SELECTION = 200,
@ -569,9 +570,11 @@ enum MangosStrings
// Battleground
LANG_BG_A_WINS = 600,
LANG_BG_H_WINS = 601,
LANG_BG_WS_ONE_MINUTE = 602,
LANG_BG_WS_HALF_MINUTE = 603,
LANG_BG_WS_BEGIN = 604,
LANG_BG_WS_START_TWO_MINUTES = 753,
LANG_BG_WS_START_ONE_MINUTE = 602,
LANG_BG_WS_START_HALF_MINUTE = 603,
LANG_BG_WS_HAS_BEGUN = 604,
LANG_BG_WS_CAPTURED_HF = 605,
LANG_BG_WS_CAPTURED_AF = 606,
@ -585,9 +588,10 @@ enum MangosStrings
LANG_BG_WS_ALLIANCE_FLAG_RESPAWNED = 614,
LANG_BG_WS_HORDE_FLAG_RESPAWNED = 615,
LANG_BG_EY_ONE_MINUTE = 636,
LANG_BG_EY_HALF_MINUTE = 637,
LANG_BG_EY_BEGIN = 638,
LANG_BG_EY_START_TWO_MINUTES = 755,
LANG_BG_EY_START_ONE_MINUTE = 636,
LANG_BG_EY_START_HALF_MINUTE = 637,
LANG_BG_EY_HAS_BEGUN = 638,
LANG_BG_AB_ALLY = 650,
LANG_BG_AB_HORDE = 651,
@ -600,9 +604,11 @@ enum MangosStrings
LANG_BG_AB_NODE_DEFENDED = 658,
LANG_BG_AB_NODE_ASSAULTED = 659,
LANG_BG_AB_NODE_CLAIMED = 660,
LANG_BG_AB_ONEMINTOSTART = 661,
LANG_BG_AB_HALFMINTOSTART = 662,
LANG_BG_AB_STARTED = 663,
LANG_BG_AB_START_TWO_MINUTES = 754,
LANG_BG_AB_START_ONE_MINUTE = 661,
LANG_BG_AB_START_HALF_MINUTE = 662,
LANG_BG_AB_HAS_BEGUN = 663,
LANG_BG_AB_A_NEAR_VICTORY = 664,
LANG_BG_AB_H_NEAR_VICTORY = 665,
LANG_BG_MARK_BY_MAIL = 666,
@ -633,7 +639,7 @@ enum MangosStrings
LANG_ARENA_ONE_MINUTE = 701,
LANG_ARENA_THIRTY_SECONDS = 702,
LANG_ARENA_FIFTEEN_SECONDS = 703,
LANG_ARENA_BEGUN = 704,
LANG_ARENA_HAS_BEGUN = 704,
LANG_WAIT_BEFORE_SPEAKING = 705,
LANG_NOT_EQUIPPED_ITEM = 706,
@ -658,7 +664,7 @@ enum MangosStrings
LANG_ARENA_NOT_ENOUGH_PLAYERS = 723, // "Your group does not have enough players to join this match."
LANG_ARENA_GOLD_WINS = 724, // "The Gold Team wins!"
LANG_ARENA_GREEN_WINS = 725, // "The Green Team wins!"
LANG_BATTLEGROUND_PREMATURE_FINISH_WARNING = 726, // The battleground will end soon, because there aren't enough players. Get more ppl or win already!
// = 726, not used
LANG_BG_GROUP_OFFLINE_MEMBER = 727, // "Your group has an offline member. Please remove him before joining."
LANG_BG_GROUP_MIXED_FACTION = 728, // "Your group has players from the opposing faction. You can't join the battleground as a group."
LANG_BG_GROUP_MIXED_LEVELS = 729, // "Your group has players from different battleground brakets. You can't join as group."
@ -680,7 +686,16 @@ enum MangosStrings
LANG_DIST_ARENA_POINTS_TEAM_START = 744,
LANG_DIST_ARENA_POINTS_TEAM_END = 745,
LANG_DIST_ARENA_POINTS_END = 746,
// Room for batleground/arena strings 747-799 not used
// = 747, not used
// = 748, not used
// = 749, not used
LANG_BATTLEGROUND_PREMATURE_FINISH_WARNING = 750, // "Not enough players. This game will close in %u mins."
LANG_BATTLEGROUND_PREMATURE_FINISH_WARNING_SECS = 751, // "Not enough players. This game will close in %u seconds."
// = 752, not used
// LANG_BG_WS_START_TWO_MINUTES = 753,
// LANG_BG_AB_START_TWO_MINUTES = 754,
// LANG_BG_EY_START_TWO_MINUTES = 755,
// Room for batleground/arena strings 756-799 not used
// in game strings
// = 800, not used
@ -694,7 +709,12 @@ enum MangosStrings
LANG_PLAYER_NOT_EXIST_OR_OFFLINE = 808,
LANG_ACCOUNT_FOR_PLAYER_NOT_FOUND = 809,
LANG_ACHIEVEMENT_EARNED = 810,
// Room for in-game strings 811-999 not used
LANG_GUILD_MASTER = 811,
LANG_GUILD_OFFICER = 812,
LANG_GUILD_VETERAN = 813,
LANG_GUILD_MEMBER = 814,
LANG_GUILD_INITIATE = 815,
// Room for in-game strings 816-999 not used
// Level 4 (CLI only commands)
LANG_COMMAND_EXIT = 1000,

View file

@ -18,13 +18,10 @@
#include "Common.h"
#include "Database/DatabaseEnv.h"
#include "WorldPacket.h"
#include "WorldSession.h"
#include "World.h"
#include "Player.h"
#include "Opcodes.h"
#include "Chat.h"
#include "MapManager.h"
#include "ObjectAccessor.h"
#include "Language.h"
#include "AccountMgr.h"

View file

@ -36,6 +36,7 @@
#include "VMapFactory.h"
#endif
//-----------------------Npc Commands-----------------------
bool ChatHandler::HandleNpcSayCommand(const char* args)
{
if(!*args)
@ -119,6 +120,7 @@ bool ChatHandler::HandleNpcWhisperCommand(const char* args)
return true;
}
//----------------------------------------------------------
// global announce
bool ChatHandler::HandleAnnounceCommand(const char* args)
@ -282,8 +284,8 @@ bool ChatHandler::HandleGPSCommand(const char* args)
CellPair cell_val = MaNGOS::ComputeCellPair(obj->GetPositionX(), obj->GetPositionY());
Cell cell(cell_val);
uint32 zone_id = obj->GetZoneId();
uint32 area_id = obj->GetAreaId();
uint32 zone_id, area_id;
obj->GetZoneAndAreaId(zone_id,area_id);
MapEntry const* mapEntry = sMapStore.LookupEntry(obj->GetMapId());
AreaTableEntry const* zoneEntry = GetAreaEntryByAreaID(zone_id);
@ -329,6 +331,12 @@ bool ChatHandler::HandleGPSCommand(const char* args)
cell.GridX(), cell.GridY(), cell.CellX(), cell.CellY(), obj->GetInstanceId(),
zone_x, zone_y, ground_z, floor_z, have_map, have_vmap );
LiquidData liquid_status;
ZLiquidStatus res = map->getLiquidStatus(obj->GetPositionX(), obj->GetPositionY(), obj->GetPositionZ(), MAP_ALL_LIQUIDS, &liquid_status);
if (res)
{
PSendSysMessage(LANG_LIQUID_STATUS, liquid_status.level, liquid_status.depth_level, liquid_status.type, res);
}
return true;
}

File diff suppressed because it is too large Load diff

View file

@ -33,7 +33,6 @@
#include "Guild.h"
#include "ObjectAccessor.h"
#include "MapManager.h"
#include "SpellAuras.h"
#include "ScriptCalls.h"
#include "Language.h"
#include "GridNotifiersImpl.h"
@ -3066,7 +3065,7 @@ bool ChatHandler::HandleGuildCreateCommand(const char* args)
}
Guild *guild = new Guild;
if (!guild->create (player->GetGUID (),guildname))
if (!guild->create (player,guildname))
{
delete guild;
SendSysMessage (LANG_GUILD_NOT_CREATED);
@ -3261,77 +3260,6 @@ bool ChatHandler::HandleGetDistanceCommand(const char* args)
return true;
}
// FIX-ME!!!
bool ChatHandler::HandleAddWeaponCommand(const char* /*args*/)
{
/*if (!*args)
return false;
uint64 guid = m_session->GetPlayer()->GetSelection();
if (guid == 0)
{
SendSysMessage(LANG_NO_SELECTION);
return true;
}
Creature *pCreature = ObjectAccessor::GetCreature(*m_session->GetPlayer(), guid);
if(!pCreature)
{
SendSysMessage(LANG_SELECT_CREATURE);
return true;
}
char* pSlotID = strtok((char*)args, " ");
if (!pSlotID)
return false;
char* pItemID = strtok(NULL, " ");
if (!pItemID)
return false;
uint32 ItemID = atoi(pItemID);
uint32 SlotID = atoi(pSlotID);
ItemPrototype* tmpItem = objmgr.GetItemPrototype(ItemID);
bool added = false;
if(tmpItem)
{
switch(SlotID)
{
case 1:
pCreature->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_DISPLAY, ItemID);
added = true;
break;
case 2:
pCreature->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_DISPLAY_01, ItemID);
added = true;
break;
case 3:
pCreature->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_DISPLAY_02, ItemID);
added = true;
break;
default:
PSendSysMessage(LANG_ITEM_SLOT_NOT_EXIST,SlotID);
added = false;
break;
}
if(added)
{
PSendSysMessage(LANG_ITEM_ADDED_TO_SLOT,ItemID,tmpItem->Name1,SlotID);
}
}
else
{
PSendSysMessage(LANG_ITEM_NOT_FOUND,ItemID);
return true;
}
*/
return true;
}
bool ChatHandler::HandleDieCommand(const char* /*args*/)
{
Unit* target = getSelectedUnit();
@ -3592,7 +3520,7 @@ bool ChatHandler::HandleLinkGraveCommand(const char* args)
return false;
}
if(objmgr.AddGraveYardLink(g_id,player->GetZoneId(),g_team))
if(objmgr.AddGraveYardLink(g_id,zoneId,g_team))
PSendSysMessage(LANG_COMMAND_GRAVEYARDLINKED, g_id,zoneId);
else
PSendSysMessage(LANG_COMMAND_GRAVEYARDALRLINKED, g_id,zoneId);
@ -3616,6 +3544,7 @@ bool ChatHandler::HandleNearGraveCommand(const char* args)
return false;
Player* player = m_session->GetPlayer();
uint32 zone_id = player->GetZoneId();
WorldSafeLocsEntry const* graveyard = objmgr.GetClosestGraveYard(
player->GetPositionX(), player->GetPositionY(), player->GetPositionZ(),player->GetMapId(),g_team);
@ -3624,7 +3553,7 @@ bool ChatHandler::HandleNearGraveCommand(const char* args)
{
uint32 g_id = graveyard->ID;
GraveYardData const* data = objmgr.FindGraveYardData(g_id,player->GetZoneId());
GraveYardData const* data = objmgr.FindGraveYardData(g_id,zone_id);
if (!data)
{
PSendSysMessage(LANG_COMMAND_GRAVEYARDERROR,g_id);
@ -3643,7 +3572,7 @@ bool ChatHandler::HandleNearGraveCommand(const char* args)
else if(g_team == ALLIANCE)
team_name = GetMangosString(LANG_COMMAND_GRAVEYARD_ALLIANCE);
PSendSysMessage(LANG_COMMAND_GRAVEYARDNEAREST, g_id,team_name.c_str(),player->GetZoneId());
PSendSysMessage(LANG_COMMAND_GRAVEYARDNEAREST, g_id,team_name.c_str(),zone_id);
}
else
{
@ -3657,29 +3586,36 @@ bool ChatHandler::HandleNearGraveCommand(const char* args)
team_name = GetMangosString(LANG_COMMAND_GRAVEYARD_ALLIANCE);
if(g_team == ~uint32(0))
PSendSysMessage(LANG_COMMAND_ZONENOGRAVEYARDS, player->GetZoneId());
PSendSysMessage(LANG_COMMAND_ZONENOGRAVEYARDS, zone_id);
else
PSendSysMessage(LANG_COMMAND_ZONENOGRAFACTION, player->GetZoneId(),team_name.c_str());
PSendSysMessage(LANG_COMMAND_ZONENOGRAFACTION, zone_id,team_name.c_str());
}
return true;
}
//play npc emote
bool ChatHandler::HandleNpcPlayEmoteCommand(const char* args)
//-----------------------Npc Commands-----------------------
bool ChatHandler::HandleNpcChangeEntryCommand(const char *args)
{
uint32 emote = atoi((char*)args);
if(!args)
return false;
Creature* target = getSelectedCreature();
if(!target)
uint32 newEntryNum = atoi(args);
if(!newEntryNum)
return false;
Unit* unit = getSelectedUnit();
if(!unit || unit->GetTypeId() != TYPEID_UNIT)
{
SendSysMessage(LANG_SELECT_CREATURE);
SetSentErrorMessage(true);
return false;
}
target->SetUInt32Value(UNIT_NPC_EMOTESTATE,emote);
Creature* creature = (Creature*)unit;
if(creature->UpdateEntry(newEntryNum))
SendSysMessage(LANG_DONE);
else
SendSysMessage(LANG_ERROR);
return true;
}
@ -3728,6 +3664,95 @@ bool ChatHandler::HandleNpcInfoCommand(const char* /*args*/)
return true;
}
//play npc emote
bool ChatHandler::HandleNpcPlayEmoteCommand(const char* args)
{
uint32 emote = atoi((char*)args);
Creature* target = getSelectedCreature();
if(!target)
{
SendSysMessage(LANG_SELECT_CREATURE);
SetSentErrorMessage(true);
return false;
}
target->SetUInt32Value(UNIT_NPC_EMOTESTATE,emote);
return true;
}
//TODO: NpcCommands that needs to be fixed :
bool ChatHandler::HandleNpcAddWeaponCommand(const char* /*args*/)
{
/*if (!*args)
return false;
uint64 guid = m_session->GetPlayer()->GetSelection();
if (guid == 0)
{
SendSysMessage(LANG_NO_SELECTION);
return true;
}
Creature *pCreature = ObjectAccessor::GetCreature(*m_session->GetPlayer(), guid);
if(!pCreature)
{
SendSysMessage(LANG_SELECT_CREATURE);
return true;
}
char* pSlotID = strtok((char*)args, " ");
if (!pSlotID)
return false;
char* pItemID = strtok(NULL, " ");
if (!pItemID)
return false;
uint32 ItemID = atoi(pItemID);
uint32 SlotID = atoi(pSlotID);
ItemPrototype* tmpItem = objmgr.GetItemPrototype(ItemID);
bool added = false;
if(tmpItem)
{
switch(SlotID)
{
case 1:
pCreature->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_DISPLAY, ItemID);
added = true;
break;
case 2:
pCreature->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_DISPLAY_01, ItemID);
added = true;
break;
case 3:
pCreature->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_DISPLAY_02, ItemID);
added = true;
break;
default:
PSendSysMessage(LANG_ITEM_SLOT_NOT_EXIST,SlotID);
added = false;
break;
}
if(added)
PSendSysMessage(LANG_ITEM_ADDED_TO_SLOT,ItemID,tmpItem->Name1,SlotID);
}
else
{
PSendSysMessage(LANG_ITEM_NOT_FOUND,ItemID);
return true;
}
*/
return true;
}
//----------------------------------------------------------
bool ChatHandler::HandleExploreCheatCommand(const char* args)
{
if (!*args)
@ -5686,30 +5711,6 @@ bool ChatHandler::HandleLoadPDumpCommand(const char *args)
return true;
}
bool ChatHandler::HandleNpcChangeEntryCommand(const char *args)
{
if(!args)
return false;
uint32 newEntryNum = atoi(args);
if(!newEntryNum)
return false;
Unit* unit = getSelectedUnit();
if(!unit || unit->GetTypeId() != TYPEID_UNIT)
{
SendSysMessage(LANG_SELECT_CREATURE);
SetSentErrorMessage(true);
return false;
}
Creature* creature = (Creature*)unit;
if(creature->UpdateEntry(newEntryNum))
SendSysMessage(LANG_DONE);
else
SendSysMessage(LANG_ERROR);
return true;
}
bool ChatHandler::HandleWritePDumpCommand(const char *args)
{
if(!args)

View file

@ -114,11 +114,18 @@ void LootStore::LoadLootTable()
float chanceOrQuestChance = fields[2].GetFloat();
uint8 group = fields[3].GetUInt8();
int32 mincountOrRef = fields[4].GetInt32();
uint8 maxcount = fields[5].GetUInt8();
uint32 maxcount = fields[5].GetUInt32();
ConditionType condition = (ConditionType)fields[6].GetUInt8();
uint32 cond_value1 = fields[7].GetUInt32();
uint32 cond_value2 = fields[8].GetUInt32();
if(maxcount > std::numeric_limits<uint8>::max())
{
sLog.outErrorDb("Table '%s' entry %d item %d: maxcount value (%u) to large. must be less %u - skipped", GetName(), entry, item, maxcount,std::numeric_limits<uint8>::max());
continue; // error already printed to log/console.
}
if(!PlayerCondition::IsValid(condition,cond_value1, cond_value2))
{
sLog.outErrorDb("... in table '%s' entry %u item %u", GetName(), entry, item);
@ -248,6 +255,12 @@ bool LootStoreItem::Roll(bool rate) const
// Checks correctness of values
bool LootStoreItem::IsValid(LootStore const& store, uint32 entry) const
{
if(group >= 1 << 7) // it stored in 7 bit field
{
sLog.outErrorDb("Table '%s' entry %d item %d: group (%u) must be less %u - skipped", store.GetName(), entry, itemid, group, 1 << 7);
return false;
}
if (mincountOrRef == 0)
{
sLog.outErrorDb("Table '%s' entry %d item %d: wrong mincountOrRef (%d) - skipped", store.GetName(), entry, itemid, mincountOrRef);

View file

@ -63,17 +63,17 @@ struct LootStoreItem
uint32 itemid; // id of the item
float chance; // always positive, chance to drop for both quest and non-quest items, chance to be used for refs
int32 mincountOrRef; // mincount for drop items (positive) or minus referenced TemplateleId (negative)
uint8 group :8;
uint8 group :7;
bool needs_quest :1; // quest drop (negative ChanceOrQuestChance in DB)
uint8 maxcount :8; // max drop count for the item (mincountOrRef positive) or Ref multiplicator (mincountOrRef negative)
uint16 conditionId :16; // additional loot condition Id
bool needs_quest :1; // quest drop (negative ChanceOrQuestChance in DB)
// Constructor, converting ChanceOrQuestChance -> (chance, needs_quest)
// displayid is filled in IsValid() which must be called after
LootStoreItem(uint32 _itemid, float _chanceOrQuestChance, int8 _group, uint8 _conditionId, int32 _mincountOrRef, uint8 _maxcount)
: itemid(_itemid), chance(fabs(_chanceOrQuestChance)), mincountOrRef(_mincountOrRef),
group(_group), maxcount(_maxcount), conditionId(_conditionId),
needs_quest(_chanceOrQuestChance < 0) {}
group(_group), needs_quest(_chanceOrQuestChance < 0), maxcount(_maxcount), conditionId(_conditionId)
{}
bool Roll(bool rate) const; // Checks if the entry takes it's chance (at loot generation)
bool IsValid(LootStore const& store, uint32 entry) const;

View file

@ -109,8 +109,8 @@ libmangosgame_a_SOURCES = \
FleeingMovementGenerator.cpp \
FleeingMovementGenerator.h \
Formulas.h \
GameEvent.cpp \
GameEvent.h \
GameEventMgr.cpp \
GameEventMgr.h \
GameObject.cpp \
GameObject.h \
GlobalEvents.cpp \

View file

@ -19,7 +19,6 @@
#include "MapManager.h"
#include "Player.h"
#include "GridNotifiers.h"
#include "WorldSession.h"
#include "Log.h"
#include "GridStates.h"
#include "CellImpl.h"
@ -42,9 +41,6 @@
#define DEFAULT_GRID_EXPIRY 300
#define MAX_GRID_LOAD_TIME 50
// magic *.map header
const char MAP_MAGIC[] = "MAP_3.00";
GridState* si_GridStates[MAX_GRID_STATE];
Map::~Map()
@ -67,9 +63,9 @@ bool Map::ExistMap(uint32 mapid,int x,int y)
return false;
}
char magic[8];
fread(magic,1,8,pf);
if(strncmp(MAP_MAGIC,magic,8))
map_fileheader header;
fread(&header, sizeof(header), 1, pf);
if (header.mapMagic != MAP_MAGIC || header.versionMagic != MAP_VERSION_MAGIC)
{
sLog.outError("Map file '%s' is non-compatible version (outdated?). Please, create new using ad.exe program.",tmp);
delete [] tmp;
@ -79,7 +75,6 @@ bool Map::ExistMap(uint32 mapid,int x,int y)
delete [] tmp;
fclose(pf);
return true;
}
@ -158,29 +153,13 @@ void Map::LoadMap(uint32 mapid, uint32 instanceid, int x,int y)
snprintf(tmp, len, (char *)(sWorld.GetDataPath()+"maps/%03u%02u%02u.map").c_str(),mapid,x,y);
sLog.outDetail("Loading map %s",tmp);
// loading data
FILE *pf=fopen(tmp,"rb");
if(!pf)
GridMaps[x][y] = new GridMap();
if (!GridMaps[x][y]->loadData(tmp))
{
delete [] tmp;
return;
sLog.outError("Error load map file: \n %s\n", tmp);
}
char magic[8];
fread(magic,1,8,pf);
if(strncmp(MAP_MAGIC,magic,8))
{
sLog.outError("Map file '%s' is non-compatible version (outdated?). Please, create new using ad.exe program.",tmp);
delete [] tmp;
fclose(pf); //close file before return
return;
}
delete [] tmp;
GridMap * buf= new GridMap;
fread(buf,1,sizeof(GridMap),pf);
fclose(pf);
GridMaps[x][y] = buf;
delete [] tmp;
return;
}
void Map::LoadMapAndVMap(uint32 mapid, uint32 instanceid, int x,int y)
@ -1032,7 +1011,11 @@ bool Map::UnloadGrid(const uint32 &x, const uint32 &y, bool pForce)
{
if (i_InstanceId == 0)
{
if(GridMaps[gx][gy]) delete (GridMaps[gx][gy]);
if(GridMaps[gx][gy])
{
GridMaps[gx][gy]->unloadData();
delete GridMaps[gx][gy];
}
// x and y are swapped
VMAP::VMapFactory::createOrGetVMapManager()->unloadMap(GetId(), gy, gx);
}
@ -1057,94 +1040,527 @@ void Map::UnloadAll(bool pForce)
}
}
float Map::GetHeight(float x, float y, float z, bool pUseVmaps) const
//*****************************
// Grid function
//*****************************
GridMap::GridMap()
{
GridPair p = MaNGOS::ComputeGridPair(x, y);
m_flags = 0;
// Area data
m_gridArea = 0;
m_area_map = NULL;
// Height level data
m_gridHeight = INVALID_HEIGHT;
m_gridGetHeight = &GridMap::getHeightFromFlat;
m_V9 = NULL;
m_V8 = NULL;
// Liquid data
m_liquidType = 0;
m_liquid_offX = 0;
m_liquid_offY = 0;
m_liquid_width = 0;
m_liquid_height = 0;
m_liquidLevel = INVALID_HEIGHT;
m_liquid_type = NULL;
m_liquid_map = NULL;
}
GridMap::~GridMap()
{
unloadData();
}
bool GridMap::loadData(char *filename)
{
// Unload old data if exist
unloadData();
map_fileheader header;
// Not return error if file not found
FILE *in = fopen(filename, "rb");
if (!in)
return true;
fread(&header, sizeof(header),1,in);
if (header.mapMagic == MAP_MAGIC && header.versionMagic == MAP_VERSION_MAGIC)
{
// loadup area data
if (header.areaMapOffset && !loadAreaData(in, header.areaMapOffset, header.areaMapSize))
{
sLog.outError("Error loading map area data\n");
fclose(in);
return false;
}
// loadup height data
if (header.heightMapOffset && !loadHeihgtData(in, header.heightMapOffset, header.heightMapSize))
{
sLog.outError("Error loading map height data\n");
fclose(in);
return false;
}
// loadup liquid data
if (header.liquidMapOffset && !loadLiquidData(in, header.liquidMapOffset, header.liquidMapSize))
{
sLog.outError("Error loading map liquids data\n");
fclose(in);
return false;
}
fclose(in);
return true;
}
sLog.outError("Map file '%s' is non-compatible version (outdated?). Please, create new using ad.exe program.", filename);
fclose(in);
return false;
}
void GridMap::unloadData()
{
if (m_area_map) delete[] m_area_map;
if (m_V9) delete[] m_V9;
if (m_V8) delete[] m_V8;
if (m_liquid_type) delete[] m_liquid_type;
if (m_liquid_map) delete[] m_liquid_map;
m_area_map = NULL;
m_V9 = NULL;
m_V8 = NULL;
m_liquid_type = NULL;
m_liquid_map = NULL;
m_gridGetHeight = &GridMap::getHeightFromFlat;
}
bool GridMap::loadAreaData(FILE *in, uint32 offset, uint32 size)
{
map_areaHeader header;
fseek(in, offset, SEEK_SET);
fread(&header, sizeof(header), 1, in);
if (header.fourcc != MAP_AREA_MAGIC)
return false;
m_gridArea = header.gridArea;
if (!(header.flags&MAP_AREA_NO_AREA))
{
m_area_map = new uint16 [16*16];
fread(m_area_map, sizeof(uint16), 16*16, in);
}
return true;
}
bool GridMap::loadHeihgtData(FILE *in, uint32 offset, uint32 size)
{
map_heightHeader header;
fseek(in, offset, SEEK_SET);
fread(&header, sizeof(header), 1, in);
if (header.fourcc != MAP_HEIGTH_MAGIC)
return false;
m_gridHeight = header.gridHeight;
if (!(header.flags&MAP_HEIGHT_NO_HIGHT))
{
if ((header.flags&MAP_HEIGHT_AS_INT16))
{
m_uint16_V9 = new uint16 [129*129];
m_uint16_V8 = new uint16 [128*128];
fread(m_uint16_V9, sizeof(uint16), 129*129, in);
fread(m_uint16_V8, sizeof(uint16), 128*128, in);
m_gridIntHeightMultiplier = (header.gridMaxHeight - header.gridHeight) / 65535;
m_gridGetHeight = &GridMap::getHeightFromUint16;
}
else if ((header.flags&MAP_HEIGHT_AS_INT8))
{
m_uint8_V9 = new uint8 [129*129];
m_uint8_V8 = new uint8 [128*128];
fread(m_uint8_V9, sizeof(uint8), 129*129, in);
fread(m_uint8_V8, sizeof(uint8), 128*128, in);
m_gridIntHeightMultiplier = (header.gridMaxHeight - header.gridHeight) / 255;
m_gridGetHeight = &GridMap::getHeightFromUint8;
}
else
{
m_V9 = new float [129*129];
m_V8 = new float [128*128];
fread(m_V9, sizeof(float), 129*129, in);
fread(m_V8, sizeof(float), 128*128, in);
m_gridGetHeight = &GridMap::getHeightFromFloat;
}
}
else
m_gridGetHeight = &GridMap::getHeightFromFlat;
return true;
}
bool GridMap::loadLiquidData(FILE *in, uint32 offset, uint32 size)
{
map_liquidHeader header;
fseek(in, offset, SEEK_SET);
fread(&header, sizeof(header), 1, in);
if (header.fourcc != MAP_LIQUID_MAGIC)
return false;
m_liquidType = header.liquidType;
m_liquid_offX = header.offsetX;
m_liquid_offY = header.offsetY;
m_liquid_width = header.width;
m_liquid_height= header.height;
m_liquidLevel = header.liquidLevel;
if (!(header.flags&MAP_LIQUID_NO_TYPE))
{
m_liquid_type = new uint8 [16*16];
fread(m_liquid_type, sizeof(uint8), 16*16, in);
}
if (!(header.flags&MAP_LIQUID_NO_HIGHT))
{
m_liquid_map = new float [m_liquid_width*m_liquid_height];
fread(m_liquid_map, sizeof(float), m_liquid_width*m_liquid_height, in);
}
return true;
}
uint16 GridMap::getArea(float x, float y)
{
if (!m_area_map)
return m_gridArea;
x = 16 * (32 - x/SIZE_OF_GRIDS);
y = 16 * (32 - y/SIZE_OF_GRIDS);
int lx = (int)x & 15;
int ly = (int)y & 15;
return m_area_map[lx*16 + ly];
}
float GridMap::getHeightFromFlat(float x, float y) const
{
return m_gridHeight;
}
float GridMap::getHeightFromFloat(float x, float y) const
{
if (!m_V8 || !m_V9)
return m_gridHeight;
x = MAP_RESOLUTION * (32 - x/SIZE_OF_GRIDS);
y = MAP_RESOLUTION * (32 - y/SIZE_OF_GRIDS);
int x_int = (int)x;
int y_int = (int)y;
x -= x_int;
y -= y_int;
x_int&=(MAP_RESOLUTION - 1);
y_int&=(MAP_RESOLUTION - 1);
// Height stored as: h5 - its v8 grid, h1-h4 - its v9 grid
// +--------------> X
// | h1-------h2 Coordinates is:
// | | \ 1 / | h1 0,0
// | | \ / | h2 0,1
// | | 2 h5 3 | h3 1,0
// | | / \ | h4 1,1
// | | / 4 \ | h5 1/2,1/2
// | h3-------h4
// V Y
// For find height need
// 1 - detect triangle
// 2 - solve linear equation from triangle points
// Calculate coefficients for solve h = a*x + b*y + c
float a,b,c;
// Select triangle:
if (x+y < 1)
{
if (x > y)
{
// 1 triangle (h1, h2, h5 points)
float h1 = m_V9[(x_int )*129 + y_int];
float h2 = m_V9[(x_int+1)*129 + y_int];
float h5 = 2 * m_V8[x_int*128 + y_int];
a = h2-h1;
b = h5-h1-h2;
c = h1;
}
else
{
// 2 triangle (h1, h3, h5 points)
float h1 = m_V9[x_int*129 + y_int ];
float h3 = m_V9[x_int*129 + y_int+1];
float h5 = 2 * m_V8[x_int*128 + y_int];
a = h5 - h1 - h3;
b = h3 - h1;
c = h1;
}
}
else
{
if (x > y)
{
// 3 triangle (h2, h4, h5 points)
float h2 = m_V9[(x_int+1)*129 + y_int ];
float h4 = m_V9[(x_int+1)*129 + y_int+1];
float h5 = 2 * m_V8[x_int*128 + y_int];
a = h2 + h4 - h5;
b = h4 - h2;
c = h5 - h4;
}
else
{
// 4 triangle (h3, h4, h5 points)
float h3 = m_V9[(x_int )*129 + y_int+1];
float h4 = m_V9[(x_int+1)*129 + y_int+1];
float h5 = 2 * m_V8[x_int*128 + y_int];
a = h4 - h3;
b = h3 + h4 - h5;
c = h5 - h4;
}
}
// Calculate height
return a * x + b * y + c;
}
float GridMap::getHeightFromUint8(float x, float y) const
{
if (!m_uint8_V8 || !m_uint8_V9)
return m_gridHeight;
x = MAP_RESOLUTION * (32 - x/SIZE_OF_GRIDS);
y = MAP_RESOLUTION * (32 - y/SIZE_OF_GRIDS);
int x_int = (int)x;
int y_int = (int)y;
x -= x_int;
y -= y_int;
x_int&=(MAP_RESOLUTION - 1);
y_int&=(MAP_RESOLUTION - 1);
int32 a, b, c;
uint8 *V9_h1_ptr = &m_uint8_V9[x_int*128 + x_int + y_int];
if (x+y < 1)
{
if (x > y)
{
// 1 triangle (h1, h2, h5 points)
int32 h1 = V9_h1_ptr[ 0];
int32 h2 = V9_h1_ptr[129];
int32 h5 = 2 * m_uint8_V8[x_int*128 + y_int];
a = h2-h1;
b = h5-h1-h2;
c = h1;
}
else
{
// 2 triangle (h1, h3, h5 points)
int32 h1 = V9_h1_ptr[0];
int32 h3 = V9_h1_ptr[1];
int32 h5 = 2 * m_uint8_V8[x_int*128 + y_int];
a = h5 - h1 - h3;
b = h3 - h1;
c = h1;
}
}
else
{
if (x > y)
{
// 3 triangle (h2, h4, h5 points)
int32 h2 = V9_h1_ptr[129];
int32 h4 = V9_h1_ptr[130];
int32 h5 = 2 * m_uint8_V8[x_int*128 + y_int];
a = h2 + h4 - h5;
b = h4 - h2;
c = h5 - h4;
}
else
{
// 4 triangle (h3, h4, h5 points)
int32 h3 = V9_h1_ptr[ 1];
int32 h4 = V9_h1_ptr[130];
int32 h5 = 2 * m_uint8_V8[x_int*128 + y_int];
a = h4 - h3;
b = h3 + h4 - h5;
c = h5 - h4;
}
}
// Calculate height
return (float)((a * x) + (b * y) + c)*m_gridIntHeightMultiplier + m_gridHeight;
}
float GridMap::getHeightFromUint16(float x, float y) const
{
if (!m_uint16_V8 || !m_uint16_V9)
return m_gridHeight;
x = MAP_RESOLUTION * (32 - x/SIZE_OF_GRIDS);
y = MAP_RESOLUTION * (32 - y/SIZE_OF_GRIDS);
int x_int = (int)x;
int y_int = (int)y;
x -= x_int;
y -= y_int;
x_int&=(MAP_RESOLUTION - 1);
y_int&=(MAP_RESOLUTION - 1);
int32 a, b, c;
uint16 *V9_h1_ptr = &m_uint16_V9[x_int*128 + x_int + y_int];
if (x+y < 1)
{
if (x > y)
{
// 1 triangle (h1, h2, h5 points)
int32 h1 = V9_h1_ptr[ 0];
int32 h2 = V9_h1_ptr[129];
int32 h5 = 2 * m_uint16_V8[x_int*128 + y_int];
a = h2-h1;
b = h5-h1-h2;
c = h1;
}
else
{
// 2 triangle (h1, h3, h5 points)
int32 h1 = V9_h1_ptr[0];
int32 h3 = V9_h1_ptr[1];
int32 h5 = 2 * m_uint16_V8[x_int*128 + y_int];
a = h5 - h1 - h3;
b = h3 - h1;
c = h1;
}
}
else
{
if (x > y)
{
// 3 triangle (h2, h4, h5 points)
int32 h2 = V9_h1_ptr[129];
int32 h4 = V9_h1_ptr[130];
int32 h5 = 2 * m_uint16_V8[x_int*128 + y_int];
a = h2 + h4 - h5;
b = h4 - h2;
c = h5 - h4;
}
else
{
// 4 triangle (h3, h4, h5 points)
int32 h3 = V9_h1_ptr[ 1];
int32 h4 = V9_h1_ptr[130];
int32 h5 = 2 * m_uint16_V8[x_int*128 + y_int];
a = h4 - h3;
b = h3 + h4 - h5;
c = h5 - h4;
}
}
// Calculate height
return (float)((a * x) + (b * y) + c)*m_gridIntHeightMultiplier + m_gridHeight;
}
float GridMap::getLiquidLevel(float x, float y)
{
if (!m_liquid_map)
return m_liquidLevel;
x = MAP_RESOLUTION * (32 - x/SIZE_OF_GRIDS);
y = MAP_RESOLUTION * (32 - y/SIZE_OF_GRIDS);
int cx_int = ((int)x & (MAP_RESOLUTION-1)) - m_liquid_offY;
int cy_int = ((int)y & (MAP_RESOLUTION-1)) - m_liquid_offX;
if (cx_int < 0 || cx_int >=m_liquid_height)
return INVALID_HEIGHT;
if (cy_int < 0 || cy_int >=m_liquid_width )
return INVALID_HEIGHT;
return m_liquid_map[cx_int*m_liquid_width + cy_int];
}
uint8 GridMap::getTerrainType(float x, float y)
{
if (!m_liquid_type)
return m_liquidType;
x = 16 * (32 - x/SIZE_OF_GRIDS);
y = 16 * (32 - y/SIZE_OF_GRIDS);
int lx = (int)x & 15;
int ly = (int)y & 15;
return m_liquid_type[lx*16 + ly];
}
// Get water state on map
inline ZLiquidStatus GridMap::getLiquidStatus(float x, float y, float z, uint8 ReqLiquidType, LiquidData *data)
{
// Check water type (if no water return)
if (!m_liquid_type && !m_liquidType)
return LIQUID_MAP_NO_WATER;
// Get cell
float cx = MAP_RESOLUTION * (32 - x/SIZE_OF_GRIDS);
float cy = MAP_RESOLUTION * (32 - y/SIZE_OF_GRIDS);
int x_int = (int)cx & (MAP_RESOLUTION-1);
int y_int = (int)cy & (MAP_RESOLUTION-1);
// Check water type in cell
uint8 type = m_liquid_type ? m_liquid_type[(x_int>>3)*16 + (y_int>>3)] : m_liquidType;
if (type == 0)
return LIQUID_MAP_NO_WATER;
// Check req liquid type mask
if (ReqLiquidType && !(ReqLiquidType&type))
return LIQUID_MAP_NO_WATER;
// Check water level:
// Check water height map
int lx_int = x_int - m_liquid_offY;
int ly_int = y_int - m_liquid_offX;
if (lx_int < 0 || lx_int >=m_liquid_height)
return LIQUID_MAP_NO_WATER;
if (ly_int < 0 || ly_int >=m_liquid_width )
return LIQUID_MAP_NO_WATER;
// Get water level
float liquid_level = m_liquid_map ? m_liquid_map[lx_int*m_liquid_width + ly_int] : m_liquidLevel;
// Get ground level (sub 0.2 for fix some errors)
float ground_level = getHeight(x, y);
// Check water level and ground level
if (liquid_level < ground_level || z < ground_level - 2)
return LIQUID_MAP_NO_WATER;
// All ok in water -> store data
if (data)
{
data->type = type;
data->level = liquid_level;
data->depth_level = ground_level;
}
// For speed check as int values
int delta = (liquid_level - z) * 10;
// Get position delta
if (delta > 20) // Under water
return LIQUID_MAP_UNDER_WATER;
if (delta > 0 ) // In water
return LIQUID_MAP_IN_WATER;
if (delta > -1) // Walk on water
return LIQUID_MAP_WATER_WALK;
// Above water
return LIQUID_MAP_ABOVE_WATER;
}
inline GridMap *Map::GetGrid(float x, float y)
{
// half opt method
int gx=(int)(32-x/SIZE_OF_GRIDS); //grid x
int gy=(int)(32-y/SIZE_OF_GRIDS); //grid y
float lx=MAP_RESOLUTION*(32 -x/SIZE_OF_GRIDS - gx);
float ly=MAP_RESOLUTION*(32 -y/SIZE_OF_GRIDS - gy);
// ensure GridMap is loaded
const_cast<Map*>(this)->EnsureGridCreated(GridPair(63-gx,63-gy));
EnsureGridCreated(GridPair(63-gx,63-gy));
return GridMaps[gx][gy];
}
float Map::GetHeight(float x, float y, float z, bool pUseVmaps) const
{
// find raw .map surface under Z coordinates
float mapHeight;
if(GridMap* gmap = GridMaps[gx][gy])
if(GridMap *gmap = const_cast<Map*>(this)->GetGrid(x, y))
{
int lx_int = (int)lx;
int ly_int = (int)ly;
lx -= lx_int;
ly -= ly_int;
// Height stored as: h5 - its v8 grid, h1-h4 - its v9 grid
// +--------------> X
// | h1-------h2 Coordinates is:
// | | \ 1 / | h1 0,0
// | | \ / | h2 0,1
// | | 2 h5 3 | h3 1,0
// | | / \ | h4 1,1
// | | / 4 \ | h5 1/2,1/2
// | h3-------h4
// V Y
// For find height need
// 1 - detect triangle
// 2 - solve linear equation from triangle points
// Calculate coefficients for solve h = a*x + b*y + c
float a,b,c;
// Select triangle:
if (lx+ly < 1)
{
if (lx > ly)
{
// 1 triangle (h1, h2, h5 points)
float h1 = gmap->v9[lx_int][ly_int];
float h2 = gmap->v9[lx_int+1][ly_int];
float h5 = 2 * gmap->v8[lx_int][ly_int];
a = h2-h1;
b = h5-h1-h2;
c = h1;
}
else
{
// 2 triangle (h1, h3, h5 points)
float h1 = gmap->v9[lx_int][ly_int];
float h3 = gmap->v9[lx_int][ly_int+1];
float h5 = 2 * gmap->v8[lx_int][ly_int];
a = h5 - h1 - h3;
b = h3 - h1;
c = h1;
}
}
else
{
if (lx > ly)
{
// 3 triangle (h2, h4, h5 points)
float h2 = gmap->v9[lx_int+1][ly_int];
float h4 = gmap->v9[lx_int+1][ly_int+1];
float h5 = 2 * gmap->v8[lx_int][ly_int];
a = h2 + h4 - h5;
b = h4 - h2;
c = h5 - h4;
}
else
{
// 4 triangle (h3, h4, h5 points)
float h3 = gmap->v9[lx_int][ly_int+1];
float h4 = gmap->v9[lx_int+1][ly_int+1];
float h5 = 2 * gmap->v8[lx_int][ly_int];
a = h4 - h3;
b = h3 + h4 - h5;
c = h5 - h4;
}
}
// Calculate height
float _mapheight = a * lx + b * ly + c;
float _mapheight = gmap->getHeight(x,y);
// look from a bit higher pos to find the floor, ignore under surface case
if(z + 2.0f > _mapheight)
@ -1203,25 +1619,9 @@ float Map::GetHeight(float x, float y, float z, bool pUseVmaps) const
uint16 Map::GetAreaFlag(float x, float y, float z) const
{
//local x,y coords
float lx,ly;
int gx,gy;
GridPair p = MaNGOS::ComputeGridPair(x, y);
// half opt method
gx=(int)(32-x/SIZE_OF_GRIDS) ; //grid x
gy=(int)(32-y/SIZE_OF_GRIDS); //grid y
lx=16*(32 -x/SIZE_OF_GRIDS - gx);
ly=16*(32 -y/SIZE_OF_GRIDS - gy);
//DEBUG_LOG("my %d %d si %d %d",gx,gy,p.x_coord,p.y_coord);
// ensure GridMap is loaded
const_cast<Map*>(this)->EnsureGridCreated(GridPair(63-gx,63-gy));
uint16 areaflag;
if(GridMaps[gx][gy])
areaflag = GridMaps[gx][gy]->area_flag[(int)(lx)][(int)(ly)];
if(GridMap *gmap = const_cast<Map*>(this)->GetGrid(x, y))
areaflag = gmap->getArea(x, y);
// this used while not all *.map files generated (instances)
else
areaflag = GetAreaFlagByMapId(i_id);
@ -1240,6 +1640,11 @@ uint16 Map::GetAreaFlag(float x, float y, float z) const
case 856: // The Noxious Glade (Eastern Plaguelands)
case 2456: // Death's Breach (Eastern Plaguelands)
if(z > 350.0f) areaflag = 1950; break;
// Dalaran
case 1593:
case 2484:
case 2492:
if( (x < 6116 && x > 5568) && (y < 982 && y > 282) && z > 563.0f) areaflag = 2153; break;
}
return areaflag;
@ -1247,49 +1652,29 @@ uint16 Map::GetAreaFlag(float x, float y, float z) const
uint8 Map::GetTerrainType(float x, float y ) const
{
//local x,y coords
float lx,ly;
int gx,gy;
// half opt method
gx=(int)(32-x/SIZE_OF_GRIDS) ; //grid x
gy=(int)(32-y/SIZE_OF_GRIDS); //grid y
lx=16*(32 -x/SIZE_OF_GRIDS - gx);
ly=16*(32 -y/SIZE_OF_GRIDS - gy);
// ensure GridMap is loaded
const_cast<Map*>(this)->EnsureGridCreated(GridPair(63-gx,63-gy));
if(GridMaps[gx][gy])
return GridMaps[gx][gy]->terrain_type[(int)(lx)][(int)(ly)];
if(GridMap *gmap = const_cast<Map*>(this)->GetGrid(x, y))
return gmap->getTerrainType(x, y);
else
return 0;
}
ZLiquidStatus Map::getLiquidStatus(float x, float y, float z, uint8 ReqLiquidType, LiquidData *data) const
{
if(GridMap* gmap = const_cast<Map*>(this)->GetGrid(x, y))
return gmap->getLiquidStatus(x, y, z, ReqLiquidType, data);
else
return LIQUID_MAP_NO_WATER;
}
float Map::GetWaterLevel(float x, float y ) const
{
//local x,y coords
float lx,ly;
int gx,gy;
// half opt method
gx=(int)(32-x/SIZE_OF_GRIDS) ; //grid x
gy=(int)(32-y/SIZE_OF_GRIDS); //grid y
lx=128*(32 -x/SIZE_OF_GRIDS - gx);
ly=128*(32 -y/SIZE_OF_GRIDS - gy);
// ensure GridMap is loaded
const_cast<Map*>(this)->EnsureGridCreated(GridPair(63-gx,63-gy));
if(GridMaps[gx][gy])
return GridMaps[gx][gy]->liquid_level[(int)(lx)][(int)(ly)];
if(GridMap* gmap = const_cast<Map*>(this)->GetGrid(x, y))
return gmap->getLiquidLevel(x, y);
else
return 0;
}
uint32 Map::GetAreaId(uint16 areaflag,uint32 map_id)
uint32 Map::GetAreaIdByAreaFlag(uint16 areaflag,uint32 map_id)
{
AreaTableEntry const *entry = GetAreaEntryByAreaFlagAndMap(areaflag,map_id);
@ -1299,7 +1684,7 @@ uint32 Map::GetAreaId(uint16 areaflag,uint32 map_id)
return 0;
}
uint32 Map::GetZoneId(uint16 areaflag,uint32 map_id)
uint32 Map::GetZoneIdByAreaFlag(uint16 areaflag,uint32 map_id)
{
AreaTableEntry const *entry = GetAreaEntryByAreaFlagAndMap(areaflag,map_id);
@ -1309,26 +1694,37 @@ uint32 Map::GetZoneId(uint16 areaflag,uint32 map_id)
return 0;
}
void Map::GetZoneAndAreaIdByAreaFlag(uint32& zoneid, uint32& areaid, uint16 areaflag,uint32 map_id)
{
AreaTableEntry const *entry = GetAreaEntryByAreaFlagAndMap(areaflag,map_id);
areaid = entry ? entry->ID : 0;
zoneid = entry ? (( entry->zone != 0 ) ? entry->zone : entry->ID) : 0;
}
bool Map::IsInWater(float x, float y, float pZ) const
{
// This method is called too often to use vamps for that (4. parameter = false).
// The pZ pos is taken anyway for future use
float z = GetHeight(x,y,pZ,false); // use .map base surface height
// underground or instance without vmap
if(z <= INVALID_HEIGHT)
return false;
float water_z = GetWaterLevel(x,y);
uint8 flag = GetTerrainType(x,y);
return (z < (water_z-2)) && (flag & 0x01);
// Check surface in x, y point for liquid
if (GridMap* gmap = const_cast<Map*>(this)->GetGrid(x, y))
{
LiquidData liquid_status;
if (getLiquidStatus(x, y, pZ, MAP_ALL_LIQUIDS, &liquid_status))
{
if (liquid_status.level - liquid_status.depth_level > 2)
return true;
}
}
return false;
}
bool Map::IsUnderWater(float x, float y, float z) const
{
float water_z = GetWaterLevel(x,y);
uint8 flag = GetTerrainType(x,y);
return (z < (water_z-2)) && (flag & 0x01);
if (GridMap* gmap = const_cast<Map*>(this)->GetGrid(x, y))
{
if (getLiquidStatus(x, y, z, MAP_LIQUID_TYPE_WATER|MAP_LIQUID_TYPE_OCEAN)&LIQUID_MAP_UNDER_WATER)
return true;
}
return false;
}
bool Map::CheckGridIntegrity(Creature* c, bool moved) const
@ -1817,7 +2213,6 @@ bool InstanceMap::Add(Player *player)
// first player enters (no players yet)
SetResetSchedule(false);
player->SendInitWorldStates();
sLog.outDetail("MAP: Player '%s' entered the instance '%u' of map '%s'", player->GetName(), GetInstanceId(), GetMapName());
// initialize unload state
m_unloadTimer = 0;
@ -1933,7 +2328,7 @@ void InstanceMap::PermBindAllPlayers(Player *player)
InstanceSave *save = sInstanceSaveManager.GetInstanceSave(GetInstanceId());
if(!save)
{
sLog.outError("Cannot bind players, no instance save available for map!\n");
sLog.outError("Cannot bind players, no instance save available for map!");
return;
}

View file

@ -68,14 +68,135 @@ typedef RGuard<GridRWLock, ZThread::Lockable> GridReadGuard;
typedef WGuard<GridRWLock, ZThread::Lockable> GridWriteGuard;
typedef MaNGOS::SingleThreaded<GridRWLock>::Lock NullGuard;
typedef struct
//******************************************
// Map file format defines
//******************************************
#define MAP_MAGIC 'SPAM'
#define MAP_VERSION_MAGIC '0.1w'
#define MAP_AREA_MAGIC 'AERA'
#define MAP_HEIGTH_MAGIC 'TGHM'
#define MAP_LIQUID_MAGIC 'QILM'
struct map_fileheader{
uint32 mapMagic;
uint32 versionMagic;
uint32 areaMapOffset;
uint32 areaMapSize;
uint32 heightMapOffset;
uint32 heightMapSize;
uint32 liquidMapOffset;
uint32 liquidMapSize;
};
#define MAP_AREA_NO_AREA 0x0001
struct map_areaHeader{
uint32 fourcc;
uint16 flags;
uint16 gridArea;
};
#define MAP_HEIGHT_NO_HIGHT 0x0001
#define MAP_HEIGHT_AS_INT16 0x0002
#define MAP_HEIGHT_AS_INT8 0x0004
struct map_heightHeader{
uint32 fourcc;
uint32 flags;
float gridHeight;
float gridMaxHeight;
};
#define MAP_LIQUID_NO_TYPE 0x0001
#define MAP_LIQUID_NO_HIGHT 0x0002
struct map_liquidHeader{
uint32 fourcc;
uint16 flags;
uint16 liquidType;
uint8 offsetX;
uint8 offsetY;
uint8 width;
uint8 height;
float liquidLevel;
};
enum ZLiquidStatus{
LIQUID_MAP_NO_WATER = 0x00000000,
LIQUID_MAP_ABOVE_WATER = 0x00000001,
LIQUID_MAP_WATER_WALK = 0x00000002,
LIQUID_MAP_IN_WATER = 0x00000004,
LIQUID_MAP_UNDER_WATER = 0x00000008
};
#define MAP_LIQUID_TYPE_NO_WATER 0x00
#define MAP_LIQUID_TYPE_WATER 0x01
#define MAP_LIQUID_TYPE_OCEAN 0x02
#define MAP_LIQUID_TYPE_MAGMA 0x04
#define MAP_LIQUID_TYPE_SLIME 0x08
#define MAP_ALL_LIQUIDS (MAP_LIQUID_TYPE_WATER | MAP_LIQUID_TYPE_OCEAN | MAP_LIQUID_TYPE_MAGMA | MAP_LIQUID_TYPE_SLIME)
#define MAP_LIQUID_TYPE_DARK_WATER 0x10
#define MAP_LIQUID_TYPE_WMO_WATER 0x20
struct LiquidData{
uint32 type;
float level;
float depth_level;
};
class GridMap
{
uint16 area_flag[16][16];
uint8 terrain_type[16][16];
float liquid_level[128][128];
float v9[MAP_RESOLUTION + 1][MAP_RESOLUTION + 1];
float v8[MAP_RESOLUTION][MAP_RESOLUTION];
}GridMap;
uint32 m_flags;
// Area data
uint16 m_gridArea;
uint16 *m_area_map;
// Height level data
float m_gridHeight;
float m_gridIntHeightMultiplier;
union{
float *m_V9;
uint16 *m_uint16_V9;
uint8 *m_uint8_V9;
};
union{
float *m_V8;
uint16 *m_uint16_V8;
uint8 *m_uint8_V8;
};
// Liquid data
uint16 m_liquidType;
uint8 m_liquid_offX;
uint8 m_liquid_offY;
uint8 m_liquid_width;
uint8 m_liquid_height;
float m_liquidLevel;
uint8 *m_liquid_type;
float *m_liquid_map;
bool loadAreaData(FILE *in, uint32 offset, uint32 size);
bool loadHeihgtData(FILE *in, uint32 offset, uint32 size);
bool loadLiquidData(FILE *in, uint32 offset, uint32 size);
// Get height functions and pointers
typedef float (GridMap::*pGetHeightPtr) (float x, float y) const;
pGetHeightPtr m_gridGetHeight;
float getHeightFromFloat(float x, float y) const;
float getHeightFromUint16(float x, float y) const;
float getHeightFromUint8(float x, float y) const;
float getHeightFromFlat(float x, float y) const;
public:
GridMap();
~GridMap();
bool loadData(char *filaname);
void unloadData();
uint16 getArea(float x, float y);
inline float getHeight(float x, float y) {return (this->*m_gridGetHeight)(x, y);}
float getLiquidLevel(float x, float y);
uint8 getTerrainType(float x, float y);
ZLiquidStatus getLiquidStatus(float x, float y, float z, uint8 ReqLiquidType, LiquidData *data = 0);
};
struct CreatureMover
{
@ -190,22 +311,30 @@ class MANGOS_DLL_SPEC Map : public GridRefManager<NGridType>, public MaNGOS::Obj
float GetHeight(float x, float y, float z, bool pCheckVMap=true) const;
bool IsInWater(float x, float y, float z) const; // does not use z pos. This is for future use
ZLiquidStatus getLiquidStatus(float x, float y, float z, uint8 ReqLiquidType, LiquidData *data = 0) const;
uint16 GetAreaFlag(float x, float y, float z) const;
uint8 GetTerrainType(float x, float y ) const;
float GetWaterLevel(float x, float y ) const;
bool IsUnderWater(float x, float y, float z) const;
static uint32 GetAreaId(uint16 areaflag,uint32 map_id);
static uint32 GetZoneId(uint16 areaflag,uint32 map_id);
static uint32 GetAreaIdByAreaFlag(uint16 areaflag,uint32 map_id);
static uint32 GetZoneIdByAreaFlag(uint16 areaflag,uint32 map_id);
static void GetZoneAndAreaIdByAreaFlag(uint32& zoneid, uint32& areaid, uint16 areaflag,uint32 map_id);
uint32 GetAreaId(float x, float y, float z) const
{
return GetAreaId(GetAreaFlag(x,y,z),i_id);
return GetAreaIdByAreaFlag(GetAreaFlag(x,y,z),i_id);
}
uint32 GetZoneId(float x, float y, float z) const
{
return GetZoneId(GetAreaFlag(x,y,z),i_id);
return GetZoneIdByAreaFlag(GetAreaFlag(x,y,z),i_id);
}
void GetZoneAndAreaId(uint32& zoneid, uint32& areaid, float x, float y, float z) const
{
GetZoneAndAreaIdByAreaFlag(zoneid,areaid,GetAreaFlag(x,y,z),i_id);
}
virtual void MoveAllCreaturesInMoveList();
@ -277,6 +406,7 @@ class MANGOS_DLL_SPEC Map : public GridRefManager<NGridType>, public MaNGOS::Obj
private:
void LoadVMap(int pX, int pY);
void LoadMap(uint32 mapid, uint32 instanceid, int x,int y);
GridMap *GetGrid(float x, float y);
void SetTimer(uint32 t) { i_gridExpiry = t < MIN_GRID_DELAY ? MIN_GRID_DELAY : t; }
//uint64 CalculateGridMask(const uint32 &y) const;

View file

@ -50,8 +50,18 @@ class MANGOS_DLL_DECL MapManager : public MaNGOS::Singleton<MapManager, MaNGOS::
Map const* m = GetBaseMap(mapid);
return m->GetAreaFlag(x, y, z);
}
uint32 GetAreaId(uint32 mapid, float x, float y, float z) const { return Map::GetAreaId(GetAreaFlag(mapid, x, y, z),mapid); }
uint32 GetZoneId(uint32 mapid, float x, float y, float z) const { return Map::GetZoneId(GetAreaFlag(mapid, x, y, z),mapid); }
uint32 GetAreaId(uint32 mapid, float x, float y, float z) const
{
return Map::GetAreaIdByAreaFlag(GetAreaFlag(mapid, x, y, z),mapid);
}
uint32 GetZoneId(uint32 mapid, float x, float y, float z) const
{
return Map::GetZoneIdByAreaFlag(GetAreaFlag(mapid, x, y, z),mapid);
}
void GetZoneAndAreaId(uint32& zoneid, uint32& areaid, uint32 mapid, float x, float y, float z)
{
Map::GetZoneAndAreaIdByAreaFlag(zoneid,areaid,GetAreaFlag(mapid, x, y, z),mapid);
}
void Initialize(void);
void Update(uint32);

View file

@ -34,11 +34,9 @@
#include "Chat.h"
#include "ScriptCalls.h"
#include <zlib/zlib.h>
#include "MapManager.h"
#include "ObjectAccessor.h"
#include "Object.h"
#include "BattleGround.h"
#include "SpellAuras.h"
#include "Pet.h"
#include "SocialMgr.h"
@ -386,10 +384,10 @@ void WorldSession::HandleZoneUpdateOpcode( WorldPacket & recv_data )
sLog.outDetail("WORLD: Recvd ZONE_UPDATE: %u", newZone);
if(newZone != _player->GetZoneId())
GetPlayer()->SendInitWorldStates(); // only if really enters to new zone, not just area change, works strange...
GetPlayer()->UpdateZone(newZone);
// use server size data
uint32 newzone, newarea;
GetPlayer()->GetZoneAndAreaId(newzone,newarea);
GetPlayer()->UpdateZone(newzone,newarea);
}
void WorldSession::HandleSetTargetOpcode( WorldPacket & recv_data )
@ -859,8 +857,16 @@ void WorldSession::HandleAreaTriggerOpcode(WorldPacket & recv_data)
}
uint32 missingQuest = 0;
if(at->requiredQuest && !GetPlayer()->GetQuestRewardStatus(at->requiredQuest))
missingQuest = at->requiredQuest;
if(GetPlayer()->GetDifficulty() == DIFFICULTY_HEROIC)
{
if (at->requiredQuestHeroic && !GetPlayer()->GetQuestRewardStatus(at->requiredQuestHeroic))
missingQuest = at->requiredQuestHeroic;
}
else
{
if(at->requiredQuest && !GetPlayer()->GetQuestRewardStatus(at->requiredQuest))
missingQuest = at->requiredQuest;
}
if(missingLevel || missingItem || missingKey || missingQuest)
{

View file

@ -21,9 +21,9 @@
#include "WorldSession.h"
#include "Opcodes.h"
#include "Log.h"
#include "World.h"
#include "Corpse.h"
#include "Player.h"
#include "Vehicle.h"
#include "MapManager.h"
#include "Transports.h"
#include "BattleGround.h"

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