*Merge after backout.
--HG-- branch : trunk
This commit is contained in:
@@ -241,10 +241,11 @@ void ReadLiquidTypeTableDBC()
|
||||
#define MAP_MAGIC 'SPAM'
|
||||
#define MAP_VERSION_MAGIC '0.1w'
|
||||
#define MAP_AREA_MAGIC 'AERA'
|
||||
#define MAP_HEIGTH_MAGIC 'TGHM'
|
||||
#define MAP_HEIGHT_MAGIC 'TGHM'
|
||||
#define MAP_LIQUID_MAGIC 'QILM'
|
||||
|
||||
struct map_fileheader{
|
||||
struct map_fileheader
|
||||
{
|
||||
uint32 mapMagic;
|
||||
uint32 versionMagic;
|
||||
uint32 areaMapOffset;
|
||||
@@ -256,17 +257,20 @@ struct map_fileheader{
|
||||
};
|
||||
|
||||
#define MAP_AREA_NO_AREA 0x0001
|
||||
struct map_areaHeader{
|
||||
|
||||
struct map_areaHeader
|
||||
{
|
||||
uint32 fourcc;
|
||||
uint16 flags;
|
||||
uint16 gridArea;
|
||||
};
|
||||
|
||||
#define MAP_HEIGHT_NO_HIGHT 0x0001
|
||||
#define MAP_HEIGHT_NO_HEIGHT 0x0001
|
||||
#define MAP_HEIGHT_AS_INT16 0x0002
|
||||
#define MAP_HEIGHT_AS_INT8 0x0004
|
||||
|
||||
struct map_heightHeader{
|
||||
struct map_heightHeader
|
||||
{
|
||||
uint32 fourcc;
|
||||
uint32 flags;
|
||||
float gridHeight;
|
||||
@@ -284,9 +288,10 @@ struct map_heightHeader{
|
||||
|
||||
|
||||
#define MAP_LIQUID_NO_TYPE 0x0001
|
||||
#define MAP_LIQUID_NO_HIGHT 0x0002
|
||||
#define MAP_LIQUID_NO_HEIGHT 0x0002
|
||||
|
||||
struct map_liquidHeader{
|
||||
struct map_liquidHeader
|
||||
{
|
||||
uint32 fourcc;
|
||||
uint16 flags;
|
||||
uint16 liquidType;
|
||||
@@ -511,20 +516,20 @@ bool ConvertADT(char *filename, char *filename2, int cell_y, int cell_x)
|
||||
map.heightMapSize = sizeof(map_heightHeader);
|
||||
|
||||
map_heightHeader heightHeader;
|
||||
heightHeader.fourcc = MAP_HEIGTH_MAGIC;
|
||||
heightHeader.fourcc = MAP_HEIGHT_MAGIC;
|
||||
heightHeader.flags = 0;
|
||||
heightHeader.gridHeight = minHeight;
|
||||
heightHeader.gridMaxHeight = maxHeight;
|
||||
|
||||
if (maxHeight == minHeight)
|
||||
heightHeader.flags |=MAP_HEIGHT_NO_HIGHT;
|
||||
heightHeader.flags |= MAP_HEIGHT_NO_HEIGHT;
|
||||
|
||||
// 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;
|
||||
heightHeader.flags |= MAP_HEIGHT_NO_HEIGHT;
|
||||
|
||||
// Try store as packed in uint16 or uint8 values
|
||||
if (!(heightHeader.flags&MAP_HEIGHT_NO_HIGHT))
|
||||
if (!(heightHeader.flags & MAP_HEIGHT_NO_HEIGHT))
|
||||
{
|
||||
float step;
|
||||
// Try Store as uint values
|
||||
@@ -756,22 +761,22 @@ bool ConvertADT(char *filename, char *filename2, int cell_y, int cell_x)
|
||||
liquidHeader.liquidLevel = minHeight;
|
||||
|
||||
if (maxHeight == minHeight)
|
||||
liquidHeader.flags|=MAP_LIQUID_NO_HIGHT;
|
||||
liquidHeader.flags |= MAP_LIQUID_NO_HEIGHT;
|
||||
|
||||
// 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;
|
||||
liquidHeader.flags |= MAP_LIQUID_NO_HEIGHT;
|
||||
|
||||
if (!fullType)
|
||||
liquidHeader.flags|=MAP_LIQUID_NO_TYPE;
|
||||
liquidHeader.flags |= MAP_LIQUID_NO_TYPE;
|
||||
|
||||
if (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;
|
||||
if (!(liquidHeader.flags & MAP_LIQUID_NO_HEIGHT))
|
||||
map.liquidMapSize += sizeof(float)*liquidHeader.width*liquidHeader.height;
|
||||
}
|
||||
|
||||
// Ok all data prepared - store it
|
||||
@@ -789,14 +794,14 @@ bool ConvertADT(char *filename, char *filename2, int cell_y, int cell_x)
|
||||
|
||||
// Store height data
|
||||
fwrite(&heightHeader, sizeof(heightHeader), 1, output);
|
||||
if (!(heightHeader.flags&MAP_HEIGHT_NO_HIGHT))
|
||||
if (!(heightHeader.flags & MAP_HEIGHT_NO_HEIGHT))
|
||||
{
|
||||
if (heightHeader.flags&MAP_HEIGHT_AS_INT16)
|
||||
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)
|
||||
else if (heightHeader.flags & MAP_HEIGHT_AS_INT8)
|
||||
{
|
||||
fwrite(uint8_V9, sizeof(uint8_V9), 1, output);
|
||||
fwrite(uint8_V8, sizeof(uint8_V8), 1, output);
|
||||
@@ -814,7 +819,7 @@ bool ConvertADT(char *filename, char *filename2, int cell_y, int cell_x)
|
||||
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))
|
||||
if (!(liquidHeader.flags&MAP_LIQUID_NO_HEIGHT))
|
||||
{
|
||||
for (int y=0; y<liquidHeader.height;y++)
|
||||
fwrite(&liquid_height[y+liquidHeader.offsetY][liquidHeader.offsetX], sizeof(float), liquidHeader.width, output);
|
||||
|
||||
+33
-21
@@ -23,7 +23,7 @@ DROP TABLE IF EXISTS `db_version`;
|
||||
CREATE TABLE `db_version` (
|
||||
`version` varchar(120) default NULL,
|
||||
`creature_ai_version` varchar(120) default NULL,
|
||||
`required_8247_01_mangos_spell_bonus_data` bit(1) default NULL
|
||||
`required_8254_01_mangos_spell_proc_event` bit(1) default NULL
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=FIXED COMMENT='Used DB version notes';
|
||||
|
||||
--
|
||||
@@ -15376,7 +15376,7 @@ INSERT INTO spell_chain VALUES
|
||||
(27219,11700,689,7,0),
|
||||
(27220,27219,689,8,0),
|
||||
(47857,27220,689,9,0),
|
||||
/*DrainSoul*/
|
||||
/*Drain Soul*/
|
||||
(1120,0,1120,1,0),
|
||||
(8288,1120,1120,2,0),
|
||||
(8289,8288,1120,3,0),
|
||||
@@ -15392,14 +15392,20 @@ INSERT INTO spell_chain VALUES
|
||||
(59161,48181,48181,2,0),
|
||||
(59163,59161,48181,3,0),
|
||||
(59164,59163,48181,4,0),
|
||||
/*HowlofTerror*/
|
||||
/*Howl of Terror*/
|
||||
(5484,0,5484,1,0),
|
||||
(17928,5484,5484,2,0),
|
||||
/*SeedofCorruption*/
|
||||
/*Seed of Corruption*/
|
||||
(27243,0,27243,1,0),
|
||||
(47835,27243,27243,2,0),
|
||||
(47836,47835,27243,3,0),
|
||||
/*UnstableAffliction*/
|
||||
/* Shadow embrace */
|
||||
(32385,0,32385,1,0),
|
||||
(32387,32385,32385,2,0),
|
||||
(32392,32387,32385,3,0),
|
||||
(32393,32392,32385,4,0),
|
||||
(32394,32393,32385,5,0),
|
||||
/*Unstable Affliction*/
|
||||
(30108,0,30108,1,0),
|
||||
(30404,30108,30108,2,0),
|
||||
(30405,30404,30108,3,0),
|
||||
@@ -15486,6 +15492,12 @@ INSERT INTO spell_chain VALUES
|
||||
(25472,25469,324,9,0),
|
||||
(49280,25472,324,10,0),
|
||||
(49281,49280,324,11,0),
|
||||
/*Maelstrom Weapon*/
|
||||
(51528,0,51528,1,0),
|
||||
(51529,51528,51528,2,0),
|
||||
(51530,51529,51528,3,0),
|
||||
(51531,51530,51528,4,0),
|
||||
(51532,51531,51528,5,0),
|
||||
/*Nature Resistance Totem*/
|
||||
(10595,0,10595,1,0),
|
||||
(10600,10595,10595,2,0),
|
||||
@@ -16924,7 +16936,7 @@ INSERT INTO `spell_proc_event` VALUES
|
||||
(12999, 0x00000000, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 4.000000, 0.000000, 0),
|
||||
(13000, 0x00000000, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 6.000000, 0.000000, 0),
|
||||
(13001, 0x00000000, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 8.000000, 0.000000, 0),
|
||||
(13002, 0x00000000, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 10.000000, 0.000000, 0),
|
||||
(13002, 0x00000000, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,10.000000, 0.000000, 0),
|
||||
(13045, 0x00000000, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000002, 0.000000, 0.000000, 0),
|
||||
(13046, 0x00000000, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000002, 0.000000, 0.000000, 0),
|
||||
(13047, 0x00000000, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000002, 0.000000, 0.000000, 0),
|
||||
@@ -17023,8 +17035,8 @@ INSERT INTO `spell_proc_event` VALUES
|
||||
(20131, 0x00000000, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000040, 0.000000, 0.000000, 0),
|
||||
(20132, 0x00000000, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000040, 0.000000, 0.000000, 0),
|
||||
(20164, 0x00000000, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 5.000000, 0.000000, 0),
|
||||
(20165, 0x00000000, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 20.000000, 0.000000, 0),
|
||||
(20166, 0x00000000, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 20.000000, 0.000000, 0),
|
||||
(20165, 0x00000000, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,20.000000, 0.000000, 0),
|
||||
(20166, 0x00000000, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,15.000000, 0.000000, 0),
|
||||
(20182, 0x00000000, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000040, 0.000000, 0.000000, 0),
|
||||
(20210, 0x00000000, 10, 0xC0000000, 0x00010000, 0x00000000, 0x00000000, 0x00000002, 0.000000, 0.000000, 0),
|
||||
(20212, 0x00000000, 10, 0xC0000000, 0x00010000, 0x00000000, 0x00000000, 0x00000002, 0.000000, 0.000000, 0),
|
||||
@@ -17065,7 +17077,7 @@ INSERT INTO `spell_proc_event` VALUES
|
||||
(24389, 0x00000000, 3, 0x00C00017, 0x00000040, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 0),
|
||||
(24398, 0x00000000, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 3),
|
||||
(24658, 0x00000000, 0, 0x00000000, 0x00000000, 0x00000000, 0x00014110, 0x00000000, 0.000000, 0.000000, 0),
|
||||
(24905, 0x00000000, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000002, 15.000000, 0.000000, 0),
|
||||
(24905, 0x00000000, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000002,15.000000, 0.000000, 0),
|
||||
(24932, 0x00000000, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000002, 0.000000, 0.000000, 6),
|
||||
(25050, 0x00000004, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 0),
|
||||
(25296, 0x00000000, 9, 0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 0),
|
||||
@@ -17168,7 +17180,7 @@ INSERT INTO `spell_proc_event` VALUES
|
||||
(31570, 0x00000000, 3, 0x00010000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 0),
|
||||
(31785, 0x00000000, 0, 0x00000000, 0x00000000, 0x00000000, 0x00008800, 0x00000000, 0.000000, 0.000000, 0),
|
||||
(31794, 0x00000000, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00010000, 0.000000, 0.000000, 0),
|
||||
(31801, 0x00000000, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 20.000000, 0.000000, 0),
|
||||
(31801, 0x00000000, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,20.000000, 0.000000, 0),
|
||||
(31833, 0x00000000, 10, 0x80000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 0),
|
||||
(31835, 0x00000000, 10, 0x80000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 0),
|
||||
(31836, 0x00000000, 10, 0x80000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 0),
|
||||
@@ -17178,11 +17190,7 @@ INSERT INTO `spell_proc_event` VALUES
|
||||
(31877, 0x00000000, 10, 0x00800000, 0x00000000, 0x00000008, 0x00004110, 0x00000000, 0.000000, 0.000000, 0),
|
||||
(31878, 0x00000000, 10, 0x00800000, 0x00000000, 0x00000008, 0x00004110, 0x00000000, 0.000000, 0.000000, 0),
|
||||
(31904, 0x00000000, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000040, 0.000000, 0.000000, 0),
|
||||
(32385, 0x00000000, 5, 0x00000402, 0x00000011, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 0),
|
||||
(32387, 0x00000000, 5, 0x00000402, 0x00000011, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 0),
|
||||
(32392, 0x00000000, 5, 0x00000402, 0x00000011, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 0),
|
||||
(32393, 0x00000000, 5, 0x00000402, 0x00000011, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 0),
|
||||
(32394, 0x00000000, 5, 0x00000402, 0x00000011, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 0),
|
||||
(32385, 0x00000000, 5, 0x00000001, 0x00040000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 0),
|
||||
(32409, 0x00000000, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 0),
|
||||
(32587, 0x00000000, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000040, 0.000000, 0.000000, 0),
|
||||
(32593, 0x00000000, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 3),
|
||||
@@ -17476,6 +17484,7 @@ INSERT INTO `spell_proc_event` VALUES
|
||||
(51483, 0x00000001, 11, 0x20000000, 0x00000000, 0x00000000, 0x00004000, 0x00000000, 0.000000, 0.000000, 0),
|
||||
(51485, 0x00000001, 11, 0x20000000, 0x00000000, 0x00000000, 0x00004000, 0x00000000, 0.000000, 0.000000, 0),
|
||||
(51486, 0x00000001, 11, 0x20000000, 0x00000000, 0x00000000, 0x00004000, 0x00000000, 0.000000, 0.000000, 0),
|
||||
(51528, 0x00000000, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,12.500000, 0.000000, 0),
|
||||
(51556, 0x00000000, 11, 0x000000C0, 0x00000000, 0x00000010, 0x00000000, 0x00000002, 0.000000, 0.000000, 0),
|
||||
(51557, 0x00000000, 11, 0x000000C0, 0x00000000, 0x00000010, 0x00000000, 0x00000002, 0.000000, 0.000000, 0),
|
||||
(51558, 0x00000000, 11, 0x000000C0, 0x00000000, 0x00000010, 0x00000000, 0x00000002, 0.000000, 0.000000, 0),
|
||||
@@ -17505,12 +17514,12 @@ INSERT INTO `spell_proc_event` VALUES
|
||||
(51698, 0x00000000, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000002, 0.000000, 0.000000, 1),
|
||||
(51700, 0x00000000, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000002, 0.000000, 0.000000, 1),
|
||||
(51701, 0x00000000, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000002, 0.000000, 0.000000, 1),
|
||||
(51940, 0x00000000, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 20.000000, 0),
|
||||
(51989, 0x00000000, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 20.000000, 0),
|
||||
(52004, 0x00000000, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 20.000000, 0),
|
||||
(52005, 0x00000000, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 20.000000, 0),
|
||||
(52007, 0x00000000, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 20.000000, 0),
|
||||
(52008, 0x00000000, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 20.000000, 0),
|
||||
(51940, 0x00000000, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0.000000,20.000000, 0),
|
||||
(51989, 0x00000000, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0.000000,20.000000, 0),
|
||||
(52004, 0x00000000, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0.000000,20.000000, 0),
|
||||
(52005, 0x00000000, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0.000000,20.000000, 0),
|
||||
(52007, 0x00000000, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0.000000,20.000000, 0),
|
||||
(52008, 0x00000000, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0.000000,20.000000, 0),
|
||||
(52020, 0x00000000, 7, 0x00008000, 0x00100000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 0),
|
||||
(52127, 0x00000000, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 3),
|
||||
(52129, 0x00000000, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 3),
|
||||
@@ -17586,6 +17595,7 @@ INSERT INTO `spell_proc_event` VALUES
|
||||
(55677, 0x00000000, 6, 0x00000000, 0x00000001, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 0),
|
||||
(55680, 0x00000000, 6, 0x00000200, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 0),
|
||||
(55689, 0x00000000, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000002, 0.000000, 0.000000, 0),
|
||||
(55747, 0x00000000, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 45),
|
||||
(55768, 0x00000000, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 45),
|
||||
(55776, 0x00000000, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 45),
|
||||
(56218, 0x00000000, 5, 0x00000002, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 0),
|
||||
@@ -17634,6 +17644,8 @@ INSERT INTO `spell_proc_event` VALUES
|
||||
(60132, 0x00000000, 15, 0x00000000, 0x08020000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 0),
|
||||
(60170, 0x00000000, 5, 0x00000006, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 0),
|
||||
(60172, 0x00000000, 5, 0x00040000, 0x00000000, 0x00000000, 0x00000000, 0x00010000, 0.000000, 0.000000, 0),
|
||||
(60436, 0x00000000, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 45),
|
||||
(60442, 0x00000000, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 45),
|
||||
(60493, 0x00000000, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 45),
|
||||
(60503, 0x00000000, 4, 0x00000004, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 0),
|
||||
(60537, 0x00000000, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000002, 0.000000, 0.000000, 0),
|
||||
|
||||
@@ -229,6 +229,8 @@ INSERT INTO spell_check (spellid,SpellFamilyName,SpellFamilyMaskA,SpellFamilyMas
|
||||
(45030, 0, -1, -1, -1, -1, -1, 3, -1,-1,'Impale Emissary', 'Spell::EffectDummy'),
|
||||
(45088,-1, -1, -1, -1, -1, -1, -1, -1,-1,'Emissary of Hate Credit', 'Spell::EffectDummy'),
|
||||
(45150, 0, -1, -1, -1, -1, -1, 2, -1,-1,'Meteor Slash', 'Spell::EffectSchoolDMG'),
|
||||
(64422, 0, -1, -1, -1, -1, -1, 2, -1,-1,'Meteor Slash', 'Spell::EffectSchoolDMG'),
|
||||
(64688, 0, -1, -1, -1, -1, -1, 2, -1,-1,'Meteor Slash', 'Spell::EffectSchoolDMG'),
|
||||
(45182,-1, -1, -1, -1, -1, -1, -1, -1,-1,'Cheat Death', 'Spell::EffectDummy'),
|
||||
(46014,-1, -1, -1, -1, -1, -1, -1, -1,-1,'Knocked Up', 'Spell::EffectDummy'),
|
||||
(47540, 6,0x0080000000000000,0x00000000, -1, -1, -1, 3, -1,-1,'Penance', 'Spell::EffectDummy'),
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
ALTER TABLE db_version CHANGE COLUMN required_8253_01_mangos_spell_chain required_8253_02_mangos_spell_proc_event bit;
|
||||
|
||||
/*Bandit's Insignia*/
|
||||
DELETE FROM `spell_proc_event` WHERE entry IN (60442);
|
||||
INSERT INTO spell_proc_event VALUES
|
||||
(60442, 0x00000000, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 45);
|
||||
|
||||
/*Seal of wisdom*/
|
||||
DELETE FROM `spell_proc_event` WHERE `entry` IN (20166);
|
||||
INSERT INTO `spell_proc_event` VALUES
|
||||
(20166, 0x00000000, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,15.000000, 0.000000, 0);
|
||||
|
||||
/*Shadow embrace*/
|
||||
DELETE FROM `spell_proc_event` WHERE `entry` IN (32385);
|
||||
INSERT INTO `spell_proc_event` VALUES
|
||||
(32385, 0x00000000, 5, 0x00000001, 0x00040000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 0);
|
||||
|
||||
/*Maelstrom Weapon*/
|
||||
DELETE FROM `spell_proc_event` WHERE `entry` IN (51528);
|
||||
INSERT INTO `spell_proc_event` VALUES
|
||||
(51528, 0x00000000, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,12.500000, 0.000000, 0);
|
||||
@@ -0,0 +1,6 @@
|
||||
ALTER TABLE db_version CHANGE COLUMN required_8253_02_mangos_spell_proc_event required_8254_01_mangos_spell_proc_event bit;
|
||||
|
||||
DELETE FROM `spell_proc_event` WHERE `entry` IN (55747,60436);
|
||||
INSERT INTO `spell_proc_event` VALUES
|
||||
(55747, 0x00000000, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 45),
|
||||
(60436, 0x00000000, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 45);
|
||||
+24
-24
@@ -26,7 +26,7 @@
|
||||
#include "Player.h"
|
||||
#include "Util.h"
|
||||
|
||||
extern DatabaseType LoginDatabase;
|
||||
extern DatabaseType loginDatabase;
|
||||
|
||||
INSTANTIATE_SINGLETON_1(AccountMgr);
|
||||
|
||||
@@ -44,26 +44,26 @@ AccountOpResult AccountMgr::CreateAccount(std::string username, std::string pass
|
||||
normalizeString(username);
|
||||
normalizeString(password);
|
||||
|
||||
LoginDatabase.escape_string(username);
|
||||
LoginDatabase.escape_string(password);
|
||||
loginDatabase.escape_string(username);
|
||||
loginDatabase.escape_string(password);
|
||||
|
||||
QueryResult *result = LoginDatabase.PQuery("SELECT 1 FROM account WHERE username = '%s'", username.c_str());
|
||||
QueryResult *result = loginDatabase.PQuery("SELECT 1 FROM account WHERE username = '%s'", username.c_str());
|
||||
if(result)
|
||||
{
|
||||
delete result;
|
||||
return AOR_NAME_ALREDY_EXIST; // username does already exist
|
||||
}
|
||||
|
||||
if(!LoginDatabase.PExecute("INSERT INTO account(username,sha_pass_hash,joindate) VALUES('%s',SHA1(CONCAT('%s',':','%s')),NOW())", username.c_str(), username.c_str(), password.c_str()))
|
||||
if(!loginDatabase.PExecute("INSERT INTO account(username,sha_pass_hash,joindate) VALUES('%s',SHA1(CONCAT('%s',':','%s')),NOW())", username.c_str(), username.c_str(), password.c_str()))
|
||||
return AOR_DB_INTERNAL_ERROR; // unexpected error
|
||||
LoginDatabase.Execute("INSERT INTO realmcharacters (realmid, acctid, numchars) SELECT realmlist.id, account.id, 0 FROM realmlist,account LEFT JOIN realmcharacters ON acctid=account.id WHERE acctid IS NULL");
|
||||
loginDatabase.Execute("INSERT INTO realmcharacters (realmid, acctid, numchars) SELECT realmlist.id, account.id, 0 FROM realmlist,account LEFT JOIN realmcharacters ON acctid=account.id WHERE acctid IS NULL");
|
||||
|
||||
return AOR_OK; // everything's fine
|
||||
}
|
||||
|
||||
AccountOpResult AccountMgr::DeleteAccount(uint32 accid)
|
||||
{
|
||||
QueryResult *result = LoginDatabase.PQuery("SELECT 1 FROM account WHERE id='%d'", accid);
|
||||
QueryResult *result = loginDatabase.PQuery("SELECT 1 FROM account WHERE id='%d'", accid);
|
||||
if(!result)
|
||||
return AOR_NAME_NOT_EXIST; // account doesn't exist
|
||||
delete result;
|
||||
@@ -94,13 +94,13 @@ AccountOpResult AccountMgr::DeleteAccount(uint32 accid)
|
||||
// table realm specific but common for all characters of account for realm
|
||||
CharacterDatabase.PExecute("DELETE FROM character_tutorial WHERE account = '%u'",accid);
|
||||
|
||||
LoginDatabase.BeginTransaction();
|
||||
loginDatabase.BeginTransaction();
|
||||
|
||||
bool res =
|
||||
LoginDatabase.PExecute("DELETE FROM account WHERE id='%d'", accid) &&
|
||||
LoginDatabase.PExecute("DELETE FROM realmcharacters WHERE acctid='%d'", accid);
|
||||
loginDatabase.PExecute("DELETE FROM account WHERE id='%d'", accid) &&
|
||||
loginDatabase.PExecute("DELETE FROM realmcharacters WHERE acctid='%d'", accid);
|
||||
|
||||
LoginDatabase.CommitTransaction();
|
||||
loginDatabase.CommitTransaction();
|
||||
|
||||
if(!res)
|
||||
return AOR_DB_INTERNAL_ERROR; // unexpected error;
|
||||
@@ -110,7 +110,7 @@ AccountOpResult AccountMgr::DeleteAccount(uint32 accid)
|
||||
|
||||
AccountOpResult AccountMgr::ChangeUsername(uint32 accid, std::string new_uname, std::string new_passwd)
|
||||
{
|
||||
QueryResult *result = LoginDatabase.PQuery("SELECT 1 FROM account WHERE id='%d'", accid);
|
||||
QueryResult *result = loginDatabase.PQuery("SELECT 1 FROM account WHERE id='%d'", accid);
|
||||
if(!result)
|
||||
return AOR_NAME_NOT_EXIST; // account doesn't exist
|
||||
delete result;
|
||||
@@ -124,9 +124,9 @@ AccountOpResult AccountMgr::ChangeUsername(uint32 accid, std::string new_uname,
|
||||
normalizeString(new_uname);
|
||||
normalizeString(new_passwd);
|
||||
|
||||
LoginDatabase.escape_string(new_uname);
|
||||
LoginDatabase.escape_string(new_passwd);
|
||||
if(!LoginDatabase.PExecute("UPDATE account SET username='%s',sha_pass_hash=SHA1(CONCAT('%s',':','%s')) WHERE id='%d'", new_uname.c_str(), new_uname.c_str(), new_passwd.c_str(), accid))
|
||||
loginDatabase.escape_string(new_uname);
|
||||
loginDatabase.escape_string(new_passwd);
|
||||
if(!loginDatabase.PExecute("UPDATE account SET username='%s',sha_pass_hash=SHA1(CONCAT('%s',':','%s')) WHERE id='%d'", new_uname.c_str(), new_uname.c_str(), new_passwd.c_str(), accid))
|
||||
return AOR_DB_INTERNAL_ERROR; // unexpected error
|
||||
|
||||
return AOR_OK;
|
||||
@@ -134,7 +134,7 @@ AccountOpResult AccountMgr::ChangeUsername(uint32 accid, std::string new_uname,
|
||||
|
||||
AccountOpResult AccountMgr::ChangePassword(uint32 accid, std::string new_passwd)
|
||||
{
|
||||
QueryResult *result = LoginDatabase.PQuery("SELECT 1 FROM account WHERE id='%d'", accid);
|
||||
QueryResult *result = loginDatabase.PQuery("SELECT 1 FROM account WHERE id='%d'", accid);
|
||||
if(!result)
|
||||
return AOR_NAME_NOT_EXIST; // account doesn't exist
|
||||
delete result;
|
||||
@@ -144,8 +144,8 @@ AccountOpResult AccountMgr::ChangePassword(uint32 accid, std::string new_passwd)
|
||||
|
||||
normalizeString(new_passwd);
|
||||
|
||||
LoginDatabase.escape_string(new_passwd);
|
||||
if(!LoginDatabase.PExecute("UPDATE account SET sha_pass_hash=SHA1(CONCAT(username,':','%s')) WHERE id='%d'", new_passwd.c_str(), accid))
|
||||
loginDatabase.escape_string(new_passwd);
|
||||
if(!loginDatabase.PExecute("UPDATE account SET sha_pass_hash=SHA1(CONCAT(username,':','%s')) WHERE id='%d'", new_passwd.c_str(), accid))
|
||||
return AOR_DB_INTERNAL_ERROR; // unexpected error
|
||||
|
||||
return AOR_OK;
|
||||
@@ -153,8 +153,8 @@ AccountOpResult AccountMgr::ChangePassword(uint32 accid, std::string new_passwd)
|
||||
|
||||
uint32 AccountMgr::GetId(std::string username)
|
||||
{
|
||||
LoginDatabase.escape_string(username);
|
||||
QueryResult *result = LoginDatabase.PQuery("SELECT id FROM account WHERE username = '%s'", username.c_str());
|
||||
loginDatabase.escape_string(username);
|
||||
QueryResult *result = loginDatabase.PQuery("SELECT id FROM account WHERE username = '%s'", username.c_str());
|
||||
if(!result)
|
||||
return 0;
|
||||
else
|
||||
@@ -167,7 +167,7 @@ uint32 AccountMgr::GetId(std::string username)
|
||||
|
||||
uint32 AccountMgr::GetSecurity(uint32 acc_id)
|
||||
{
|
||||
QueryResult *result = LoginDatabase.PQuery("SELECT gmlevel FROM account WHERE id = '%u'", acc_id);
|
||||
QueryResult *result = loginDatabase.PQuery("SELECT gmlevel FROM account WHERE id = '%u'", acc_id);
|
||||
if(result)
|
||||
{
|
||||
uint32 sec = (*result)[0].GetUInt32();
|
||||
@@ -180,7 +180,7 @@ uint32 AccountMgr::GetSecurity(uint32 acc_id)
|
||||
|
||||
bool AccountMgr::GetName(uint32 acc_id, std::string &name)
|
||||
{
|
||||
QueryResult *result = LoginDatabase.PQuery("SELECT username FROM account WHERE id = '%u'", acc_id);
|
||||
QueryResult *result = loginDatabase.PQuery("SELECT username FROM account WHERE id = '%u'", acc_id);
|
||||
if(result)
|
||||
{
|
||||
name = (*result)[0].GetCppString();
|
||||
@@ -194,9 +194,9 @@ bool AccountMgr::GetName(uint32 acc_id, std::string &name)
|
||||
bool AccountMgr::CheckPassword(uint32 accid, std::string passwd)
|
||||
{
|
||||
normalizeString(passwd);
|
||||
LoginDatabase.escape_string(passwd);
|
||||
loginDatabase.escape_string(passwd);
|
||||
|
||||
QueryResult *result = LoginDatabase.PQuery("SELECT 1 FROM account WHERE id='%d' AND sha_pass_hash=SHA1(CONCAT(username,':','%s'))", accid, passwd.c_str());
|
||||
QueryResult *result = loginDatabase.PQuery("SELECT 1 FROM account WHERE id='%d' AND sha_pass_hash=SHA1(CONCAT(username,':','%s'))", accid, passwd.c_str());
|
||||
if (result)
|
||||
{
|
||||
delete result;
|
||||
|
||||
+66
-10
@@ -36,6 +36,8 @@
|
||||
#include "SpellMgr.h"
|
||||
|
||||
#include "MapManager.h"
|
||||
#include "BattleGround.h"
|
||||
#include "BattleGroundAB.h"
|
||||
|
||||
|
||||
INSTANTIATE_SINGLETON_1(AchievementGlobalMgr);
|
||||
@@ -81,6 +83,7 @@ bool AchievementCriteriaData::IsValid(AchievementCriteriaEntry const* criteria)
|
||||
|
||||
switch(criteria->requiredType)
|
||||
{
|
||||
case ACHIEVEMENT_CRITERIA_TYPE_WIN_BG:
|
||||
case ACHIEVEMENT_CRITERIA_TYPE_KILL_CREATURE:
|
||||
case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_QUEST: // only hardcoded list
|
||||
case ACHIEVEMENT_CRITERIA_TYPE_FALL_WITHOUT_DYING:
|
||||
@@ -233,6 +236,8 @@ bool AchievementCriteriaData::IsValid(AchievementCriteriaEntry const* criteria)
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
case ACHIEVEMENT_CRITERIA_DATA_TYPE_BG_LOSS_TEAM_SCORE:
|
||||
return true; // not check correctness node indexes
|
||||
default:
|
||||
sLog.outErrorDb( "Table `achievement_criteria_data` (Entry: %u Type: %u) have data for not supported data type (%u), ignore.", criteria->ID, criteria->requiredType,dataType);
|
||||
return false;
|
||||
@@ -301,6 +306,13 @@ bool AchievementCriteriaData::Meets(Player const* source, Unit const* target, ui
|
||||
return Player::GetDrunkenstateByValue(source->GetDrunkValue()) >= drunk.state;
|
||||
case ACHIEVEMENT_CRITERIA_DATA_TYPE_HOLIDAY:
|
||||
return IsHolidayActive(HolidayIds(holiday.id));
|
||||
case ACHIEVEMENT_CRITERIA_DATA_TYPE_BG_LOSS_TEAM_SCORE:
|
||||
{
|
||||
BattleGround* bg = source->GetBattleGround();
|
||||
if(!bg)
|
||||
return false;
|
||||
return bg->IsTeamScoreInRange(source->GetTeam()==ALLIANCE ? HORDE : ALLIANCE,bg_loss_team_score.min_score,bg_loss_team_score.max_score);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@@ -720,6 +732,54 @@ void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, ui
|
||||
|
||||
// specialized cases
|
||||
|
||||
case ACHIEVEMENT_CRITERIA_TYPE_WIN_BG:
|
||||
{
|
||||
// AchievementMgr::UpdateAchievementCriteria might also be called on login - skip in this case
|
||||
if (!miscvalue1)
|
||||
continue;
|
||||
if (achievementCriteria->win_bg.bgMapID != GetPlayer()->GetMapId())
|
||||
continue;
|
||||
|
||||
if (achievementCriteria->win_bg.additionalRequirement1_type)
|
||||
{
|
||||
// those requirements couldn't be found in the dbc
|
||||
AchievementCriteriaDataSet const* data = achievementmgr.GetCriteriaDataSet(achievementCriteria);
|
||||
if (!data || !data->Meets(GetPlayer(),unit))
|
||||
continue;
|
||||
}
|
||||
// some hardcoded requirements
|
||||
else
|
||||
{
|
||||
BattleGround* bg = GetPlayer()->GetBattleGround();
|
||||
if (!bg)
|
||||
continue;
|
||||
|
||||
switch(achievementCriteria->referredAchievement)
|
||||
{
|
||||
case 161: // AB, Overcome a 500 resource disadvantage
|
||||
{
|
||||
if (bg->GetTypeID() != BATTLEGROUND_AB)
|
||||
continue;
|
||||
if(!((BattleGroundAB*)bg)->IsTeamScores500disadvantage(GetPlayer()->GetTeam()))
|
||||
continue;
|
||||
break;
|
||||
}
|
||||
case 156: // AB, win while controlling all 5 flags (all nodes)
|
||||
case 784: // EY, win while holding 4 bases (all nodes)
|
||||
{
|
||||
if(!bg->IsAllNodesConrolledByTeam(GetPlayer()->GetTeam()))
|
||||
continue;
|
||||
break;
|
||||
}
|
||||
case 1762: // SA, win without losing any siege vehicles
|
||||
case 2192: // SA, win without losing any siege vehicles
|
||||
continue; // not implemented
|
||||
}
|
||||
}
|
||||
|
||||
SetCriteriaProgress(achievementCriteria, miscvalue1, PROGRESS_ACCUMULATE);
|
||||
break;
|
||||
}
|
||||
case ACHIEVEMENT_CRITERIA_TYPE_KILL_CREATURE:
|
||||
{
|
||||
// AchievementMgr::UpdateAchievementCriteria might also be called on login - skip in this case
|
||||
@@ -790,14 +850,6 @@ void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, ui
|
||||
continue;
|
||||
SetCriteriaProgress(achievementCriteria, miscvalue1, PROGRESS_ACCUMULATE);
|
||||
break;
|
||||
case ACHIEVEMENT_CRITERIA_TYPE_WIN_BG:
|
||||
// AchievementMgr::UpdateAchievementCriteria might also be called on login - skip in this case
|
||||
if(!miscvalue1)
|
||||
continue;
|
||||
if(GetPlayer()->GetMapId() != achievementCriteria->win_bg.bgMapID)
|
||||
continue;
|
||||
SetCriteriaProgress(achievementCriteria, miscvalue1, PROGRESS_ACCUMULATE);
|
||||
break;
|
||||
case ACHIEVEMENT_CRITERIA_TYPE_DEATH_AT_MAP:
|
||||
// AchievementMgr::UpdateAchievementCriteria might also be called on login - skip in this case
|
||||
if(!miscvalue1)
|
||||
@@ -1347,6 +1399,8 @@ bool AchievementMgr::IsCompletedCriteria(AchievementCriteriaEntry const* achieve
|
||||
|
||||
switch(achievementCriteria->requiredType)
|
||||
{
|
||||
case ACHIEVEMENT_CRITERIA_TYPE_WIN_BG:
|
||||
return progress->counter >= achievementCriteria->win_bg.winCount;
|
||||
case ACHIEVEMENT_CRITERIA_TYPE_KILL_CREATURE:
|
||||
return progress->counter >= achievementCriteria->kill_creature.creatureCount;
|
||||
case ACHIEVEMENT_CRITERIA_TYPE_REACH_LEVEL:
|
||||
@@ -1438,8 +1492,6 @@ bool AchievementMgr::IsCompletedCriteria(AchievementCriteriaEntry const* achieve
|
||||
return progress->counter >= achievementCriteria->learn_skill_line.spellCount;
|
||||
case ACHIEVEMENT_CRITERIA_TYPE_EARN_HONORABLE_KILL:
|
||||
return progress->counter >= achievementCriteria->honorable_kill.killCount;
|
||||
case ACHIEVEMENT_CRITERIA_TYPE_WIN_BG:
|
||||
return progress->counter >= achievementCriteria->win_bg.winCount;
|
||||
// handle all statistic-only criteria here
|
||||
case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_BATTLEGROUND:
|
||||
case ACHIEVEMENT_CRITERIA_TYPE_DEATH_AT_MAP:
|
||||
@@ -1853,6 +1905,10 @@ void AchievementGlobalMgr::LoadAchievementCriteriaData()
|
||||
|
||||
switch(criteria->requiredType)
|
||||
{
|
||||
case ACHIEVEMENT_CRITERIA_TYPE_WIN_BG:
|
||||
if(!criteria->win_bg.additionalRequirement1_type)
|
||||
continue;
|
||||
break;
|
||||
case ACHIEVEMENT_CRITERIA_TYPE_KILL_CREATURE:
|
||||
break; // any cases
|
||||
case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_QUEST:
|
||||
|
||||
@@ -59,9 +59,10 @@ enum AchievementCriteriaDataType
|
||||
ACHIEVEMENT_CRITERIA_DATA_TYPE_T_TEAM = 14,// team HORDE(67), ALLIANCE(469)
|
||||
ACHIEVEMENT_CRITERIA_DATA_TYPE_S_DRUNK = 15,// drunken_state 0 (enum DrunkenState) of player
|
||||
ACHIEVEMENT_CRITERIA_DATA_TYPE_HOLIDAY = 16,// holiday_id 0 event in holiday time
|
||||
ACHIEVEMENT_CRITERIA_DATA_TYPE_BG_LOSS_TEAM_SCORE = 17,// min_score max_score player's team win bg and opposition team have team score in range
|
||||
};
|
||||
|
||||
#define MAX_ACHIEVEMENT_CRITERIA_DATA_TYPE 17 // maximum value in AchievementCriteriaDataType enum
|
||||
#define MAX_ACHIEVEMENT_CRITERIA_DATA_TYPE 18 // maximum value in AchievementCriteriaDataType enum
|
||||
|
||||
class Player;
|
||||
class Unit;
|
||||
@@ -141,11 +142,17 @@ struct AchievementCriteriaData
|
||||
{
|
||||
uint32 state;
|
||||
} drunk;
|
||||
// ACHIEVEMENT_CRITERIA_DATA_TYPE_HOLIDAY
|
||||
// ACHIEVEMENT_CRITERIA_DATA_TYPE_HOLIDAY = 16
|
||||
struct
|
||||
{
|
||||
uint16 id;
|
||||
uint32 id;
|
||||
} holiday;
|
||||
// ACHIEVEMENT_CRITERIA_DATA_TYPE_BG_LOSS_TEAM_SCORE= 17
|
||||
struct
|
||||
{
|
||||
uint32 min_score;
|
||||
uint32 max_score;
|
||||
} bg_loss_team_score;
|
||||
// ...
|
||||
struct
|
||||
{
|
||||
|
||||
+118
-119
@@ -33,24 +33,24 @@ void ArenaTeamMember::ModifyPersonalRating(Player* plr, int32 mod, uint32 slot)
|
||||
|
||||
ArenaTeam::ArenaTeam()
|
||||
{
|
||||
Id = 0;
|
||||
Type = 0;
|
||||
Name = "";
|
||||
CaptainGuid = 0;
|
||||
BackgroundColor = 0; // background
|
||||
EmblemStyle = 0; // icon
|
||||
EmblemColor = 0; // icon color
|
||||
BorderStyle = 0; // border
|
||||
BorderColor = 0; // border color
|
||||
stats.games_week = 0;
|
||||
stats.games_season = 0;
|
||||
stats.rank = 0;
|
||||
m_TeamId = 0;
|
||||
m_Type = 0;
|
||||
m_Name = "";
|
||||
m_CaptainGuid = 0;
|
||||
m_BackgroundColor = 0; // background
|
||||
m_EmblemStyle = 0; // icon
|
||||
m_EmblemColor = 0; // icon color
|
||||
m_BorderStyle = 0; // border
|
||||
m_BorderColor = 0; // border color
|
||||
m_stats.games_week = 0;
|
||||
m_stats.games_season = 0;
|
||||
m_stats.rank = 0;
|
||||
if (sWorld.getConfig(CONFIG_ARENA_SEASON_ID) >= 6)
|
||||
stats.rating = 0;
|
||||
m_stats.rating = 0;
|
||||
else
|
||||
stats.rating = 1500;
|
||||
stats.wins_week = 0;
|
||||
stats.wins_season = 0;
|
||||
m_stats.rating = 1500;
|
||||
m_stats.wins_week = 0;
|
||||
m_stats.wins_season = 0;
|
||||
}
|
||||
|
||||
ArenaTeam::~ArenaTeam()
|
||||
@@ -66,27 +66,27 @@ bool ArenaTeam::Create(uint64 captainGuid, uint32 type, std::string ArenaTeamNam
|
||||
|
||||
sLog.outDebug("GUILD: creating arena team %s to leader: %u", ArenaTeamName.c_str(), GUID_LOPART(captainGuid));
|
||||
|
||||
CaptainGuid = captainGuid;
|
||||
Name = ArenaTeamName;
|
||||
Type = type;
|
||||
m_CaptainGuid = captainGuid;
|
||||
m_Name = ArenaTeamName;
|
||||
m_Type = type;
|
||||
|
||||
Id = objmgr.GenerateArenaTeamId();
|
||||
m_TeamId = objmgr.GenerateArenaTeamId();
|
||||
|
||||
// ArenaTeamName already assigned to ArenaTeam::name, use it to encode string for DB
|
||||
CharacterDatabase.escape_string(ArenaTeamName);
|
||||
|
||||
CharacterDatabase.BeginTransaction();
|
||||
// CharacterDatabase.PExecute("DELETE FROM arena_team WHERE arenateamid='%u'", Id); - MAX(arenateam)+1 not exist
|
||||
CharacterDatabase.PExecute("DELETE FROM arena_team_member WHERE arenateamid='%u'", Id);
|
||||
// CharacterDatabase.PExecute("DELETE FROM arena_team WHERE arenateamid='%u'", m_TeamId); - MAX(arenateam)+1 not exist
|
||||
CharacterDatabase.PExecute("DELETE FROM arena_team_member WHERE arenateamid='%u'", m_TeamId);
|
||||
CharacterDatabase.PExecute("INSERT INTO arena_team (arenateamid,name,captainguid,type,BackgroundColor,EmblemStyle,EmblemColor,BorderStyle,BorderColor) "
|
||||
"VALUES('%u','%s','%u','%u','%u','%u','%u','%u','%u')",
|
||||
Id, ArenaTeamName.c_str(), GUID_LOPART(CaptainGuid), Type, BackgroundColor, EmblemStyle, EmblemColor, BorderStyle, BorderColor);
|
||||
m_TeamId, ArenaTeamName.c_str(), GUID_LOPART(m_CaptainGuid), m_Type, m_BackgroundColor, m_EmblemStyle, m_EmblemColor, m_BorderStyle, m_BorderColor);
|
||||
CharacterDatabase.PExecute("INSERT INTO arena_team_stats (arenateamid, rating, games, wins, played, wins2, rank) VALUES "
|
||||
"('%u', '%u', '%u', '%u', '%u', '%u', '%u')", Id, stats.rating, stats.games_week, stats.wins_week, stats.games_season, stats.wins_season, stats.rank);
|
||||
"('%u', '%u', '%u', '%u', '%u', '%u', '%u')", m_TeamId, m_stats.rating, m_stats.games_week, m_stats.wins_week, m_stats.games_season, m_stats.wins_season, m_stats.rank);
|
||||
|
||||
CharacterDatabase.CommitTransaction();
|
||||
|
||||
AddMember(CaptainGuid);
|
||||
AddMember(m_CaptainGuid);
|
||||
sLog.outArena("New ArenaTeam created [Id: %u] [Type: %u] [Captain GUID: %u]", GetId(), GetType(), GetCaptain());
|
||||
return true;
|
||||
}
|
||||
@@ -145,8 +145,8 @@ bool ArenaTeam::AddMember(const uint64& PlayerGuid)
|
||||
newmember.wins_week = 0;
|
||||
if (sWorld.getConfig(CONFIG_ARENA_SEASON_ID) >= 6)
|
||||
{
|
||||
if (stats.rating < 1000)
|
||||
newmember.personal_rating = stats.rating;
|
||||
if (m_stats.rating < 1000)
|
||||
newmember.personal_rating = m_stats.rating;
|
||||
else
|
||||
newmember.personal_rating = 1000;
|
||||
}
|
||||
@@ -154,18 +154,18 @@ bool ArenaTeam::AddMember(const uint64& PlayerGuid)
|
||||
{
|
||||
newmember.personal_rating = 1500;
|
||||
}
|
||||
members.push_back(newmember);
|
||||
m_members.push_back(newmember);
|
||||
|
||||
CharacterDatabase.PExecute("INSERT INTO arena_team_member (arenateamid, guid, personal_rating) VALUES ('%u', '%u', '%u')", Id, GUID_LOPART(newmember.guid), newmember.personal_rating );
|
||||
CharacterDatabase.PExecute("INSERT INTO arena_team_member (arenateamid, guid, personal_rating) VALUES ('%u', '%u', '%u')", m_TeamId, GUID_LOPART(newmember.guid), newmember.personal_rating );
|
||||
|
||||
if(pl)
|
||||
{
|
||||
pl->SetInArenaTeam(Id, GetSlot());
|
||||
pl->SetInArenaTeam(m_TeamId, GetSlot());
|
||||
pl->SetArenaTeamIdInvited(0);
|
||||
pl->SetUInt32Value(PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + (GetSlot()*6) + 5, newmember.personal_rating );
|
||||
|
||||
// hide promote/remove buttons
|
||||
if(CaptainGuid != PlayerGuid)
|
||||
if(m_CaptainGuid != PlayerGuid)
|
||||
pl->SetUInt32Value(PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + (GetSlot() * 6) + 1, 1);
|
||||
sLog.outArena("Player: %s [GUID: %u] joined arena team type: %u [Id: %u].", pl->GetName(), pl->GetGUIDLow(), GetType(), GetId());
|
||||
}
|
||||
@@ -181,15 +181,15 @@ bool ArenaTeam::LoadArenaTeamFromDB(uint32 ArenaTeamId)
|
||||
|
||||
Field *fields = result->Fetch();
|
||||
|
||||
Id = fields[0].GetUInt32();
|
||||
Name = fields[1].GetCppString();
|
||||
CaptainGuid = MAKE_NEW_GUID(fields[2].GetUInt32(), 0, HIGHGUID_PLAYER);
|
||||
Type = fields[3].GetUInt32();
|
||||
BackgroundColor = fields[4].GetUInt32();
|
||||
EmblemStyle = fields[5].GetUInt32();
|
||||
EmblemColor = fields[6].GetUInt32();
|
||||
BorderStyle = fields[7].GetUInt32();
|
||||
BorderColor = fields[8].GetUInt32();
|
||||
m_TeamId = fields[0].GetUInt32();
|
||||
m_Name = fields[1].GetCppString();
|
||||
m_CaptainGuid = MAKE_NEW_GUID(fields[2].GetUInt32(), 0, HIGHGUID_PLAYER);
|
||||
m_Type = fields[3].GetUInt32();
|
||||
m_BackgroundColor = fields[4].GetUInt32();
|
||||
m_EmblemStyle = fields[5].GetUInt32();
|
||||
m_EmblemColor = fields[6].GetUInt32();
|
||||
m_BorderStyle = fields[7].GetUInt32();
|
||||
m_BorderColor = fields[8].GetUInt32();
|
||||
|
||||
delete result;
|
||||
|
||||
@@ -221,12 +221,12 @@ void ArenaTeam::LoadStatsFromDB(uint32 ArenaTeamId)
|
||||
|
||||
Field *fields = result->Fetch();
|
||||
|
||||
stats.rating = fields[0].GetUInt32();
|
||||
stats.games_week = fields[1].GetUInt32();
|
||||
stats.wins_week = fields[2].GetUInt32();
|
||||
stats.games_season = fields[3].GetUInt32();
|
||||
stats.wins_season = fields[4].GetUInt32();
|
||||
stats.rank = fields[5].GetUInt32();
|
||||
m_stats.rating = fields[0].GetUInt32();
|
||||
m_stats.games_week = fields[1].GetUInt32();
|
||||
m_stats.wins_week = fields[2].GetUInt32();
|
||||
m_stats.games_season = fields[3].GetUInt32();
|
||||
m_stats.wins_season = fields[4].GetUInt32();
|
||||
m_stats.rank = fields[5].GetUInt32();
|
||||
|
||||
delete result;
|
||||
}
|
||||
@@ -253,7 +253,7 @@ void ArenaTeam::LoadMembersFromDB(uint32 ArenaTeamId)
|
||||
newmember.personal_rating = fields[5].GetUInt32();
|
||||
newmember.name = fields[6].GetCppString();
|
||||
newmember.Class = fields[7].GetUInt8();
|
||||
members.push_back(newmember);
|
||||
m_members.push_back(newmember);
|
||||
}while( result->NextRow() );
|
||||
delete result;
|
||||
}
|
||||
@@ -266,10 +266,10 @@ void ArenaTeam::SetCaptain(const uint64& guid)
|
||||
oldcaptain->SetUInt32Value(PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + 1 + (GetSlot() * 6), 1);
|
||||
|
||||
// set new captain
|
||||
CaptainGuid = guid;
|
||||
m_CaptainGuid = guid;
|
||||
|
||||
// update database
|
||||
CharacterDatabase.PExecute("UPDATE arena_team SET captainguid = '%u' WHERE arenateamid = '%u'", GUID_LOPART(guid), Id);
|
||||
CharacterDatabase.PExecute("UPDATE arena_team SET captainguid = '%u' WHERE arenateamid = '%u'", GUID_LOPART(guid), m_TeamId);
|
||||
|
||||
// enable remove/promote buttons
|
||||
Player *newcaptain = objmgr.GetPlayer(guid);
|
||||
@@ -282,11 +282,11 @@ void ArenaTeam::SetCaptain(const uint64& guid)
|
||||
|
||||
void ArenaTeam::DelMember(uint64 guid)
|
||||
{
|
||||
for (MemberList::iterator itr = members.begin(); itr != members.end(); ++itr)
|
||||
for (MemberList::iterator itr = m_members.begin(); itr != m_members.end(); ++itr)
|
||||
{
|
||||
if (itr->guid == guid)
|
||||
{
|
||||
members.erase(itr);
|
||||
m_members.erase(itr);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -314,21 +314,21 @@ void ArenaTeam::Disband(WorldSession *session)
|
||||
session->BuildArenaTeamEventPacket(&data, ERR_ARENA_TEAM_DISBANDED_S, 2, session->GetPlayerName(), GetName(), "");
|
||||
BroadcastPacket(&data);
|
||||
|
||||
while (!members.empty())
|
||||
while (!m_members.empty())
|
||||
{
|
||||
// Removing from members is done in DelMember.
|
||||
DelMember(members.front().guid);
|
||||
DelMember(m_members.front().guid);
|
||||
}
|
||||
|
||||
if(Player *player = session->GetPlayer())
|
||||
sLog.outArena("Player: %s [GUID: %u] disbanded arena team type: %u [Id: %u].", player->GetName(), player->GetGUIDLow(), GetType(), GetId());
|
||||
|
||||
CharacterDatabase.BeginTransaction();
|
||||
CharacterDatabase.PExecute("DELETE FROM arena_team WHERE arenateamid = '%u'", Id);
|
||||
CharacterDatabase.PExecute("DELETE FROM arena_team_member WHERE arenateamid = '%u'", Id); //< this should be alredy done by calling DelMember(memberGuids[j]); for each member
|
||||
CharacterDatabase.PExecute("DELETE FROM arena_team_stats WHERE arenateamid = '%u'", Id);
|
||||
CharacterDatabase.PExecute("DELETE FROM arena_team WHERE arenateamid = '%u'", m_TeamId);
|
||||
CharacterDatabase.PExecute("DELETE FROM arena_team_member WHERE arenateamid = '%u'", m_TeamId); //< this should be alredy done by calling DelMember(memberGuids[j]); for each member
|
||||
CharacterDatabase.PExecute("DELETE FROM arena_team_stats WHERE arenateamid = '%u'", m_TeamId);
|
||||
CharacterDatabase.CommitTransaction();
|
||||
objmgr.RemoveArenaTeam(Id);
|
||||
objmgr.RemoveArenaTeam(m_TeamId);
|
||||
}
|
||||
|
||||
void ArenaTeam::Roster(WorldSession *session)
|
||||
@@ -338,12 +338,12 @@ void ArenaTeam::Roster(WorldSession *session)
|
||||
uint8 unk308 = 0;
|
||||
|
||||
WorldPacket data(SMSG_ARENA_TEAM_ROSTER, 100);
|
||||
data << uint32(GetId()); // arena team id
|
||||
data << uint32(GetId()); // team id
|
||||
data << uint8(unk308); // 308 unknown value but affect packet structure
|
||||
data << uint32(GetMembersSize()); // members count
|
||||
data << uint32(GetType()); // arena team type?
|
||||
|
||||
for (MemberList::const_iterator itr = members.begin(); itr != members.end(); ++itr)
|
||||
for (MemberList::const_iterator itr = m_members.begin(); itr != m_members.end(); ++itr)
|
||||
{
|
||||
pl = objmgr.GetPlayer(itr->guid);
|
||||
|
||||
@@ -375,11 +375,11 @@ void ArenaTeam::Query(WorldSession *session)
|
||||
data << uint32(GetId()); // team id
|
||||
data << GetName(); // team name
|
||||
data << uint32(GetType()); // arena team type (2=2x2, 3=3x3 or 5=5x5)
|
||||
data << uint32(BackgroundColor); // background color
|
||||
data << uint32(EmblemStyle); // emblem style
|
||||
data << uint32(EmblemColor); // emblem color
|
||||
data << uint32(BorderStyle); // border style
|
||||
data << uint32(BorderColor); // border color
|
||||
data << uint32(m_BackgroundColor); // background color
|
||||
data << uint32(m_EmblemStyle); // emblem style
|
||||
data << uint32(m_EmblemColor); // emblem color
|
||||
data << uint32(m_BorderStyle); // border style
|
||||
data << uint32(m_BorderColor); // border color
|
||||
session->SendPacket(&data);
|
||||
sLog.outDebug("WORLD: Sent SMSG_ARENA_TEAM_QUERY_RESPONSE");
|
||||
}
|
||||
@@ -387,13 +387,13 @@ void ArenaTeam::Query(WorldSession *session)
|
||||
void ArenaTeam::Stats(WorldSession *session)
|
||||
{
|
||||
WorldPacket data(SMSG_ARENA_TEAM_STATS, 4*7);
|
||||
data << uint32(GetId()); // arena team id
|
||||
data << uint32(stats.rating); // rating
|
||||
data << uint32(stats.games_week); // games this week
|
||||
data << uint32(stats.wins_week); // wins this week
|
||||
data << uint32(stats.games_season); // played this season
|
||||
data << uint32(stats.wins_season); // wins this season
|
||||
data << uint32(stats.rank); // rank
|
||||
data << uint32(GetId()); // team id
|
||||
data << uint32(m_stats.rating); // rating
|
||||
data << uint32(m_stats.games_week); // games this week
|
||||
data << uint32(m_stats.wins_week); // wins this week
|
||||
data << uint32(m_stats.games_season); // played this season
|
||||
data << uint32(m_stats.wins_season); // wins this season
|
||||
data << uint32(m_stats.rank); // rank
|
||||
session->SendPacket(&data);
|
||||
}
|
||||
|
||||
@@ -401,7 +401,7 @@ void ArenaTeam::NotifyStatsChanged()
|
||||
{
|
||||
// this is called after a rated match ended
|
||||
// updates arena team stats for every member of the team (not only the ones who participated!)
|
||||
for(MemberList::const_iterator itr = members.begin(); itr != members.end(); ++itr)
|
||||
for(MemberList::const_iterator itr = m_members.begin(); itr != m_members.end(); ++itr)
|
||||
{
|
||||
Player * plr = objmgr.GetPlayer(itr->guid);
|
||||
if(plr)
|
||||
@@ -419,9 +419,9 @@ void ArenaTeam::InspectStats(WorldSession *session, uint64 guid)
|
||||
data << uint64(guid); // player guid
|
||||
data << uint8(GetSlot()); // slot (0...2)
|
||||
data << uint32(GetId()); // arena team id
|
||||
data << uint32(stats.rating); // rating
|
||||
data << uint32(stats.games_season); // season played
|
||||
data << uint32(stats.wins_season); // season wins
|
||||
data << uint32(m_stats.rating); // rating
|
||||
data << uint32(m_stats.games_season); // season played
|
||||
data << uint32(m_stats.wins_season); // season wins
|
||||
data << uint32(member->games_season); // played (count of all games, that the inspected member participated...)
|
||||
data << uint32(member->personal_rating); // personal rating
|
||||
session->SendPacket(&data);
|
||||
@@ -429,13 +429,13 @@ void ArenaTeam::InspectStats(WorldSession *session, uint64 guid)
|
||||
|
||||
void ArenaTeam::SetEmblem(uint32 backgroundColor, uint32 emblemStyle, uint32 emblemColor, uint32 borderStyle, uint32 borderColor)
|
||||
{
|
||||
BackgroundColor = backgroundColor;
|
||||
EmblemStyle = emblemStyle;
|
||||
EmblemColor = emblemColor;
|
||||
BorderStyle = borderStyle;
|
||||
BorderColor = borderColor;
|
||||
m_BackgroundColor = backgroundColor;
|
||||
m_EmblemStyle = emblemStyle;
|
||||
m_EmblemColor = emblemColor;
|
||||
m_BorderStyle = borderStyle;
|
||||
m_BorderColor = borderColor;
|
||||
|
||||
CharacterDatabase.PExecute("UPDATE arena_team SET BackgroundColor='%u', EmblemStyle='%u', EmblemColor='%u', BorderStyle='%u', BorderColor='%u' WHERE arenateamid='%u'", BackgroundColor, EmblemStyle, EmblemColor, BorderStyle, BorderColor, Id);
|
||||
CharacterDatabase.PExecute("UPDATE arena_team SET BackgroundColor='%u', EmblemStyle='%u', EmblemColor='%u', BorderStyle='%u', BorderColor='%u' WHERE arenateamid='%u'", m_BackgroundColor, m_EmblemStyle, m_EmblemColor, m_BorderStyle, m_BorderColor, m_TeamId);
|
||||
}
|
||||
|
||||
void ArenaTeam::SetStats(uint32 stat_type, uint32 value)
|
||||
@@ -443,27 +443,27 @@ void ArenaTeam::SetStats(uint32 stat_type, uint32 value)
|
||||
switch(stat_type)
|
||||
{
|
||||
case STAT_TYPE_RATING:
|
||||
stats.rating = value;
|
||||
m_stats.rating = value;
|
||||
CharacterDatabase.PExecute("UPDATE arena_team_stats SET rating = '%u' WHERE arenateamid = '%u'", value, GetId());
|
||||
break;
|
||||
case STAT_TYPE_GAMES_WEEK:
|
||||
stats.games_week = value;
|
||||
m_stats.games_week = value;
|
||||
CharacterDatabase.PExecute("UPDATE arena_team_stats SET games = '%u' WHERE arenateamid = '%u'", value, GetId());
|
||||
break;
|
||||
case STAT_TYPE_WINS_WEEK:
|
||||
stats.wins_week = value;
|
||||
m_stats.wins_week = value;
|
||||
CharacterDatabase.PExecute("UPDATE arena_team_stats SET wins = '%u' WHERE arenateamid = '%u'", value, GetId());
|
||||
break;
|
||||
case STAT_TYPE_GAMES_SEASON:
|
||||
stats.games_season = value;
|
||||
m_stats.games_season = value;
|
||||
CharacterDatabase.PExecute("UPDATE arena_team_stats SET played = '%u' WHERE arenateamid = '%u'", value, GetId());
|
||||
break;
|
||||
case STAT_TYPE_WINS_SEASON:
|
||||
stats.wins_season = value;
|
||||
m_stats.wins_season = value;
|
||||
CharacterDatabase.PExecute("UPDATE arena_team_stats SET wins2 = '%u' WHERE arenateamid = '%u'", value, GetId());
|
||||
break;
|
||||
case STAT_TYPE_RANK:
|
||||
stats.rank = value;
|
||||
m_stats.rank = value;
|
||||
CharacterDatabase.PExecute("UPDATE arena_team_stats SET rank = '%u' WHERE arenateamid = '%u'", value, GetId());
|
||||
break;
|
||||
default:
|
||||
@@ -474,7 +474,7 @@ void ArenaTeam::SetStats(uint32 stat_type, uint32 value)
|
||||
|
||||
void ArenaTeam::BroadcastPacket(WorldPacket *packet)
|
||||
{
|
||||
for (MemberList::const_iterator itr = members.begin(); itr != members.end(); ++itr)
|
||||
for (MemberList::const_iterator itr = m_members.begin(); itr != m_members.end(); ++itr)
|
||||
{
|
||||
Player *player = objmgr.GetPlayer(itr->guid);
|
||||
if(player)
|
||||
@@ -498,7 +498,7 @@ uint8 ArenaTeam::GetSlotByType( uint32 type )
|
||||
|
||||
bool ArenaTeam::HaveMember( const uint64& guid ) const
|
||||
{
|
||||
for (MemberList::const_iterator itr = members.begin(); itr != members.end(); ++itr)
|
||||
for (MemberList::const_iterator itr = m_members.begin(); itr != m_members.end(); ++itr)
|
||||
if(itr->guid == guid)
|
||||
return true;
|
||||
|
||||
@@ -510,7 +510,7 @@ uint32 ArenaTeam::GetPoints(uint32 MemberRating)
|
||||
// returns how many points would be awarded with this team type with this rating
|
||||
float points;
|
||||
|
||||
uint32 rating = MemberRating + 150 < stats.rating ? MemberRating : stats.rating;
|
||||
uint32 rating = MemberRating + 150 < m_stats.rating ? MemberRating : m_stats.rating;
|
||||
|
||||
if(rating<=1500)
|
||||
// points = (float)1500 * 0.22f + 14.0f;
|
||||
@@ -519,9 +519,9 @@ uint32 ArenaTeam::GetPoints(uint32 MemberRating)
|
||||
points = 1511.26f / (1.0f + 1639.28f * exp(-0.00412f * (float)rating));
|
||||
|
||||
// type penalties for <5v5 teams
|
||||
if(Type == ARENA_TEAM_2v2)
|
||||
if(m_Type == ARENA_TEAM_2v2)
|
||||
points *= 0.76f;
|
||||
else if(Type == ARENA_TEAM_3v3)
|
||||
else if(m_Type == ARENA_TEAM_3v3)
|
||||
points *= 0.88f;
|
||||
|
||||
return (uint32) points;
|
||||
@@ -535,26 +535,25 @@ float ArenaTeam::GetChanceAgainst(uint32 own_rating, uint32 enemy_rating)
|
||||
if (sWorld.getConfig(CONFIG_ARENA_SEASON_ID) >= 6)
|
||||
if (enemy_rating < 1300)
|
||||
enemy_rating = 1300;
|
||||
|
||||
return 1.0f/(1.0f+exp(log(10.0f)*(float)((float)enemy_rating - (float)own_rating)/400.0f));
|
||||
}
|
||||
|
||||
void ArenaTeam::FinishGame(int32 mod)
|
||||
{
|
||||
if (int32(stats.rating) + mod < 0)
|
||||
stats.rating = 0;
|
||||
if (int32(m_stats.rating) + mod < 0)
|
||||
m_stats.rating = 0;
|
||||
else
|
||||
stats.rating += mod;
|
||||
m_stats.rating += mod;
|
||||
|
||||
stats.games_week += 1;
|
||||
stats.games_season += 1;
|
||||
m_stats.games_week += 1;
|
||||
m_stats.games_season += 1;
|
||||
// update team's rank
|
||||
stats.rank = 1;
|
||||
m_stats.rank = 1;
|
||||
ObjectMgr::ArenaTeamMap::const_iterator i = objmgr.GetArenaTeamMapBegin();
|
||||
for ( ; i != objmgr.GetArenaTeamMapEnd(); ++i)
|
||||
{
|
||||
if (i->second->GetType() == this->Type && i->second->GetStats().rating > stats.rating)
|
||||
++stats.rank;
|
||||
if (i->second->GetType() == m_Type && i->second->GetStats().rating > m_stats.rating)
|
||||
++m_stats.rank;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -562,13 +561,13 @@ int32 ArenaTeam::WonAgainst(uint32 againstRating)
|
||||
{
|
||||
// called when the team has won
|
||||
//'chance' calculation - to beat the opponent
|
||||
float chance = GetChanceAgainst(stats.rating, againstRating);
|
||||
float chance = GetChanceAgainst(m_stats.rating, againstRating);
|
||||
// calculate the rating modification (ELO system with k=32)
|
||||
int32 mod = (int32)floor(32.0f * (1.0f - chance));
|
||||
// modify the team stats accordingly
|
||||
FinishGame(mod);
|
||||
stats.wins_week += 1;
|
||||
stats.wins_season += 1;
|
||||
m_stats.wins_week += 1;
|
||||
m_stats.wins_season += 1;
|
||||
|
||||
// return the rating change, used to display it on the results screen
|
||||
return mod;
|
||||
@@ -578,7 +577,7 @@ int32 ArenaTeam::LostAgainst(uint32 againstRating)
|
||||
{
|
||||
// called when the team has lost
|
||||
//'chance' calculation - to loose to the opponent
|
||||
float chance = GetChanceAgainst(stats.rating, againstRating);
|
||||
float chance = GetChanceAgainst(m_stats.rating, againstRating);
|
||||
// calculate the rating modification (ELO system with k=32)
|
||||
int32 mod = (int32)ceil(32.0f * (0.0f - chance));
|
||||
// modify the team stats accordingly
|
||||
@@ -591,7 +590,7 @@ int32 ArenaTeam::LostAgainst(uint32 againstRating)
|
||||
void ArenaTeam::MemberLost(Player * plr, uint32 againstRating)
|
||||
{
|
||||
// called for each participant of a match after losing
|
||||
for(MemberList::iterator itr = members.begin(); itr != members.end(); ++itr)
|
||||
for(MemberList::iterator itr = m_members.begin(); itr != m_members.end(); ++itr)
|
||||
{
|
||||
if(itr->guid == plr->GetGUID())
|
||||
{
|
||||
@@ -613,7 +612,7 @@ 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)
|
||||
for(MemberList::iterator itr = m_members.begin(); itr != m_members.end(); ++itr)
|
||||
{
|
||||
if(itr->guid == guid)
|
||||
{
|
||||
@@ -635,7 +634,7 @@ void ArenaTeam::OfflineMemberLost(uint64 guid, uint32 againstRating)
|
||||
void ArenaTeam::MemberWon(Player * plr, uint32 againstRating)
|
||||
{
|
||||
// called for each participant after winning a match
|
||||
for(MemberList::iterator itr = members.begin(); itr != members.end(); ++itr)
|
||||
for(MemberList::iterator itr = m_members.begin(); itr != m_members.end(); ++itr)
|
||||
{
|
||||
if(itr->guid == plr->GetGUID())
|
||||
{
|
||||
@@ -661,17 +660,17 @@ void ArenaTeam::UpdateArenaPointsHelper(std::map<uint32, uint32>& PlayerPoints)
|
||||
// called after a match has ended and the stats are already modified
|
||||
// helper function for arena point distribution (this way, when distributing, no actual calculation is required, just a few comparisons)
|
||||
// 10 played games per week is a minimum
|
||||
if (stats.games_week < 10)
|
||||
if (m_stats.games_week < 10)
|
||||
return;
|
||||
// to get points, a player has to participate in at least 30% of the matches
|
||||
uint32 min_plays = (uint32) ceil(stats.games_week * 0.3);
|
||||
for(MemberList::const_iterator itr = members.begin(); itr != members.end(); ++itr)
|
||||
uint32 min_plays = (uint32) ceil(m_stats.games_week * 0.3);
|
||||
for(MemberList::const_iterator itr = m_members.begin(); itr != m_members.end(); ++itr)
|
||||
{
|
||||
// the player participated in enough games, update his points
|
||||
uint32 points_to_add = 0;
|
||||
if (itr->games_week >= min_plays)
|
||||
points_to_add = GetPoints(itr->personal_rating);
|
||||
// OBSOLETE : CharacterDatabase.PExecute("UPDATE arena_team_member SET points_to_add = '%u' WHERE arenateamid = '%u' AND guid = '%u'", points_to_add, Id, itr->guid);
|
||||
// OBSOLETE : CharacterDatabase.PExecute("UPDATE arena_team_member SET points_to_add = '%u' WHERE arenateamid = '%u' AND guid = '%u'", points_to_add, m_TeamId, itr->guid);
|
||||
|
||||
std::map<uint32, uint32>::iterator plr_itr = PlayerPoints.find(GUID_LOPART(itr->guid));
|
||||
if (plr_itr != PlayerPoints.end())
|
||||
@@ -690,19 +689,19 @@ void ArenaTeam::SaveToDB()
|
||||
// save team and member stats to db
|
||||
// called after a match has ended, or when calculating arena_points
|
||||
CharacterDatabase.BeginTransaction();
|
||||
CharacterDatabase.PExecute("UPDATE arena_team_stats SET rating = '%u',games = '%u',played = '%u',rank = '%u',wins = '%u',wins2 = '%u' WHERE arenateamid = '%u'", stats.rating, stats.games_week, stats.games_season, stats.rank, stats.wins_week, stats.wins_season, GetId());
|
||||
for(MemberList::const_iterator itr = members.begin(); itr != members.end(); ++itr)
|
||||
CharacterDatabase.PExecute("UPDATE arena_team_stats SET rating = '%u',games = '%u',played = '%u',rank = '%u',wins = '%u',wins2 = '%u' WHERE arenateamid = '%u'", m_stats.rating, m_stats.games_week, m_stats.games_season, m_stats.rank, m_stats.wins_week, m_stats.wins_season, GetId());
|
||||
for(MemberList::const_iterator itr = m_members.begin(); itr != m_members.end(); ++itr)
|
||||
{
|
||||
CharacterDatabase.PExecute("UPDATE arena_team_member SET played_week = '%u', wons_week = '%u', played_season = '%u', wons_season = '%u', personal_rating = '%u' WHERE arenateamid = '%u' AND guid = '%u'", itr->games_week, itr->wins_week, itr->games_season, itr->wins_season, itr->personal_rating, Id, GUID_LOPART(itr->guid));
|
||||
CharacterDatabase.PExecute("UPDATE arena_team_member SET played_week = '%u', wons_week = '%u', played_season = '%u', wons_season = '%u', personal_rating = '%u' WHERE arenateamid = '%u' AND guid = '%u'", itr->games_week, itr->wins_week, itr->games_season, itr->wins_season, itr->personal_rating, m_TeamId, GUID_LOPART(itr->guid));
|
||||
}
|
||||
CharacterDatabase.CommitTransaction();
|
||||
}
|
||||
|
||||
void ArenaTeam::FinishWeek()
|
||||
{
|
||||
stats.games_week = 0; // played this week
|
||||
stats.wins_week = 0; // wins this week
|
||||
for(MemberList::iterator itr = members.begin(); itr != members.end(); ++itr)
|
||||
m_stats.games_week = 0; // played this week
|
||||
m_stats.wins_week = 0; // wins this week
|
||||
for(MemberList::iterator itr = m_members.begin(); itr != m_members.end(); ++itr)
|
||||
{
|
||||
itr->games_week = 0;
|
||||
itr->wins_week = 0;
|
||||
@@ -711,7 +710,7 @@ void ArenaTeam::FinishWeek()
|
||||
|
||||
bool ArenaTeam::IsFighting() const
|
||||
{
|
||||
for (MemberList::const_iterator itr = members.begin(); itr != members.end(); ++itr)
|
||||
for (MemberList::const_iterator itr = m_members.begin(); itr != m_members.end(); ++itr)
|
||||
{
|
||||
if (Player *p = objmgr.GetPlayer(itr->guid))
|
||||
{
|
||||
|
||||
+29
-29
@@ -117,26 +117,26 @@ class ArenaTeam
|
||||
ArenaTeam();
|
||||
~ArenaTeam();
|
||||
|
||||
bool Create(uint64 CaptainGuid, uint32 type, std::string ArenaTeamName);
|
||||
bool Create(uint64 captainGuid, uint32 type, std::string ArenaTeamName);
|
||||
void Disband(WorldSession *session);
|
||||
|
||||
typedef std::list<ArenaTeamMember> MemberList;
|
||||
|
||||
uint32 GetId() const { return Id; }
|
||||
uint32 GetType() const { return Type; }
|
||||
uint32 GetId() const { return m_TeamId; }
|
||||
uint32 GetType() const { return m_Type; }
|
||||
uint8 GetSlot() const { return GetSlotByType(GetType()); }
|
||||
static uint8 GetSlotByType(uint32 type);
|
||||
const uint64& GetCaptain() const { return CaptainGuid; }
|
||||
std::string GetName() const { return Name; }
|
||||
const ArenaTeamStats& GetStats() const { return stats; }
|
||||
const uint64& GetCaptain() const { return m_CaptainGuid; }
|
||||
std::string GetName() const { return m_Name; }
|
||||
const ArenaTeamStats& GetStats() const { return m_stats; }
|
||||
void SetStats(uint32 stat_type, uint32 value);
|
||||
uint32 GetRating() const { return stats.rating; }
|
||||
uint32 GetRating() const { return m_stats.rating; }
|
||||
|
||||
uint32 GetEmblemStyle() const { return EmblemStyle; }
|
||||
uint32 GetEmblemColor() const { return EmblemColor; }
|
||||
uint32 GetBorderStyle() const { return BorderStyle; }
|
||||
uint32 GetBorderColor() const { return BorderColor; }
|
||||
uint32 GetBackgroundColor() const { return BackgroundColor; }
|
||||
uint32 GetEmblemStyle() const { return m_EmblemStyle; }
|
||||
uint32 GetEmblemColor() const { return m_EmblemColor; }
|
||||
uint32 GetBorderStyle() const { return m_BorderStyle; }
|
||||
uint32 GetBorderColor() const { return m_BorderColor; }
|
||||
uint32 GetBackgroundColor() const { return m_BackgroundColor; }
|
||||
|
||||
void SetCaptain(const uint64& guid);
|
||||
bool AddMember(const uint64& PlayerGuid);
|
||||
@@ -147,15 +147,15 @@ class ArenaTeam
|
||||
|
||||
void SetEmblem(uint32 backgroundColor, uint32 emblemStyle, uint32 emblemColor, uint32 borderStyle, uint32 borderColor);
|
||||
|
||||
size_t GetMembersSize() const { return members.size(); }
|
||||
bool Empty() const { return members.empty(); }
|
||||
MemberList::iterator membersBegin() { return members.begin(); }
|
||||
MemberList::iterator membersEnd() { return members.end(); }
|
||||
size_t GetMembersSize() const { return m_members.size(); }
|
||||
bool Empty() const { return m_members.empty(); }
|
||||
MemberList::iterator m_membersBegin() { return m_members.begin(); }
|
||||
MemberList::iterator m_membersEnd() { return m_members.end(); }
|
||||
bool HaveMember(const uint64& guid) const;
|
||||
|
||||
ArenaTeamMember* GetMember(const uint64& guid)
|
||||
{
|
||||
for (MemberList::iterator itr = members.begin(); itr != members.end(); ++itr)
|
||||
for (MemberList::iterator itr = m_members.begin(); itr != m_members.end(); ++itr)
|
||||
if(itr->guid == guid)
|
||||
return &(*itr);
|
||||
|
||||
@@ -164,7 +164,7 @@ class ArenaTeam
|
||||
|
||||
ArenaTeamMember* GetMember(const std::string& name)
|
||||
{
|
||||
for (MemberList::iterator itr = members.begin(); itr != members.end(); ++itr)
|
||||
for (MemberList::iterator itr = m_members.begin(); itr != m_members.end(); ++itr)
|
||||
if(itr->name == name)
|
||||
return &(*itr);
|
||||
|
||||
@@ -203,19 +203,19 @@ class ArenaTeam
|
||||
|
||||
protected:
|
||||
|
||||
uint32 Id;
|
||||
uint32 Type;
|
||||
std::string Name;
|
||||
uint64 CaptainGuid;
|
||||
uint32 m_TeamId;
|
||||
uint32 m_Type;
|
||||
std::string m_Name;
|
||||
uint64 m_CaptainGuid;
|
||||
|
||||
uint32 BackgroundColor; // ARGB format
|
||||
uint32 EmblemStyle; // icon id
|
||||
uint32 EmblemColor; // ARGB format
|
||||
uint32 BorderStyle; // border image id
|
||||
uint32 BorderColor; // ARGB format
|
||||
uint32 m_BackgroundColor; // ARGB format
|
||||
uint32 m_EmblemStyle; // icon id
|
||||
uint32 m_EmblemColor; // ARGB format
|
||||
uint32 m_BorderStyle; // border image id
|
||||
uint32 m_BorderColor; // ARGB format
|
||||
|
||||
MemberList members;
|
||||
ArenaTeamStats stats;
|
||||
MemberList m_members;
|
||||
ArenaTeamStats m_stats;
|
||||
};
|
||||
#endif
|
||||
|
||||
|
||||
@@ -182,6 +182,9 @@ BattleGround::BattleGround()
|
||||
m_PlayersCount[BG_TEAM_ALLIANCE] = 0;
|
||||
m_PlayersCount[BG_TEAM_HORDE] = 0;
|
||||
|
||||
m_TeamScores[BG_TEAM_ALLIANCE] = 0;
|
||||
m_TeamScores[BG_TEAM_HORDE] = 0;
|
||||
|
||||
m_PrematureCountDown = false;
|
||||
m_PrematureCountDown = 0;
|
||||
|
||||
@@ -473,7 +476,7 @@ void BattleGround::Update(uint32 diff)
|
||||
|
||||
void BattleGround::SetTeamStartLoc(uint32 TeamID, float X, float Y, float Z, float O)
|
||||
{
|
||||
uint8 idx = GetTeamIndexByTeamId(TeamID);
|
||||
BattleGroundTeamId idx = GetTeamIndexByTeamId(TeamID);
|
||||
m_TeamStartLocX[idx] = X;
|
||||
m_TeamStartLocY[idx] = Y;
|
||||
m_TeamStartLocZ[idx] = Z;
|
||||
@@ -1875,3 +1878,9 @@ WorldSafeLocsEntry const* BattleGround::GetClosestGraveYard( Player* player )
|
||||
{
|
||||
return objmgr.GetClosestGraveYard( player->GetPositionX(), player->GetPositionY(), player->GetPositionZ(), player->GetMapId(), player->GetTeam() );
|
||||
}
|
||||
|
||||
bool BattleGround::IsTeamScoreInRange(uint32 team, uint32 minScore, uint32 maxScore) const
|
||||
{
|
||||
BattleGroundTeamId team_idx = GetTeamIndexByTeamId(team);
|
||||
return m_TeamScores[team_idx] >= minScore && m_TeamScores[team_idx] <= maxScore;
|
||||
}
|
||||
|
||||
@@ -298,6 +298,10 @@ class BattleGround
|
||||
virtual void StartingEventCloseDoors() {}
|
||||
virtual void StartingEventOpenDoors() {}
|
||||
|
||||
/* achievement req. */
|
||||
virtual bool IsAllNodesConrolledByTeam(uint32 /*team*/) const { return false; }
|
||||
bool IsTeamScoreInRange(uint32 team, uint32 minScore, uint32 maxScore) const;
|
||||
|
||||
/* Battleground */
|
||||
// Get methods:
|
||||
char const* GetName() const { return m_Name; }
|
||||
@@ -397,7 +401,7 @@ class BattleGround
|
||||
void SetTeamStartLoc(uint32 TeamID, float X, float Y, float Z, float O);
|
||||
void GetTeamStartLoc(uint32 TeamID, float &X, float &Y, float &Z, float &O) const
|
||||
{
|
||||
uint8 idx = GetTeamIndexByTeamId(TeamID);
|
||||
BattleGroundTeamId idx = GetTeamIndexByTeamId(TeamID);
|
||||
X = m_TeamStartLocX[idx];
|
||||
Y = m_TeamStartLocY[idx];
|
||||
Z = m_TeamStartLocZ[idx];
|
||||
@@ -441,7 +445,7 @@ class BattleGround
|
||||
|
||||
virtual void UpdatePlayerScore(Player *Source, uint32 type, uint32 value);
|
||||
|
||||
uint8 GetTeamIndexByTeamId(uint32 Team) const { return Team == ALLIANCE ? BG_TEAM_ALLIANCE : BG_TEAM_HORDE; }
|
||||
static BattleGroundTeamId GetTeamIndexByTeamId(uint32 Team) { return Team == ALLIANCE ? BG_TEAM_ALLIANCE : BG_TEAM_HORDE; }
|
||||
uint32 GetPlayersCountByTeam(uint32 Team) const { return m_PlayersCount[GetTeamIndexByTeamId(Team)]; }
|
||||
uint32 GetAlivePlayersCountByTeam(uint32 Team) const; // used in arenas to correctly handle death in spirit of redemption / last stand etc. (killer = killed) cases
|
||||
void UpdatePlayersCountByTeam(uint32 Team, bool remove)
|
||||
@@ -514,6 +518,9 @@ class BattleGround
|
||||
|
||||
void SetDeleteThis() {m_SetDeleteThis = true;}
|
||||
|
||||
/* virtual score-array - get's used in bg-subclasses */
|
||||
int32 m_TeamScores[BG_TEAMS_COUNT];
|
||||
|
||||
protected:
|
||||
//this method is called, when BG cannot spawn its own spirit guide, or something is wrong, It correctly ends BattleGround
|
||||
void EndNow();
|
||||
|
||||
@@ -161,6 +161,18 @@ void BattleGroundAB::Update(uint32 diff)
|
||||
}
|
||||
}
|
||||
|
||||
// achievements flags
|
||||
if (m_TeamScores[BG_TEAM_ALLIANCE] > m_TeamScores[BG_TEAM_HORDE])
|
||||
{
|
||||
if (m_TeamScores[BG_TEAM_ALLIANCE] - m_TeamScores[BG_TEAM_HORDE] >= 500)
|
||||
m_TeamScores500disadvantage[BG_TEAM_HORDE] = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (m_TeamScores[BG_TEAM_HORDE] - m_TeamScores[BG_TEAM_ALLIANCE] >= 500)
|
||||
m_TeamScores500disadvantage[BG_TEAM_ALLIANCE] = true;
|
||||
}
|
||||
|
||||
// Test win condition
|
||||
if (m_TeamScores[BG_TEAM_ALLIANCE] >= BG_AB_MAX_TEAM_SCORE)
|
||||
EndBattleGround(ALLIANCE);
|
||||
@@ -428,7 +440,7 @@ void BattleGroundAB::EventPlayerClickedOnFlag(Player *source, GameObject* /*targ
|
||||
return;
|
||||
}
|
||||
|
||||
uint8 teamIndex = GetTeamIndexByTeamId(source->GetTeam());
|
||||
BattleGroundTeamId teamIndex = GetTeamIndexByTeamId(source->GetTeam());
|
||||
|
||||
// Check if player really could use this banner, not cheated
|
||||
if (!(m_Nodes[node] == 0 || teamIndex == m_Nodes[node]%2))
|
||||
@@ -474,7 +486,7 @@ void BattleGroundAB::EventPlayerClickedOnFlag(Player *source, GameObject* /*targ
|
||||
m_NodeTimers[node] = BG_AB_FLAG_CAPTURING_TIME;
|
||||
|
||||
// FIXME: node names not localized
|
||||
if (teamIndex == 0)
|
||||
if (teamIndex == BG_TEAM_ALLIANCE)
|
||||
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));
|
||||
@@ -491,15 +503,15 @@ void BattleGroundAB::EventPlayerClickedOnFlag(Player *source, GameObject* /*targ
|
||||
_CreateBanner(node, BG_AB_NODE_TYPE_OCCUPIED, teamIndex, true);
|
||||
_SendNodeUpdate(node);
|
||||
m_NodeTimers[node] = 0;
|
||||
_NodeOccupied(node,(teamIndex == 0) ? ALLIANCE:HORDE);
|
||||
_NodeOccupied(node,(teamIndex == BG_TEAM_ALLIANCE) ? ALLIANCE:HORDE);
|
||||
|
||||
// FIXME: node names not localized
|
||||
if (teamIndex == 0)
|
||||
if (teamIndex == BG_TEAM_ALLIANCE)
|
||||
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) ? BG_AB_SOUND_NODE_ASSAULTED_ALLIANCE : BG_AB_SOUND_NODE_ASSAULTED_HORDE;
|
||||
sound = (teamIndex == BG_TEAM_ALLIANCE) ? BG_AB_SOUND_NODE_ASSAULTED_ALLIANCE : BG_AB_SOUND_NODE_ASSAULTED_HORDE;
|
||||
}
|
||||
// If node is occupied, change to enemy-contested
|
||||
else
|
||||
@@ -516,19 +528,19 @@ void BattleGroundAB::EventPlayerClickedOnFlag(Player *source, GameObject* /*targ
|
||||
m_NodeTimers[node] = BG_AB_FLAG_CAPTURING_TIME;
|
||||
|
||||
// FIXME: node names not localized
|
||||
if (teamIndex == 0)
|
||||
if (teamIndex == BG_TEAM_ALLIANCE)
|
||||
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) ? BG_AB_SOUND_NODE_ASSAULTED_ALLIANCE : BG_AB_SOUND_NODE_ASSAULTED_HORDE;
|
||||
sound = (teamIndex == BG_TEAM_ALLIANCE) ? BG_AB_SOUND_NODE_ASSAULTED_ALLIANCE : BG_AB_SOUND_NODE_ASSAULTED_HORDE;
|
||||
}
|
||||
|
||||
// If node is occupied again, send "X has taken the Y" msg.
|
||||
if (m_Nodes[node] >= BG_AB_NODE_TYPE_OCCUPIED)
|
||||
{
|
||||
// FIXME: team and node names not localized
|
||||
if (teamIndex == 0)
|
||||
if (teamIndex == BG_TEAM_ALLIANCE)
|
||||
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));
|
||||
@@ -591,6 +603,8 @@ void BattleGroundAB::Reset()
|
||||
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;
|
||||
m_TeamScores500disadvantage[BG_TEAM_ALLIANCE] = false;
|
||||
m_TeamScores500disadvantage[BG_TEAM_HORDE] = false;
|
||||
|
||||
for (uint8 i = 0; i < BG_AB_DYNAMIC_NODES_COUNT; ++i)
|
||||
{
|
||||
@@ -621,7 +635,7 @@ void BattleGroundAB::EndBattleGround(uint32 winner)
|
||||
|
||||
WorldSafeLocsEntry const* BattleGroundAB::GetClosestGraveYard(Player* player)
|
||||
{
|
||||
uint8 teamIndex = GetTeamIndexByTeamId(player->GetTeam());
|
||||
BattleGroundTeamId teamIndex = GetTeamIndexByTeamId(player->GetTeam());
|
||||
|
||||
// Is there any occupied node for this team?
|
||||
std::vector<uint8> nodes;
|
||||
@@ -679,3 +693,13 @@ void BattleGroundAB::UpdatePlayerScore(Player *Source, uint32 type, uint32 value
|
||||
}
|
||||
}
|
||||
|
||||
bool BattleGroundAB::IsAllNodesConrolledByTeam(uint32 team) const
|
||||
{
|
||||
uint32 count = 0;
|
||||
for(int i = 0; i < BG_AB_DYNAMIC_NODES_COUNT; ++i)
|
||||
if (team == ALLIANCE && m_Nodes[i] == BG_AB_NODE_STATUS_ALLY_OCCUPIED ||
|
||||
team == HORDE && m_Nodes[i] == BG_AB_NODE_STATUS_HORDE_OCCUPIED)
|
||||
++count;
|
||||
|
||||
return count == BG_AB_DYNAMIC_NODES_COUNT;
|
||||
}
|
||||
|
||||
@@ -262,6 +262,9 @@ class BattleGroundAB : public BattleGround
|
||||
/* Nodes occupying */
|
||||
virtual void EventPlayerClickedOnFlag(Player *source, GameObject* target_obj);
|
||||
|
||||
/* achievement req. */
|
||||
bool IsAllNodesConrolledByTeam(uint32 team) const; // overwrited
|
||||
bool IsTeamScores500disadvantage(uint32 team) const { return m_TeamScores500disadvantage[GetTeamIndexByTeamId(team)]; }
|
||||
private:
|
||||
/* Gameobject spawning/despawning */
|
||||
void _CreateBanner(uint8 node, uint8 type, uint8 teamIndex, bool delay);
|
||||
@@ -285,15 +288,14 @@ class BattleGroundAB : public BattleGround
|
||||
uint8 m_prevNodes[BG_AB_DYNAMIC_NODES_COUNT];
|
||||
BG_AB_BannerTimer m_BannerTimers[BG_AB_DYNAMIC_NODES_COUNT];
|
||||
uint32 m_NodeTimers[BG_AB_DYNAMIC_NODES_COUNT];
|
||||
uint32 m_TeamScores[BG_TEAMS_COUNT];
|
||||
uint32 m_lastTick[BG_TEAMS_COUNT];
|
||||
uint32 m_HonorScoreTics[BG_TEAMS_COUNT];
|
||||
uint32 m_ReputationScoreTics[BG_TEAMS_COUNT];
|
||||
bool m_IsInformedNearVictory;
|
||||
uint32 m_HonorTics;
|
||||
uint32 m_ReputationTics;
|
||||
|
||||
|
||||
// need for achievements
|
||||
bool m_TeamScores500disadvantage[BG_TEAMS_COUNT];
|
||||
};
|
||||
#endif
|
||||
|
||||
|
||||
@@ -128,7 +128,7 @@ void BattleGroundEY::StartingEventOpenDoors()
|
||||
|
||||
void BattleGroundEY::AddPoints(uint32 Team, uint32 Points)
|
||||
{
|
||||
uint8 team_index = GetTeamIndexByTeamId(Team);
|
||||
BattleGroundTeamId team_index = GetTeamIndexByTeamId(Team);
|
||||
m_TeamScores[team_index] += Points;
|
||||
m_HonorScoreTics[team_index] += Points;
|
||||
if (m_HonorScoreTics[team_index] >= m_HonorTics )
|
||||
@@ -908,3 +908,12 @@ WorldSafeLocsEntry const *BattleGroundEY::GetClosestGraveYard(Player* player)
|
||||
return nearestEntry;
|
||||
}
|
||||
|
||||
bool BattleGroundEY::IsAllNodesConrolledByTeam(uint32 team) const
|
||||
{
|
||||
uint32 count = 0;
|
||||
for(int i = 0; i < EY_POINTS_MAX; ++i)
|
||||
if (m_PointOwnedByTeam[i] == team && m_PointState[i] == EY_POINT_UNDER_CONTROL)
|
||||
++count;
|
||||
|
||||
return count == EY_POINTS_MAX;
|
||||
}
|
||||
|
||||
@@ -350,6 +350,8 @@ class BattleGroundEY : public BattleGround
|
||||
virtual void EventPlayerClickedOnFlag(Player *Source, GameObject* target_obj);
|
||||
virtual void EventPlayerDroppedFlag(Player *Source);
|
||||
|
||||
/* achievement req. */
|
||||
bool IsAllNodesConrolledByTeam(uint32 team) const;
|
||||
private:
|
||||
void EventPlayerCapturedFlag(Player *Source, uint32 BgObjectType);
|
||||
void EventTeamCapturedPoint(Player *Source, uint32 Point);
|
||||
@@ -369,7 +371,6 @@ class BattleGroundEY : public BattleGround
|
||||
void RemovePoint(uint32 TeamID, uint32 Points = 1) { m_TeamScores[GetTeamIndexByTeamId(TeamID)] -= Points; }
|
||||
void SetTeamPoint(uint32 TeamID, uint32 Points = 0) { m_TeamScores[GetTeamIndexByTeamId(TeamID)] = Points; }
|
||||
|
||||
uint32 m_TeamScores[2];
|
||||
uint32 m_HonorScoreTics[2];
|
||||
uint32 m_TeamPointsCount[2];
|
||||
|
||||
|
||||
@@ -200,12 +200,10 @@ class BattleGroundWS : public BattleGround
|
||||
void AddPoint(uint32 TeamID, uint32 Points = 1) { m_TeamScores[GetTeamIndexByTeamId(TeamID)] += Points; }
|
||||
void SetTeamPoint(uint32 TeamID, uint32 Points = 0) { m_TeamScores[GetTeamIndexByTeamId(TeamID)] = Points; }
|
||||
void RemovePoint(uint32 TeamID, uint32 Points = 1) { m_TeamScores[GetTeamIndexByTeamId(TeamID)] -= Points; }
|
||||
|
||||
private:
|
||||
uint64 m_FlagKeepers[2]; // 0 - alliance, 1 - horde
|
||||
uint64 m_DroppedFlagGUID[2];
|
||||
uint8 m_FlagState[2]; // for checking flag state
|
||||
uint32 m_TeamScores[2];
|
||||
int32 m_FlagsTimer[2];
|
||||
int32 m_FlagsDropTimer[2];
|
||||
|
||||
|
||||
@@ -24,9 +24,6 @@
|
||||
#include "ObjectMgr.h" // for normalizePlayerName
|
||||
#include "ChannelMgr.h"
|
||||
|
||||
INSTANTIATE_SINGLETON_1( AllianceChannelMgr );
|
||||
INSTANTIATE_SINGLETON_1( HordeChannelMgr );
|
||||
|
||||
void WorldSession::HandleJoinChannel(WorldPacket& recvPacket)
|
||||
{
|
||||
sLog.outDebug("Opcode %u", recvPacket.GetOpcode());
|
||||
|
||||
@@ -0,0 +1,97 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "ChannelMgr.h"
|
||||
#include "Policies/SingletonImp.h"
|
||||
#include "World.h"
|
||||
|
||||
INSTANTIATE_SINGLETON_1( AllianceChannelMgr );
|
||||
INSTANTIATE_SINGLETON_1( HordeChannelMgr );
|
||||
|
||||
ChannelMgr* channelMgr(uint32 team)
|
||||
{
|
||||
if (sWorld.getConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_CHANNEL))
|
||||
return &MaNGOS::Singleton<AllianceChannelMgr>::Instance(); // cross-faction
|
||||
|
||||
if(team == ALLIANCE)
|
||||
return &MaNGOS::Singleton<AllianceChannelMgr>::Instance();
|
||||
if(team == HORDE)
|
||||
return &MaNGOS::Singleton<HordeChannelMgr>::Instance();
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ChannelMgr::~ChannelMgr()
|
||||
{
|
||||
for(ChannelMap::iterator itr = channels.begin();itr!=channels.end(); ++itr)
|
||||
delete itr->second;
|
||||
|
||||
channels.clear();
|
||||
}
|
||||
|
||||
Channel *ChannelMgr::GetJoinChannel(std::string name, uint32 channel_id)
|
||||
{
|
||||
if (channels.find(name) == channels.end())
|
||||
{
|
||||
Channel *nchan = new Channel(name,channel_id, team);
|
||||
channels[name] = nchan;
|
||||
}
|
||||
|
||||
return channels[name];
|
||||
}
|
||||
|
||||
Channel *ChannelMgr::GetChannel(std::string name, Player *p, bool pkt)
|
||||
{
|
||||
ChannelMap::const_iterator i = channels.find(name);
|
||||
|
||||
if(i == channels.end())
|
||||
{
|
||||
if(pkt)
|
||||
{
|
||||
WorldPacket data;
|
||||
MakeNotOnPacket(&data,name);
|
||||
p->GetSession()->SendPacket(&data);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
else
|
||||
return i->second;
|
||||
}
|
||||
|
||||
void ChannelMgr::LeftChannel(std::string name)
|
||||
{
|
||||
ChannelMap::const_iterator i = channels.find(name);
|
||||
|
||||
if(i == channels.end())
|
||||
return;
|
||||
|
||||
Channel* channel = i->second;
|
||||
|
||||
if(channel->GetNumPlayers() == 0 && !channel->IsConstant())
|
||||
{
|
||||
channels.erase(name);
|
||||
delete channel;
|
||||
}
|
||||
}
|
||||
|
||||
void ChannelMgr::MakeNotOnPacket(WorldPacket *data, std::string name)
|
||||
{
|
||||
data->Initialize(SMSG_CHANNEL_NOTIFY, (1+10)); // we guess size
|
||||
(*data) << (uint8)0x05 << name;
|
||||
}
|
||||
+12
-61
@@ -17,8 +17,12 @@
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
#ifndef TRINITYCORE_CHANNELMGR_H
|
||||
#define TRINITYCORE_CHANNELMGR_H
|
||||
#ifndef MANGOSSERVER_CHANNELMGR_H
|
||||
#define MANGOSSERVER_CHANNELMGR_H
|
||||
|
||||
#include "Common.h"
|
||||
#include "Channel.h"
|
||||
#include "Policies/Singleton.h"
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
@@ -34,73 +38,20 @@ class ChannelMgr
|
||||
uint32 team;
|
||||
typedef std::map<std::string,Channel *> ChannelMap;
|
||||
ChannelMgr() {team = 0;}
|
||||
~ChannelMgr()
|
||||
{
|
||||
for(ChannelMap::const_iterator itr = channels.begin();itr!=channels.end(); ++itr)
|
||||
delete itr->second;
|
||||
channels.clear();
|
||||
}
|
||||
Channel *GetJoinChannel(const std::string& name, uint32 channel_id)
|
||||
{
|
||||
if (channels.find(name) == channels.end())
|
||||
{
|
||||
Channel *nchan = new Channel(name,channel_id, team);
|
||||
channels[name] = nchan;
|
||||
}
|
||||
return channels[name];
|
||||
}
|
||||
Channel *GetChannel(const std::string& name, Player *p)
|
||||
{
|
||||
ChannelMap::const_iterator i = channels.find(name);
|
||||
~ChannelMgr();
|
||||
|
||||
if(i == channels.end())
|
||||
{
|
||||
WorldPacket data;
|
||||
MakeNotOnPacket(&data,name);
|
||||
p->GetSession()->SendPacket(&data);
|
||||
return NULL;
|
||||
}
|
||||
else
|
||||
return i->second;
|
||||
}
|
||||
void LeftChannel(const std::string& name)
|
||||
{
|
||||
ChannelMap::const_iterator i = channels.find(name);
|
||||
|
||||
if(i == channels.end())
|
||||
return;
|
||||
|
||||
Channel* channel = i->second;
|
||||
|
||||
if(channel->GetNumPlayers() == 0 && !channel->IsConstant())
|
||||
{
|
||||
channels.erase(name);
|
||||
delete channel;
|
||||
}
|
||||
}
|
||||
Channel *GetJoinChannel(std::string name, uint32 channel_id);
|
||||
Channel *GetChannel(std::string name, Player *p, bool pkt = true);
|
||||
void LeftChannel(std::string name);
|
||||
private:
|
||||
ChannelMap channels;
|
||||
void MakeNotOnPacket(WorldPacket *data, const std::string& name)
|
||||
{
|
||||
data->Initialize(SMSG_CHANNEL_NOTIFY, (1+10)); // we guess size
|
||||
(*data) << (uint8)0x05 << name;
|
||||
}
|
||||
void MakeNotOnPacket(WorldPacket *data, std::string name);
|
||||
};
|
||||
|
||||
class AllianceChannelMgr : public ChannelMgr {};
|
||||
class HordeChannelMgr : public ChannelMgr {};
|
||||
|
||||
inline ChannelMgr* channelMgr(uint32 team)
|
||||
{
|
||||
if (sWorld.getConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_CHANNEL))
|
||||
//For Test,No Seprate Faction
|
||||
return &Trinity::Singleton<AllianceChannelMgr>::Instance();
|
||||
ChannelMgr* channelMgr(uint32 team);
|
||||
|
||||
if(team==ALLIANCE)
|
||||
return &Trinity::Singleton<AllianceChannelMgr>::Instance();
|
||||
if(team==HORDE)
|
||||
return &Trinity::Singleton<HordeChannelMgr>::Instance();
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
@@ -123,7 +123,7 @@ class CharacterHandler
|
||||
void WorldSession::HandleCharEnum(QueryResult * result)
|
||||
{
|
||||
// keys can be non cleared if player open realm list and close it by 'cancel'
|
||||
LoginDatabase.PExecute("UPDATE account SET v = '0', s = '0' WHERE id = '%u'", GetAccountId());
|
||||
loginDatabase.PExecute("UPDATE account SET v = '0', s = '0' WHERE id = '%u'", GetAccountId());
|
||||
|
||||
WorldPacket data(SMSG_CHAR_ENUM, 100); // we guess size
|
||||
|
||||
@@ -280,7 +280,7 @@ void WorldSession::HandleCharCreateOpcode( WorldPacket & recv_data )
|
||||
return;
|
||||
}
|
||||
|
||||
QueryResult *resultacct = LoginDatabase.PQuery("SELECT SUM(numchars) FROM realmcharacters WHERE acctid = '%d'", GetAccountId());
|
||||
QueryResult *resultacct = loginDatabase.PQuery("SELECT SUM(numchars) FROM realmcharacters WHERE acctid = '%d'", GetAccountId());
|
||||
if (resultacct)
|
||||
{
|
||||
Field *fields=resultacct->Fetch();
|
||||
@@ -461,8 +461,8 @@ void WorldSession::HandleCharCreateOpcode( WorldPacket & recv_data )
|
||||
pNewChar->SaveToDB();
|
||||
charcount+=1;
|
||||
|
||||
LoginDatabase.PExecute("DELETE FROM realmcharacters WHERE acctid= '%d' AND realmid = '%d'", GetAccountId(), realmID);
|
||||
LoginDatabase.PExecute("INSERT INTO realmcharacters (numchars, acctid, realmid) VALUES (%u, %u, %u)", charcount, GetAccountId(), realmID);
|
||||
loginDatabase.PExecute("DELETE FROM realmcharacters WHERE acctid= '%d' AND realmid = '%d'", GetAccountId(), realmID);
|
||||
loginDatabase.PExecute("INSERT INTO realmcharacters (numchars, acctid, realmid) VALUES (%u, %u, %u)", charcount, GetAccountId(), realmID);
|
||||
|
||||
delete pNewChar; // created only to call SaveToDB()
|
||||
|
||||
@@ -736,7 +736,7 @@ void WorldSession::HandlePlayerLogin(LoginQueryHolder * holder)
|
||||
pCurrChar->SendInitialPacketsAfterAddToMap();
|
||||
|
||||
CharacterDatabase.PExecute("UPDATE characters SET online = 1 WHERE guid = '%u'", pCurrChar->GetGUIDLow());
|
||||
LoginDatabase.PExecute("UPDATE account SET online = 1 WHERE id = '%u'", GetAccountId());
|
||||
loginDatabase.PExecute("UPDATE account SET online = 1 WHERE id = '%u'", GetAccountId());
|
||||
pCurrChar->SetInGameTime( getMSTime() );
|
||||
|
||||
// announce group about member online (must be after add to player list to receive announce to self)
|
||||
|
||||
+1
-1
@@ -1810,4 +1810,4 @@ LocaleConstant CliHandler::GetSessionDbcLocale() const
|
||||
int CliHandler::GetSessionDbLocaleIndex() const
|
||||
{
|
||||
return objmgr.GetDBCLocaleIndex();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -39,7 +39,7 @@ void CreatureEventAIMgr::LoadCreatureEventAI_Texts()
|
||||
objmgr.LoadTrinityStrings(WorldDatabase,"creature_ai_texts",MIN_CREATURE_AI_TEXT_STRING_ID,MAX_CREATURE_AI_TEXT_STRING_ID);
|
||||
|
||||
// Gather Additional data from EventAI Texts
|
||||
QueryResult *result = WorldDatabase.PQuery("SELECT entry, sound, type, language, emote FROM creature_ai_texts");
|
||||
QueryResult *result = WorldDatabase.Query("SELECT entry, sound, type, language, emote FROM creature_ai_texts");
|
||||
|
||||
sLog.outString("Loading EventAI Texts additional data...");
|
||||
if (result)
|
||||
@@ -117,8 +117,8 @@ void CreatureEventAIMgr::LoadCreatureEventAI_Summons()
|
||||
//Drop Existing EventSummon Map
|
||||
m_CreatureEventAI_Summon_Map.clear();
|
||||
|
||||
//Gather additional data for EventAI
|
||||
QueryResult *result = WorldDatabase.PQuery("SELECT id, position_x, position_y, position_z, orientation, spawntimesecs FROM creature_ai_summons");
|
||||
// Gather additional data for EventAI
|
||||
QueryResult *result = WorldDatabase.Query("SELECT id, position_x, position_y, position_z, orientation, spawntimesecs FROM creature_ai_summons");
|
||||
if (result)
|
||||
{
|
||||
barGoLink bar(result->GetRowCount());
|
||||
@@ -169,8 +169,8 @@ void CreatureEventAIMgr::LoadCreatureEventAI_Scripts()
|
||||
//Drop Existing EventAI List
|
||||
m_CreatureEventAI_Event_Map.clear();
|
||||
|
||||
//Gather event data
|
||||
QueryResult *result = WorldDatabase.PQuery("SELECT id, creature_id, event_type, event_inverse_phase_mask, event_chance, event_flags, "
|
||||
// Gather event data
|
||||
QueryResult *result = WorldDatabase.Query("SELECT id, creature_id, event_type, event_inverse_phase_mask, event_chance, event_flags, "
|
||||
"event_param1, event_param2, event_param3, event_param4, "
|
||||
"action1_type, action1_param1, action1_param2, action1_param3, "
|
||||
"action2_type, action2_param1, action2_param2, action2_param3, "
|
||||
|
||||
@@ -84,11 +84,14 @@ struct AchievementCriteriaEntry
|
||||
} kill_creature;
|
||||
|
||||
// ACHIEVEMENT_CRITERIA_TYPE_WIN_BG = 1
|
||||
// TODO: there are further criterias instead just winning
|
||||
struct
|
||||
{
|
||||
uint32 bgMapID; // 3
|
||||
uint32 winCount; // 4
|
||||
uint32 additionalRequirement1_type; // 5 additional requirement 1 type
|
||||
uint32 additionalRequirement1_value; // 6 additional requirement 1 value
|
||||
uint32 additionalRequirement2_type; // 7 additional requirement 2 type
|
||||
uint32 additionalRequirement2_value; // 8 additional requirement 1 value
|
||||
} win_bg;
|
||||
|
||||
// ACHIEVEMENT_CRITERIA_TYPE_REACH_LEVEL = 5
|
||||
|
||||
@@ -949,7 +949,7 @@ void GameObject::Use(Unit* user)
|
||||
UseDoorOrButton();
|
||||
|
||||
// activate script
|
||||
sWorld.ScriptsStart(sGameObjectScripts, GetDBTableGUIDLow(), spellCaster, this);
|
||||
GetMap()->ScriptsStart(sGameObjectScripts, GetDBTableGUIDLow(), spellCaster, this);
|
||||
return;
|
||||
|
||||
case GAMEOBJECT_TYPE_QUESTGIVER: //2
|
||||
@@ -1045,7 +1045,7 @@ void GameObject::Use(Unit* user)
|
||||
player->CastedCreatureOrGO(info->id, GetGUID(), 0);
|
||||
|
||||
if (info->goober.eventId)
|
||||
sWorld.ScriptsStart(sEventScripts, info->goober.eventId, player, this);
|
||||
GetMap()->ScriptsStart(sEventScripts, info->goober.eventId, player, this);
|
||||
}
|
||||
|
||||
// cast this spell later if provided
|
||||
@@ -1068,7 +1068,7 @@ void GameObject::Use(Unit* user)
|
||||
player->SendCinematicStart(info->camera.cinematicId);
|
||||
|
||||
if (info->camera.eventID)
|
||||
sWorld.ScriptsStart(sEventScripts, info->camera.eventID, player, this);
|
||||
GetMap()->ScriptsStart(sEventScripts, info->camera.eventID, player, this);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
+2
-2
@@ -245,14 +245,14 @@ bool ChatHandler::HandleAccountLockCommand(const char* args)
|
||||
std::string argstr = (char*)args;
|
||||
if (argstr == "on")
|
||||
{
|
||||
LoginDatabase.PExecute( "UPDATE account SET locked = '1' WHERE id = '%d'",m_session->GetAccountId());
|
||||
loginDatabase.PExecute( "UPDATE account SET locked = '1' WHERE id = '%d'",m_session->GetAccountId());
|
||||
PSendSysMessage(LANG_COMMAND_ACCLOCKLOCKED);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (argstr == "off")
|
||||
{
|
||||
LoginDatabase.PExecute( "UPDATE account SET locked = '0' WHERE id = '%d'",m_session->GetAccountId());
|
||||
loginDatabase.PExecute( "UPDATE account SET locked = '0' WHERE id = '%d'",m_session->GetAccountId());
|
||||
PSendSysMessage(LANG_COMMAND_ACCLOCKUNLOCKED);
|
||||
return true;
|
||||
}
|
||||
|
||||
+1
-1
@@ -499,7 +499,7 @@ bool ChatHandler::HandleGMTicketAssignToCommand(const char* args)
|
||||
}
|
||||
uint64 tarGUID = objmgr.GetPlayerGUIDByName(targm.c_str());
|
||||
uint64 accid = objmgr.GetPlayerAccountIdByGUID(tarGUID);
|
||||
QueryResult *result = LoginDatabase.PQuery("SELECT `gmlevel` FROM `account` WHERE `id` = '%u'", accid);
|
||||
QueryResult *result = loginDatabase.PQuery("SELECT `gmlevel` FROM `account` WHERE `id` = '%u'", accid);
|
||||
if(!tarGUID|| !result || result->Fetch()->GetUInt32() < SEC_MODERATOR)
|
||||
{
|
||||
SendSysMessage(LANG_COMMAND_TICKETASSIGNERROR_A);
|
||||
|
||||
+9
-9
@@ -84,7 +84,7 @@ bool ChatHandler::HandleMuteCommand(const char* args)
|
||||
if (target)
|
||||
target->GetSession()->m_muteTime = mutetime;
|
||||
|
||||
LoginDatabase.PExecute("UPDATE account SET mutetime = " UI64FMTD " WHERE id = '%u'",uint64(mutetime), account_id );
|
||||
loginDatabase.PExecute("UPDATE account SET mutetime = " UI64FMTD " WHERE id = '%u'",uint64(mutetime), account_id );
|
||||
|
||||
if(target)
|
||||
ChatHandler(target).PSendSysMessage(LANG_YOUR_CHAT_DISABLED, notspeaktime, mutereasonstr.c_str());
|
||||
@@ -130,7 +130,7 @@ bool ChatHandler::HandleUnmuteCommand(const char* args)
|
||||
target->GetSession()->m_muteTime = 0;
|
||||
}
|
||||
|
||||
LoginDatabase.PExecute("UPDATE account SET mutetime = '0' WHERE id = '%u'", account_id );
|
||||
loginDatabase.PExecute("UPDATE account SET mutetime = '0' WHERE id = '%u'", account_id );
|
||||
|
||||
if(target)
|
||||
ChatHandler(target).PSendSysMessage(LANG_YOUR_CHAT_ENABLED);
|
||||
@@ -2189,7 +2189,7 @@ bool ChatHandler::HandlePInfoCommand(const char* args)
|
||||
uint32 security = 0;
|
||||
std::string last_login = GetTrinityString(LANG_ERROR);
|
||||
|
||||
QueryResult* result = LoginDatabase.PQuery("SELECT username,gmlevel,email,last_ip,last_login FROM account WHERE id = '%u'",accId);
|
||||
QueryResult* result = loginDatabase.PQuery("SELECT username,gmlevel,email,last_ip,last_login FROM account WHERE id = '%u'",accId);
|
||||
if(result)
|
||||
{
|
||||
Field* fields = result->Fetch();
|
||||
@@ -3933,9 +3933,9 @@ bool ChatHandler::HandleLookupPlayerIpCommand(const char* args)
|
||||
char* limit_str = strtok (NULL, " ");
|
||||
int32 limit = limit_str ? atoi (limit_str) : -1;
|
||||
|
||||
LoginDatabase.escape_string (ip);
|
||||
loginDatabase.escape_string (ip);
|
||||
|
||||
QueryResult* result = LoginDatabase.PQuery ("SELECT id,username FROM account WHERE last_ip = '%s'", ip.c_str ());
|
||||
QueryResult* result = loginDatabase.PQuery ("SELECT id,username FROM account WHERE last_ip = '%s'", ip.c_str ());
|
||||
|
||||
return LookupPlayerSearchCommand (result,limit);
|
||||
}
|
||||
@@ -3952,9 +3952,9 @@ bool ChatHandler::HandleLookupPlayerAccountCommand(const char* args)
|
||||
if (!AccountMgr::normalizeString (account))
|
||||
return false;
|
||||
|
||||
LoginDatabase.escape_string (account);
|
||||
loginDatabase.escape_string (account);
|
||||
|
||||
QueryResult* result = LoginDatabase.PQuery ("SELECT id,username FROM account WHERE username = '%s'", account.c_str ());
|
||||
QueryResult* result = loginDatabase.PQuery ("SELECT id,username FROM account WHERE username = '%s'", account.c_str ());
|
||||
|
||||
return LookupPlayerSearchCommand (result,limit);
|
||||
}
|
||||
@@ -3969,9 +3969,9 @@ bool ChatHandler::HandleLookupPlayerEmailCommand(const char* args)
|
||||
char* limit_str = strtok (NULL, " ");
|
||||
int32 limit = limit_str ? atoi (limit_str) : -1;
|
||||
|
||||
LoginDatabase.escape_string (email);
|
||||
loginDatabase.escape_string (email);
|
||||
|
||||
QueryResult* result = LoginDatabase.PQuery ("SELECT id,username FROM account WHERE email = '%s'", email.c_str ());
|
||||
QueryResult* result = loginDatabase.PQuery ("SELECT id,username FROM account WHERE email = '%s'", email.c_str ());
|
||||
|
||||
return LookupPlayerSearchCommand (result,limit);
|
||||
}
|
||||
|
||||
+19
-19
@@ -1415,7 +1415,7 @@ bool ChatHandler::HandleAccountSetGmLevelCommand(const char* args)
|
||||
PSendSysMessage(LANG_YOURS_SECURITY_CHANGED, m_session->GetPlayer()->GetName(), gm);
|
||||
}
|
||||
|
||||
LoginDatabase.PExecute("UPDATE account SET gmlevel = '%d' WHERE id = '%u'", gm, targetAccountId);
|
||||
loginDatabase.PExecute("UPDATE account SET gmlevel = '%d' WHERE id = '%u'", gm, targetAccountId);
|
||||
return true;
|
||||
}else
|
||||
{
|
||||
@@ -1456,7 +1456,7 @@ bool ChatHandler::HandleAccountSetGmLevelCommand(const char* args)
|
||||
}
|
||||
|
||||
PSendSysMessage(LANG_YOU_CHANGE_SECURITY, targetAccountName.c_str(), gm);
|
||||
LoginDatabase.PExecute("UPDATE account SET gmlevel = '%d' WHERE id = '%u'", gm, targetAccountId);
|
||||
loginDatabase.PExecute("UPDATE account SET gmlevel = '%d' WHERE id = '%u'", gm, targetAccountId);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -5909,7 +5909,7 @@ bool ChatHandler::HandleBanInfoCharacterCommand(const char* args)
|
||||
|
||||
bool ChatHandler::HandleBanInfoHelper(uint32 accountid, char const* accountname)
|
||||
{
|
||||
QueryResult *result = LoginDatabase.PQuery("SELECT FROM_UNIXTIME(bandate), unbandate-bandate, active, unbandate,banreason,bannedby FROM account_banned WHERE id = '%u' ORDER BY bandate ASC",accountid);
|
||||
QueryResult *result = loginDatabase.PQuery("SELECT FROM_UNIXTIME(bandate), unbandate-bandate, active, unbandate,banreason,bannedby FROM account_banned WHERE id = '%u' ORDER BY bandate ASC",accountid);
|
||||
if(!result)
|
||||
{
|
||||
PSendSysMessage(LANG_BANINFO_NOACCOUNTBAN, accountname);
|
||||
@@ -5949,8 +5949,8 @@ bool ChatHandler::HandleBanInfoIPCommand(const char* args)
|
||||
|
||||
std::string IP = cIP;
|
||||
|
||||
LoginDatabase.escape_string(IP);
|
||||
QueryResult *result = LoginDatabase.PQuery("SELECT ip, FROM_UNIXTIME(bandate), FROM_UNIXTIME(unbandate), unbandate-UNIX_TIMESTAMP(), banreason,bannedby,unbandate-bandate FROM ip_banned WHERE ip = '%s'",IP.c_str());
|
||||
loginDatabase.escape_string(IP);
|
||||
QueryResult *result = loginDatabase.PQuery("SELECT ip, FROM_UNIXTIME(bandate), FROM_UNIXTIME(unbandate), unbandate-UNIX_TIMESTAMP(), banreason,bannedby,unbandate-bandate FROM ip_banned WHERE ip = '%s'",IP.c_str());
|
||||
if(!result)
|
||||
{
|
||||
PSendSysMessage(LANG_BANINFO_NOIP);
|
||||
@@ -5968,14 +5968,14 @@ bool ChatHandler::HandleBanInfoIPCommand(const char* args)
|
||||
|
||||
bool ChatHandler::HandleBanListCharacterCommand(const char* args)
|
||||
{
|
||||
LoginDatabase.Execute("DELETE FROM ip_banned WHERE unbandate<=UNIX_TIMESTAMP() AND unbandate<>bandate");
|
||||
loginDatabase.Execute("DELETE FROM ip_banned WHERE unbandate<=UNIX_TIMESTAMP() AND unbandate<>bandate");
|
||||
|
||||
char* cFilter = strtok ((char*)args, " ");
|
||||
if(!cFilter)
|
||||
return false;
|
||||
|
||||
std::string filter = cFilter;
|
||||
LoginDatabase.escape_string(filter);
|
||||
loginDatabase.escape_string(filter);
|
||||
QueryResult* result = CharacterDatabase.PQuery("SELECT account FROM characters WHERE name "_LIKE_" "_CONCAT3_("'%%'","'%s'","'%%'"),filter.c_str());
|
||||
if (!result)
|
||||
{
|
||||
@@ -5988,22 +5988,22 @@ bool ChatHandler::HandleBanListCharacterCommand(const char* args)
|
||||
|
||||
bool ChatHandler::HandleBanListAccountCommand(const char* args)
|
||||
{
|
||||
LoginDatabase.Execute("DELETE FROM ip_banned WHERE unbandate<=UNIX_TIMESTAMP() AND unbandate<>bandate");
|
||||
loginDatabase.Execute("DELETE FROM ip_banned WHERE unbandate<=UNIX_TIMESTAMP() AND unbandate<>bandate");
|
||||
|
||||
char* cFilter = strtok((char*)args, " ");
|
||||
std::string filter = cFilter ? cFilter : "";
|
||||
LoginDatabase.escape_string(filter);
|
||||
loginDatabase.escape_string(filter);
|
||||
|
||||
QueryResult* result;
|
||||
|
||||
if(filter.empty())
|
||||
{
|
||||
result = LoginDatabase.Query("SELECT account.id, username FROM account, account_banned"
|
||||
result = loginDatabase.Query("SELECT account.id, username FROM account, account_banned"
|
||||
" WHERE account.id = account_banned.id AND active = 1 GROUP BY account.id");
|
||||
}
|
||||
else
|
||||
{
|
||||
result = LoginDatabase.PQuery("SELECT account.id, username FROM account, account_banned"
|
||||
result = loginDatabase.PQuery("SELECT account.id, username FROM account, account_banned"
|
||||
" WHERE account.id = account_banned.id AND active = 1 AND username "_LIKE_" "_CONCAT3_("'%%'","'%s'","'%%'")" GROUP BY account.id",
|
||||
filter.c_str());
|
||||
}
|
||||
@@ -6029,7 +6029,7 @@ bool ChatHandler::HandleBanListHelper(QueryResult* result)
|
||||
Field* fields = result->Fetch();
|
||||
uint32 accountid = fields[0].GetUInt32();
|
||||
|
||||
QueryResult* banresult = LoginDatabase.PQuery("SELECT account.username FROM account,account_banned WHERE account_banned.id='%u' AND account_banned.id=account.id",accountid);
|
||||
QueryResult* banresult = loginDatabase.PQuery("SELECT account.username FROM account,account_banned WHERE account_banned.id='%u' AND account_banned.id=account.id",accountid);
|
||||
if(banresult)
|
||||
{
|
||||
Field* fields2 = banresult->Fetch();
|
||||
@@ -6060,7 +6060,7 @@ bool ChatHandler::HandleBanListHelper(QueryResult* result)
|
||||
accmgr.GetName (account_id,account_name);
|
||||
|
||||
// No SQL injection. id is uint32.
|
||||
QueryResult *banInfo = LoginDatabase.PQuery("SELECT bandate,unbandate,bannedby,banreason FROM account_banned WHERE id = %u ORDER BY unbandate", account_id);
|
||||
QueryResult *banInfo = loginDatabase.PQuery("SELECT bandate,unbandate,bannedby,banreason FROM account_banned WHERE id = %u ORDER BY unbandate", account_id);
|
||||
if (banInfo)
|
||||
{
|
||||
Field *fields2 = banInfo->Fetch();
|
||||
@@ -6097,23 +6097,23 @@ bool ChatHandler::HandleBanListHelper(QueryResult* result)
|
||||
|
||||
bool ChatHandler::HandleBanListIPCommand(const char* args)
|
||||
{
|
||||
LoginDatabase.Execute("DELETE FROM ip_banned WHERE unbandate<=UNIX_TIMESTAMP() AND unbandate<>bandate");
|
||||
loginDatabase.Execute("DELETE FROM ip_banned WHERE unbandate<=UNIX_TIMESTAMP() AND unbandate<>bandate");
|
||||
|
||||
char* cFilter = strtok((char*)args, " ");
|
||||
std::string filter = cFilter ? cFilter : "";
|
||||
LoginDatabase.escape_string(filter);
|
||||
loginDatabase.escape_string(filter);
|
||||
|
||||
QueryResult* result;
|
||||
|
||||
if(filter.empty())
|
||||
{
|
||||
result = LoginDatabase.Query ("SELECT ip,bandate,unbandate,bannedby,banreason FROM ip_banned"
|
||||
result = loginDatabase.Query ("SELECT ip,bandate,unbandate,bannedby,banreason FROM ip_banned"
|
||||
" WHERE (bandate=unbandate OR unbandate>UNIX_TIMESTAMP())"
|
||||
" ORDER BY unbandate" );
|
||||
}
|
||||
else
|
||||
{
|
||||
result = LoginDatabase.PQuery( "SELECT ip,bandate,unbandate,bannedby,banreason FROM ip_banned"
|
||||
result = loginDatabase.PQuery( "SELECT ip,bandate,unbandate,bannedby,banreason FROM ip_banned"
|
||||
" WHERE (bandate=unbandate OR unbandate>UNIX_TIMESTAMP()) AND ip "_LIKE_" "_CONCAT3_("'%%'","'%s'","'%%'")
|
||||
" ORDER BY unbandate",filter.c_str() );
|
||||
}
|
||||
@@ -6882,7 +6882,7 @@ bool ChatHandler::HandleInstanceSaveDataCommand(const char * /*args*/)
|
||||
bool ChatHandler::HandleGMListFullCommand(const char* /*args*/)
|
||||
{
|
||||
///- Get the accounts with GM Level >0
|
||||
QueryResult *result = LoginDatabase.Query( "SELECT username,gmlevel FROM account WHERE gmlevel > 0" );
|
||||
QueryResult *result = loginDatabase.Query( "SELECT username,gmlevel FROM account WHERE gmlevel > 0" );
|
||||
if(result)
|
||||
{
|
||||
SendSysMessage(LANG_GMLIST);
|
||||
@@ -6991,7 +6991,7 @@ bool ChatHandler::HandleAccountSetAddonCommand(const char* args)
|
||||
return false;
|
||||
|
||||
// No SQL injection
|
||||
LoginDatabase.PExecute("UPDATE account SET expansion = '%d' WHERE id = '%u'",lev,account_id);
|
||||
loginDatabase.PExecute("UPDATE account SET expansion = '%d' WHERE id = '%u'",lev,account_id);
|
||||
PSendSysMessage(LANG_ACCOUNT_SETADDON,account_name.c_str(),account_id,lev);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -624,6 +624,7 @@ libmangosgame_a_SOURCES = \
|
||||
Channel.cpp \
|
||||
Channel.h \
|
||||
ChannelHandler.cpp \
|
||||
ChannelMgr.cpp \
|
||||
ChannelMgr.h \
|
||||
CharacterHandler.cpp \
|
||||
Chat.cpp \
|
||||
@@ -840,11 +841,8 @@ libmangosgame_a_SOURCES = \
|
||||
GroupRefManager.h
|
||||
>>>>>>> 5a6594330caefc0dc00a5fe792dcb0e344b457cb:src/game/Makefile.am
|
||||
|
||||
## Link against shared library
|
||||
libmangosgame_a_LIBADD = ../shared/libmangosshared.a ../shared/Auth/libmangosauth.a ../shared/Config/libmangosconfig.a ../shared/Database/libmangosdatabase.a ../shared/vmap/libmangosvmaps.a
|
||||
|
||||
## Additional files to include when running 'make dist'
|
||||
# Precompiled Headers for WIN
|
||||
EXTRA_DIST = \
|
||||
pchdef.cpp \
|
||||
pchdef.h
|
||||
pchdef.h
|
||||
|
||||
+860
-13
@@ -20,6 +20,7 @@
|
||||
|
||||
#include "MapManager.h"
|
||||
#include "Player.h"
|
||||
#include "Vehicle.h"
|
||||
#include "GridNotifiers.h"
|
||||
#include "Log.h"
|
||||
#include "GridStates.h"
|
||||
@@ -36,6 +37,7 @@
|
||||
#include "Group.h"
|
||||
#include "MapRefManager.h"
|
||||
#include "Vehicle.h"
|
||||
#include "WaypointManager.h"
|
||||
|
||||
#include "MapInstanced.h"
|
||||
#include "InstanceSaveMgr.h"
|
||||
@@ -46,9 +48,20 @@
|
||||
|
||||
GridState* si_GridStates[MAX_GRID_STATE];
|
||||
|
||||
struct ScriptAction
|
||||
{
|
||||
uint64 sourceGUID;
|
||||
uint64 targetGUID;
|
||||
uint64 ownerGUID; // owner of source if source is item
|
||||
ScriptInfo const* script; // pointer to static script data
|
||||
};
|
||||
|
||||
Map::~Map()
|
||||
{
|
||||
UnloadAll();
|
||||
|
||||
if(!m_scriptSchedule.empty())
|
||||
sWorld.DecreaseScheduledScriptCount(m_scriptSchedule.size());
|
||||
}
|
||||
|
||||
bool Map::ExistMap(uint32 mapid,int gx,int gy)
|
||||
@@ -780,17 +793,21 @@ void Map::Update(const uint32 &t_diff)
|
||||
|
||||
// Don't unload grids if it's battleground, since we may have manually added GOs,creatures, those doesn't load from DB at grid re-load !
|
||||
// This isn't really bother us, since as soon as we have instanced BG-s, the whole map unloads as the BG gets ended
|
||||
if (IsBattleGroundOrArena())
|
||||
return;
|
||||
|
||||
for (GridRefManager<NGridType>::iterator i = GridRefManager<NGridType>::begin(); i != GridRefManager<NGridType>::end(); )
|
||||
if (!IsBattleGroundOrArena())
|
||||
{
|
||||
NGridType *grid = i->getSource();
|
||||
GridInfo *info = i->getSource()->getGridInfoRef();
|
||||
++i; // The update might delete the map and we need the next map before the iterator gets invalid
|
||||
assert(grid->GetGridState() >= 0 && grid->GetGridState() < MAX_GRID_STATE);
|
||||
si_GridStates[grid->GetGridState()]->Update(*this, *grid, *info, grid->getX(), grid->getY(), t_diff);
|
||||
for (GridRefManager<NGridType>::iterator i = GridRefManager<NGridType>::begin(); i != GridRefManager<NGridType>::end(); )
|
||||
{
|
||||
NGridType *grid = i->getSource();
|
||||
GridInfo *info = i->getSource()->getGridInfoRef();
|
||||
++i; // The update might delete the map and we need the next map before the iterator gets invalid
|
||||
assert(grid->GetGridState() >= 0 && grid->GetGridState() < MAX_GRID_STATE);
|
||||
si_GridStates[grid->GetGridState()]->Update(*this, *grid, *info, grid->getX(), grid->getY(), t_diff);
|
||||
}
|
||||
}
|
||||
|
||||
///- Process necessary scripts
|
||||
if (!m_scriptSchedule.empty())
|
||||
ScriptsProcess();
|
||||
}
|
||||
|
||||
void Map::Remove(Player *player, bool remove)
|
||||
@@ -1312,11 +1329,11 @@ 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 != uint32(MAP_HEIGTH_MAGIC))
|
||||
if (header.fourcc != uint32(MAP_HEIGHT_MAGIC))
|
||||
return false;
|
||||
|
||||
m_gridHeight = header.gridHeight;
|
||||
if (!(header.flags & MAP_HEIGHT_NO_HIGHT))
|
||||
if (!(header.flags & MAP_HEIGHT_NO_HEIGHT))
|
||||
{
|
||||
if ((header.flags & MAP_HEIGHT_AS_INT16))
|
||||
{
|
||||
@@ -1365,12 +1382,12 @@ bool GridMap::loadLiquidData(FILE *in, uint32 offset, uint32 size)
|
||||
m_liquid_height= header.height;
|
||||
m_liquidLevel = header.liquidLevel;
|
||||
|
||||
if (!(header.flags&MAP_LIQUID_NO_TYPE))
|
||||
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))
|
||||
if (!(header.flags & MAP_LIQUID_NO_HEIGHT))
|
||||
{
|
||||
m_liquid_map = new float [m_liquid_width*m_liquid_height];
|
||||
fread(m_liquid_map, sizeof(float), m_liquid_width*m_liquid_height, in);
|
||||
@@ -2745,6 +2762,836 @@ void BattleGroundMap::UnloadAll()
|
||||
Map::UnloadAll();
|
||||
}
|
||||
|
||||
/// Put scripts in the execution queue
|
||||
void Map::ScriptsStart(ScriptMapMap const& scripts, uint32 id, Object* source, Object* target)
|
||||
{
|
||||
///- Find the script map
|
||||
ScriptMapMap::const_iterator s = scripts.find(id);
|
||||
if (s == scripts.end())
|
||||
return;
|
||||
|
||||
// prepare static data
|
||||
uint64 sourceGUID = source ? source->GetGUID() : (uint64)0; //some script commands doesn't have source
|
||||
uint64 targetGUID = target ? target->GetGUID() : (uint64)0;
|
||||
uint64 ownerGUID = (source->GetTypeId()==TYPEID_ITEM) ? ((Item*)source)->GetOwnerGUID() : (uint64)0;
|
||||
|
||||
///- Schedule script execution for all scripts in the script map
|
||||
ScriptMap const *s2 = &(s->second);
|
||||
bool immedScript = false;
|
||||
for (ScriptMap::const_iterator iter = s2->begin(); iter != s2->end(); ++iter)
|
||||
{
|
||||
ScriptAction sa;
|
||||
sa.sourceGUID = sourceGUID;
|
||||
sa.targetGUID = targetGUID;
|
||||
sa.ownerGUID = ownerGUID;
|
||||
|
||||
sa.script = &iter->second;
|
||||
m_scriptSchedule.insert(std::pair<time_t, ScriptAction>(time_t(sWorld.GetGameTime() + iter->first), sa));
|
||||
if (iter->first == 0)
|
||||
immedScript = true;
|
||||
|
||||
sWorld.IncreaseScheduledScriptsCount();
|
||||
}
|
||||
///- If one of the effects should be immediate, launch the script execution
|
||||
if (/*start &&*/ immedScript)
|
||||
ScriptsProcess();
|
||||
}
|
||||
|
||||
void Map::ScriptCommandStart(ScriptInfo const& script, uint32 delay, Object* source, Object* target)
|
||||
{
|
||||
// NOTE: script record _must_ exist until command executed
|
||||
|
||||
// prepare static data
|
||||
uint64 sourceGUID = source ? source->GetGUID() : (uint64)0;
|
||||
uint64 targetGUID = target ? target->GetGUID() : (uint64)0;
|
||||
uint64 ownerGUID = (source->GetTypeId()==TYPEID_ITEM) ? ((Item*)source)->GetOwnerGUID() : (uint64)0;
|
||||
|
||||
ScriptAction sa;
|
||||
sa.sourceGUID = sourceGUID;
|
||||
sa.targetGUID = targetGUID;
|
||||
sa.ownerGUID = ownerGUID;
|
||||
|
||||
sa.script = &script;
|
||||
m_scriptSchedule.insert(std::pair<time_t, ScriptAction>(time_t(sWorld.GetGameTime() + delay), sa));
|
||||
|
||||
sWorld.IncreaseScheduledScriptsCount();
|
||||
|
||||
///- If effects should be immediate, launch the script execution
|
||||
if(delay == 0)
|
||||
ScriptsProcess();
|
||||
}
|
||||
|
||||
/// Process queued scripts
|
||||
void Map::ScriptsProcess()
|
||||
{
|
||||
if (m_scriptSchedule.empty())
|
||||
return;
|
||||
|
||||
///- Process overdue queued scripts
|
||||
std::multimap<time_t, ScriptAction>::iterator iter = m_scriptSchedule.begin();
|
||||
// ok as multimap is a *sorted* associative container
|
||||
while (!m_scriptSchedule.empty() && (iter->first <= sWorld.GetGameTime()))
|
||||
{
|
||||
ScriptAction const& step = iter->second;
|
||||
|
||||
Object* source = NULL;
|
||||
|
||||
if(step.sourceGUID)
|
||||
{
|
||||
switch(GUID_HIPART(step.sourceGUID))
|
||||
{
|
||||
case HIGHGUID_ITEM:
|
||||
// case HIGHGUID_CONTAINER: ==HIGHGUID_ITEM
|
||||
{
|
||||
Player* player = HashMapHolder<Player>::Find(step.ownerGUID);
|
||||
if(player)
|
||||
source = player->GetItemByGuid(step.sourceGUID);
|
||||
break;
|
||||
}
|
||||
case HIGHGUID_UNIT:
|
||||
source = HashMapHolder<Creature>::Find(step.sourceGUID);
|
||||
break;
|
||||
case HIGHGUID_PET:
|
||||
source = HashMapHolder<Pet>::Find(step.sourceGUID);
|
||||
break;
|
||||
case HIGHGUID_VEHICLE:
|
||||
source = HashMapHolder<Vehicle>::Find(step.sourceGUID);
|
||||
break;
|
||||
case HIGHGUID_PLAYER:
|
||||
source = HashMapHolder<Player>::Find(step.sourceGUID);
|
||||
break;
|
||||
case HIGHGUID_GAMEOBJECT:
|
||||
source = HashMapHolder<GameObject>::Find(step.sourceGUID);
|
||||
break;
|
||||
case HIGHGUID_CORPSE:
|
||||
source = HashMapHolder<Corpse>::Find(step.sourceGUID);
|
||||
break;
|
||||
case HIGHGUID_MO_TRANSPORT:
|
||||
for (MapManager::TransportSet::iterator iter = MapManager::Instance().m_Transports.begin(); iter != MapManager::Instance().m_Transports.end(); ++iter)
|
||||
{
|
||||
if((*iter)->GetGUID() == step.sourceGUID)
|
||||
{
|
||||
source = reinterpret_cast<Object*>(*iter);
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
sLog.outError("*_script source with unsupported high guid value %u",GUID_HIPART(step.sourceGUID));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//if(source && !source->IsInWorld()) source = NULL;
|
||||
|
||||
Object* target = NULL;
|
||||
|
||||
if(step.targetGUID)
|
||||
{
|
||||
switch(GUID_HIPART(step.targetGUID))
|
||||
{
|
||||
case HIGHGUID_UNIT:
|
||||
target = HashMapHolder<Creature>::Find(step.targetGUID);
|
||||
break;
|
||||
case HIGHGUID_PET:
|
||||
target = HashMapHolder<Pet>::Find(step.targetGUID);
|
||||
break;
|
||||
case HIGHGUID_VEHICLE:
|
||||
target = HashMapHolder<Vehicle>::Find(step.targetGUID);
|
||||
break;
|
||||
case HIGHGUID_PLAYER: // empty GUID case also
|
||||
target = HashMapHolder<Player>::Find(step.targetGUID);
|
||||
break;
|
||||
case HIGHGUID_GAMEOBJECT:
|
||||
target = HashMapHolder<GameObject>::Find(step.targetGUID);
|
||||
break;
|
||||
case HIGHGUID_CORPSE:
|
||||
target = HashMapHolder<Corpse>::Find(step.targetGUID);
|
||||
break;
|
||||
default:
|
||||
sLog.outError("*_script source with unsupported high guid value %u",GUID_HIPART(step.targetGUID));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//if(target && !target->IsInWorld()) target = NULL;
|
||||
|
||||
switch (step.script->command)
|
||||
{
|
||||
case SCRIPT_COMMAND_TALK:
|
||||
{
|
||||
if(!source)
|
||||
{
|
||||
sLog.outError("SCRIPT_COMMAND_TALK call for NULL creature.");
|
||||
break;
|
||||
}
|
||||
|
||||
if(source->GetTypeId()!=TYPEID_UNIT)
|
||||
{
|
||||
sLog.outError("SCRIPT_COMMAND_TALK call for non-creature (TypeId: %u), skipping.",source->GetTypeId());
|
||||
break;
|
||||
}
|
||||
if(step.script->datalong > 3)
|
||||
{
|
||||
sLog.outError("SCRIPT_COMMAND_TALK invalid chat type (%u), skipping.",step.script->datalong);
|
||||
break;
|
||||
}
|
||||
|
||||
uint64 unit_target = target ? target->GetGUID() : 0;
|
||||
|
||||
//datalong 0=normal say, 1=whisper, 2=yell, 3=emote text
|
||||
switch(step.script->datalong)
|
||||
{
|
||||
case 0: // Say
|
||||
((Creature *)source)->Say(step.script->dataint, LANG_UNIVERSAL, unit_target);
|
||||
break;
|
||||
case 1: // Whisper
|
||||
if(!unit_target)
|
||||
{
|
||||
sLog.outError("SCRIPT_COMMAND_TALK attempt to whisper (%u) NULL, skipping.",step.script->datalong);
|
||||
break;
|
||||
}
|
||||
((Creature *)source)->Whisper(step.script->dataint,unit_target);
|
||||
break;
|
||||
case 2: // Yell
|
||||
((Creature *)source)->Yell(step.script->dataint, LANG_UNIVERSAL, unit_target);
|
||||
break;
|
||||
case 3: // Emote text
|
||||
((Creature *)source)->TextEmote(step.script->dataint, unit_target);
|
||||
break;
|
||||
default:
|
||||
break; // must be already checked at load
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case SCRIPT_COMMAND_EMOTE:
|
||||
if(!source)
|
||||
{
|
||||
sLog.outError("SCRIPT_COMMAND_EMOTE call for NULL creature.");
|
||||
break;
|
||||
}
|
||||
|
||||
if(source->GetTypeId()!=TYPEID_UNIT)
|
||||
{
|
||||
sLog.outError("SCRIPT_COMMAND_EMOTE call for non-creature (TypeId: %u), skipping.",source->GetTypeId());
|
||||
break;
|
||||
}
|
||||
|
||||
((Creature *)source)->HandleEmoteCommand(step.script->datalong);
|
||||
break;
|
||||
case SCRIPT_COMMAND_FIELD_SET:
|
||||
if(!source)
|
||||
{
|
||||
sLog.outError("SCRIPT_COMMAND_FIELD_SET call for NULL object.");
|
||||
break;
|
||||
}
|
||||
if(step.script->datalong <= OBJECT_FIELD_ENTRY || step.script->datalong >= source->GetValuesCount())
|
||||
{
|
||||
sLog.outError("SCRIPT_COMMAND_FIELD_SET call for wrong field %u (max count: %u) in object (TypeId: %u).",
|
||||
step.script->datalong,source->GetValuesCount(),source->GetTypeId());
|
||||
break;
|
||||
}
|
||||
|
||||
source->SetUInt32Value(step.script->datalong, step.script->datalong2);
|
||||
break;
|
||||
case SCRIPT_COMMAND_MOVE_TO:
|
||||
if(!source)
|
||||
{
|
||||
sLog.outError("SCRIPT_COMMAND_MOVE_TO call for NULL creature.");
|
||||
break;
|
||||
}
|
||||
|
||||
if(source->GetTypeId()!=TYPEID_UNIT)
|
||||
{
|
||||
sLog.outError("SCRIPT_COMMAND_MOVE_TO call for non-creature (TypeId: %u), skipping.",source->GetTypeId());
|
||||
break;
|
||||
}
|
||||
((Creature*)source)->SendMonsterMoveWithSpeed(step.script->x, step.script->y, step.script->z, step.script->datalong2 );
|
||||
((Creature*)source)->GetMap()->CreatureRelocation(((Creature*)source), step.script->x, step.script->y, step.script->z, 0);
|
||||
break;
|
||||
case SCRIPT_COMMAND_FLAG_SET:
|
||||
if(!source)
|
||||
{
|
||||
sLog.outError("SCRIPT_COMMAND_FLAG_SET call for NULL object.");
|
||||
break;
|
||||
}
|
||||
if(step.script->datalong <= OBJECT_FIELD_ENTRY || step.script->datalong >= source->GetValuesCount())
|
||||
{
|
||||
sLog.outError("SCRIPT_COMMAND_FLAG_SET call for wrong field %u (max count: %u) in object (TypeId: %u).",
|
||||
step.script->datalong,source->GetValuesCount(),source->GetTypeId());
|
||||
break;
|
||||
}
|
||||
|
||||
source->SetFlag(step.script->datalong, step.script->datalong2);
|
||||
break;
|
||||
case SCRIPT_COMMAND_FLAG_REMOVE:
|
||||
if(!source)
|
||||
{
|
||||
sLog.outError("SCRIPT_COMMAND_FLAG_REMOVE call for NULL object.");
|
||||
break;
|
||||
}
|
||||
if(step.script->datalong <= OBJECT_FIELD_ENTRY || step.script->datalong >= source->GetValuesCount())
|
||||
{
|
||||
sLog.outError("SCRIPT_COMMAND_FLAG_REMOVE call for wrong field %u (max count: %u) in object (TypeId: %u).",
|
||||
step.script->datalong,source->GetValuesCount(),source->GetTypeId());
|
||||
break;
|
||||
}
|
||||
|
||||
source->RemoveFlag(step.script->datalong, step.script->datalong2);
|
||||
break;
|
||||
|
||||
case SCRIPT_COMMAND_TELEPORT_TO:
|
||||
{
|
||||
// accept player in any one from target/source arg
|
||||
if (!target && !source)
|
||||
{
|
||||
sLog.outError("SCRIPT_COMMAND_TELEPORT_TO call for NULL object.");
|
||||
break;
|
||||
}
|
||||
|
||||
// must be only Player
|
||||
if((!target || target->GetTypeId() != TYPEID_PLAYER) && (!source || source->GetTypeId() != TYPEID_PLAYER))
|
||||
{
|
||||
sLog.outError("SCRIPT_COMMAND_TELEPORT_TO call for non-player (TypeIdSource: %u)(TypeIdTarget: %u), skipping.", source ? source->GetTypeId() : 0, target ? target->GetTypeId() : 0);
|
||||
break;
|
||||
}
|
||||
|
||||
Player* pSource = target && target->GetTypeId() == TYPEID_PLAYER ? (Player*)target : (Player*)source;
|
||||
|
||||
pSource->TeleportTo(step.script->datalong, step.script->x, step.script->y, step.script->z, step.script->o);
|
||||
break;
|
||||
}
|
||||
|
||||
case SCRIPT_COMMAND_TEMP_SUMMON_CREATURE:
|
||||
{
|
||||
if(!step.script->datalong) // creature not specified
|
||||
{
|
||||
sLog.outError("SCRIPT_COMMAND_TEMP_SUMMON_CREATURE call for NULL creature.");
|
||||
break;
|
||||
}
|
||||
|
||||
if(!source)
|
||||
{
|
||||
sLog.outError("SCRIPT_COMMAND_TEMP_SUMMON_CREATURE call for NULL world object.");
|
||||
break;
|
||||
}
|
||||
|
||||
WorldObject* summoner = dynamic_cast<WorldObject*>(source);
|
||||
|
||||
if(!summoner)
|
||||
{
|
||||
sLog.outError("SCRIPT_COMMAND_TEMP_SUMMON_CREATURE call for non-WorldObject (TypeId: %u), skipping.",source->GetTypeId());
|
||||
break;
|
||||
}
|
||||
|
||||
float x = step.script->x;
|
||||
float y = step.script->y;
|
||||
float z = step.script->z;
|
||||
float o = step.script->o;
|
||||
|
||||
Creature* pCreature = summoner->SummonCreature(step.script->datalong, x, y, z, o,TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,step.script->datalong2);
|
||||
if (!pCreature)
|
||||
{
|
||||
sLog.outError("SCRIPT_COMMAND_TEMP_SUMMON failed for creature (entry: %u).",step.script->datalong);
|
||||
break;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case SCRIPT_COMMAND_RESPAWN_GAMEOBJECT:
|
||||
{
|
||||
if(!step.script->datalong) // gameobject not specified
|
||||
{
|
||||
sLog.outError("SCRIPT_COMMAND_RESPAWN_GAMEOBJECT call for NULL gameobject.");
|
||||
break;
|
||||
}
|
||||
|
||||
if(!source)
|
||||
{
|
||||
sLog.outError("SCRIPT_COMMAND_RESPAWN_GAMEOBJECT call for NULL world object.");
|
||||
break;
|
||||
}
|
||||
|
||||
WorldObject* summoner = dynamic_cast<WorldObject*>(source);
|
||||
|
||||
if(!summoner)
|
||||
{
|
||||
sLog.outError("SCRIPT_COMMAND_RESPAWN_GAMEOBJECT call for non-WorldObject (TypeId: %u), skipping.",source->GetTypeId());
|
||||
break;
|
||||
}
|
||||
|
||||
GameObject *go = NULL;
|
||||
int32 time_to_despawn = step.script->datalong2<5 ? 5 : (int32)step.script->datalong2;
|
||||
|
||||
CellPair p(MaNGOS::ComputeCellPair(summoner->GetPositionX(), summoner->GetPositionY()));
|
||||
Cell cell(p);
|
||||
cell.data.Part.reserved = ALL_DISTRICT;
|
||||
|
||||
MaNGOS::GameObjectWithDbGUIDCheck go_check(*summoner,step.script->datalong);
|
||||
MaNGOS::GameObjectSearcher<MaNGOS::GameObjectWithDbGUIDCheck> checker(summoner, go,go_check);
|
||||
|
||||
TypeContainerVisitor<MaNGOS::GameObjectSearcher<MaNGOS::GameObjectWithDbGUIDCheck>, GridTypeMapContainer > object_checker(checker);
|
||||
CellLock<GridReadGuard> cell_lock(cell, p);
|
||||
cell_lock->Visit(cell_lock, object_checker, *summoner->GetMap());
|
||||
|
||||
if ( !go )
|
||||
{
|
||||
sLog.outError("SCRIPT_COMMAND_RESPAWN_GAMEOBJECT failed for gameobject(guid: %u).", step.script->datalong);
|
||||
break;
|
||||
}
|
||||
|
||||
if( go->GetGoType()==GAMEOBJECT_TYPE_FISHINGNODE ||
|
||||
go->GetGoType()==GAMEOBJECT_TYPE_DOOR ||
|
||||
go->GetGoType()==GAMEOBJECT_TYPE_BUTTON ||
|
||||
go->GetGoType()==GAMEOBJECT_TYPE_TRAP )
|
||||
{
|
||||
sLog.outError("SCRIPT_COMMAND_RESPAWN_GAMEOBJECT can not be used with gameobject of type %u (guid: %u).", uint32(go->GetGoType()), step.script->datalong);
|
||||
break;
|
||||
}
|
||||
|
||||
if( go->isSpawned() )
|
||||
break; //gameobject already spawned
|
||||
|
||||
go->SetLootState(GO_READY);
|
||||
go->SetRespawnTime(time_to_despawn); //despawn object in ? seconds
|
||||
|
||||
go->GetMap()->Add(go);
|
||||
break;
|
||||
}
|
||||
case SCRIPT_COMMAND_OPEN_DOOR:
|
||||
{
|
||||
if(!step.script->datalong) // door not specified
|
||||
{
|
||||
sLog.outError("SCRIPT_COMMAND_OPEN_DOOR call for NULL door.");
|
||||
break;
|
||||
}
|
||||
|
||||
if(!source)
|
||||
{
|
||||
sLog.outError("SCRIPT_COMMAND_OPEN_DOOR call for NULL unit.");
|
||||
break;
|
||||
}
|
||||
|
||||
if(!source->isType(TYPEMASK_UNIT)) // must be any Unit (creature or player)
|
||||
{
|
||||
sLog.outError("SCRIPT_COMMAND_OPEN_DOOR call for non-unit (TypeId: %u), skipping.",source->GetTypeId());
|
||||
break;
|
||||
}
|
||||
|
||||
Unit* caster = (Unit*)source;
|
||||
|
||||
GameObject *door = NULL;
|
||||
int32 time_to_close = step.script->datalong2 < 15 ? 15 : (int32)step.script->datalong2;
|
||||
|
||||
CellPair p(MaNGOS::ComputeCellPair(caster->GetPositionX(), caster->GetPositionY()));
|
||||
Cell cell(p);
|
||||
cell.data.Part.reserved = ALL_DISTRICT;
|
||||
|
||||
MaNGOS::GameObjectWithDbGUIDCheck go_check(*caster,step.script->datalong);
|
||||
MaNGOS::GameObjectSearcher<MaNGOS::GameObjectWithDbGUIDCheck> checker(caster,door,go_check);
|
||||
|
||||
TypeContainerVisitor<MaNGOS::GameObjectSearcher<MaNGOS::GameObjectWithDbGUIDCheck>, GridTypeMapContainer > object_checker(checker);
|
||||
CellLock<GridReadGuard> cell_lock(cell, p);
|
||||
cell_lock->Visit(cell_lock, object_checker, *caster->GetMap());
|
||||
|
||||
if (!door)
|
||||
{
|
||||
sLog.outError("SCRIPT_COMMAND_OPEN_DOOR failed for gameobject(guid: %u).", step.script->datalong);
|
||||
break;
|
||||
}
|
||||
if (door->GetGoType() != GAMEOBJECT_TYPE_DOOR)
|
||||
{
|
||||
sLog.outError("SCRIPT_COMMAND_OPEN_DOOR failed for non-door(GoType: %u).", door->GetGoType());
|
||||
break;
|
||||
}
|
||||
|
||||
if (door->GetGoState() != GO_STATE_READY)
|
||||
break; //door already open
|
||||
|
||||
door->UseDoorOrButton(time_to_close);
|
||||
|
||||
if(target && target->isType(TYPEMASK_GAMEOBJECT) && ((GameObject*)target)->GetGoType()==GAMEOBJECT_TYPE_BUTTON)
|
||||
((GameObject*)target)->UseDoorOrButton(time_to_close);
|
||||
break;
|
||||
}
|
||||
case SCRIPT_COMMAND_CLOSE_DOOR:
|
||||
{
|
||||
if(!step.script->datalong) // guid for door not specified
|
||||
{
|
||||
sLog.outError("SCRIPT_COMMAND_CLOSE_DOOR call for NULL door.");
|
||||
break;
|
||||
}
|
||||
|
||||
if(!source)
|
||||
{
|
||||
sLog.outError("SCRIPT_COMMAND_CLOSE_DOOR call for NULL unit.");
|
||||
break;
|
||||
}
|
||||
|
||||
if(!source->isType(TYPEMASK_UNIT)) // must be any Unit (creature or player)
|
||||
{
|
||||
sLog.outError("SCRIPT_COMMAND_CLOSE_DOOR call for non-unit (TypeId: %u), skipping.",source->GetTypeId());
|
||||
break;
|
||||
}
|
||||
|
||||
Unit* caster = (Unit*)source;
|
||||
|
||||
GameObject *door = NULL;
|
||||
int32 time_to_open = step.script->datalong2 < 15 ? 15 : (int32)step.script->datalong2;
|
||||
|
||||
CellPair p(MaNGOS::ComputeCellPair(caster->GetPositionX(), caster->GetPositionY()));
|
||||
Cell cell(p);
|
||||
cell.data.Part.reserved = ALL_DISTRICT;
|
||||
|
||||
MaNGOS::GameObjectWithDbGUIDCheck go_check(*caster,step.script->datalong);
|
||||
MaNGOS::GameObjectSearcher<MaNGOS::GameObjectWithDbGUIDCheck> checker(caster,door,go_check);
|
||||
|
||||
TypeContainerVisitor<MaNGOS::GameObjectSearcher<MaNGOS::GameObjectWithDbGUIDCheck>, GridTypeMapContainer > object_checker(checker);
|
||||
CellLock<GridReadGuard> cell_lock(cell, p);
|
||||
cell_lock->Visit(cell_lock, object_checker, *caster->GetMap());
|
||||
|
||||
if ( !door )
|
||||
{
|
||||
sLog.outError("SCRIPT_COMMAND_CLOSE_DOOR failed for gameobject(guid: %u).", step.script->datalong);
|
||||
break;
|
||||
}
|
||||
if ( door->GetGoType() != GAMEOBJECT_TYPE_DOOR )
|
||||
{
|
||||
sLog.outError("SCRIPT_COMMAND_CLOSE_DOOR failed for non-door(GoType: %u).", door->GetGoType());
|
||||
break;
|
||||
}
|
||||
|
||||
if( door->GetGoState() == GO_STATE_READY )
|
||||
break; //door already closed
|
||||
|
||||
door->UseDoorOrButton(time_to_open);
|
||||
|
||||
if(target && target->isType(TYPEMASK_GAMEOBJECT) && ((GameObject*)target)->GetGoType()==GAMEOBJECT_TYPE_BUTTON)
|
||||
((GameObject*)target)->UseDoorOrButton(time_to_open);
|
||||
|
||||
break;
|
||||
}
|
||||
case SCRIPT_COMMAND_QUEST_EXPLORED:
|
||||
{
|
||||
if(!source)
|
||||
{
|
||||
sLog.outError("SCRIPT_COMMAND_QUEST_EXPLORED call for NULL source.");
|
||||
break;
|
||||
}
|
||||
|
||||
if(!target)
|
||||
{
|
||||
sLog.outError("SCRIPT_COMMAND_QUEST_EXPLORED call for NULL target.");
|
||||
break;
|
||||
}
|
||||
|
||||
// when script called for item spell casting then target == (unit or GO) and source is player
|
||||
WorldObject* worldObject;
|
||||
Player* player;
|
||||
|
||||
if(target->GetTypeId()==TYPEID_PLAYER)
|
||||
{
|
||||
if(source->GetTypeId()!=TYPEID_UNIT && source->GetTypeId()!=TYPEID_GAMEOBJECT)
|
||||
{
|
||||
sLog.outError("SCRIPT_COMMAND_QUEST_EXPLORED call for non-creature and non-gameobject (TypeId: %u), skipping.",source->GetTypeId());
|
||||
break;
|
||||
}
|
||||
|
||||
worldObject = (WorldObject*)source;
|
||||
player = (Player*)target;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(target->GetTypeId()!=TYPEID_UNIT && target->GetTypeId()!=TYPEID_GAMEOBJECT)
|
||||
{
|
||||
sLog.outError("SCRIPT_COMMAND_QUEST_EXPLORED call for non-creature and non-gameobject (TypeId: %u), skipping.",target->GetTypeId());
|
||||
break;
|
||||
}
|
||||
|
||||
if(source->GetTypeId()!=TYPEID_PLAYER)
|
||||
{
|
||||
sLog.outError("SCRIPT_COMMAND_QUEST_EXPLORED call for non-player(TypeId: %u), skipping.",source->GetTypeId());
|
||||
break;
|
||||
}
|
||||
|
||||
worldObject = (WorldObject*)target;
|
||||
player = (Player*)source;
|
||||
}
|
||||
|
||||
// quest id and flags checked at script loading
|
||||
if( (worldObject->GetTypeId()!=TYPEID_UNIT || ((Unit*)worldObject)->isAlive()) &&
|
||||
(step.script->datalong2==0 || worldObject->IsWithinDistInMap(player,float(step.script->datalong2))) )
|
||||
player->AreaExploredOrEventHappens(step.script->datalong);
|
||||
else
|
||||
player->FailQuest(step.script->datalong);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case SCRIPT_COMMAND_ACTIVATE_OBJECT:
|
||||
{
|
||||
if(!source)
|
||||
{
|
||||
sLog.outError("SCRIPT_COMMAND_ACTIVATE_OBJECT must have source caster.");
|
||||
break;
|
||||
}
|
||||
|
||||
if(!source->isType(TYPEMASK_UNIT))
|
||||
{
|
||||
sLog.outError("SCRIPT_COMMAND_ACTIVATE_OBJECT source caster isn't unit (TypeId: %u), skipping.",source->GetTypeId());
|
||||
break;
|
||||
}
|
||||
|
||||
if(!target)
|
||||
{
|
||||
sLog.outError("SCRIPT_COMMAND_ACTIVATE_OBJECT call for NULL gameobject.");
|
||||
break;
|
||||
}
|
||||
|
||||
if(target->GetTypeId()!=TYPEID_GAMEOBJECT)
|
||||
{
|
||||
sLog.outError("SCRIPT_COMMAND_ACTIVATE_OBJECT call for non-gameobject (TypeId: %u), skipping.",target->GetTypeId());
|
||||
break;
|
||||
}
|
||||
|
||||
Unit* caster = (Unit*)source;
|
||||
|
||||
GameObject *go = (GameObject*)target;
|
||||
|
||||
go->Use(caster);
|
||||
break;
|
||||
}
|
||||
|
||||
case SCRIPT_COMMAND_REMOVE_AURA:
|
||||
{
|
||||
Object* cmdTarget = step.script->datalong2 ? source : target;
|
||||
|
||||
if(!cmdTarget)
|
||||
{
|
||||
sLog.outError("SCRIPT_COMMAND_REMOVE_AURA call for NULL %s.",step.script->datalong2 ? "source" : "target");
|
||||
break;
|
||||
}
|
||||
|
||||
if(!cmdTarget->isType(TYPEMASK_UNIT))
|
||||
{
|
||||
sLog.outError("SCRIPT_COMMAND_REMOVE_AURA %s isn't unit (TypeId: %u), skipping.",step.script->datalong2 ? "source" : "target",cmdTarget->GetTypeId());
|
||||
break;
|
||||
}
|
||||
|
||||
((Unit*)cmdTarget)->RemoveAurasDueToSpell(step.script->datalong);
|
||||
break;
|
||||
}
|
||||
|
||||
case SCRIPT_COMMAND_CAST_SPELL:
|
||||
{
|
||||
if(!source)
|
||||
{
|
||||
sLog.outError("SCRIPT_COMMAND_CAST_SPELL must have source caster.");
|
||||
break;
|
||||
}
|
||||
|
||||
Object* cmdTarget = step.script->datalong2 & 0x01 ? source : target;
|
||||
|
||||
if(!cmdTarget)
|
||||
{
|
||||
sLog.outError("SCRIPT_COMMAND_CAST_SPELL call for NULL %s.",step.script->datalong2 & 0x01 ? "source" : "target");
|
||||
break;
|
||||
}
|
||||
|
||||
if(!cmdTarget->isType(TYPEMASK_UNIT))
|
||||
{
|
||||
sLog.outError("SCRIPT_COMMAND_CAST_SPELL %s isn't unit (TypeId: %u), skipping.",step.script->datalong2 & 0x01 ? "source" : "target",cmdTarget->GetTypeId());
|
||||
break;
|
||||
}
|
||||
|
||||
Unit* spellTarget = (Unit*)cmdTarget;
|
||||
|
||||
Object* cmdSource = step.script->datalong2 & 0x02 ? target : source;
|
||||
|
||||
if(!cmdSource)
|
||||
{
|
||||
sLog.outError("SCRIPT_COMMAND_CAST_SPELL call for NULL %s.",step.script->datalong2 & 0x02 ? "target" : "source");
|
||||
break;
|
||||
}
|
||||
|
||||
if(!cmdSource->isType(TYPEMASK_UNIT))
|
||||
{
|
||||
sLog.outError("SCRIPT_COMMAND_CAST_SPELL %s isn't unit (TypeId: %u), skipping.",step.script->datalong2 & 0x02 ? "target" : "source", cmdSource->GetTypeId());
|
||||
break;
|
||||
}
|
||||
|
||||
Unit* spellSource = (Unit*)cmdSource;
|
||||
|
||||
//TODO: when GO cast implemented, code below must be updated accordingly to also allow GO spell cast
|
||||
spellSource->CastSpell(spellTarget,step.script->datalong,false);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case SCRIPT_COMMAND_LOAD_PATH:
|
||||
{
|
||||
if(!source)
|
||||
{
|
||||
sLog.outError("SCRIPT_COMMAND_START_MOVE is tried to apply to NON-existing unit.");
|
||||
break;
|
||||
}
|
||||
|
||||
if(!source->isType(TYPEMASK_UNIT))
|
||||
{
|
||||
sLog.outError("SCRIPT_COMMAND_START_MOVE source mover isn't unit (TypeId: %u), skipping.",source->GetTypeId());
|
||||
break;
|
||||
}
|
||||
|
||||
if(!WaypointMgr.GetPath(step.script->datalong))
|
||||
{
|
||||
sLog.outError("SCRIPT_COMMAND_START_MOVE source mover has an invallid path, skipping.", step.script->datalong2);
|
||||
break;
|
||||
}
|
||||
|
||||
dynamic_cast<Unit*>(source)->GetMotionMaster()->MovePath(step.script->datalong, step.script->datalong2);
|
||||
break;
|
||||
}
|
||||
|
||||
case SCRIPT_COMMAND_CALLSCRIPT_TO_UNIT:
|
||||
{
|
||||
if(!step.script->datalong || !step.script->datalong2)
|
||||
{
|
||||
sLog.outError("SCRIPT_COMMAND_CALLSCRIPT calls invallid db_script_id or lowguid not present: skipping.");
|
||||
break;
|
||||
}
|
||||
//our target
|
||||
Creature* target = NULL;
|
||||
|
||||
if(source) //using grid searcher
|
||||
{
|
||||
CellPair p(Trinity::ComputeCellPair(((Unit*)source)->GetPositionX(), ((Unit*)source)->GetPositionY()));
|
||||
Cell cell(p);
|
||||
cell.data.Part.reserved = ALL_DISTRICT;
|
||||
|
||||
//sLog.outDebug("Attempting to find Creature: Db GUID: %i", step.script->datalong);
|
||||
Trinity::CreatureWithDbGUIDCheck target_check(((Unit*)source), step.script->datalong);
|
||||
Trinity::CreatureSearcher<Trinity::CreatureWithDbGUIDCheck> checker(((Unit*)source), target, target_check);
|
||||
|
||||
TypeContainerVisitor<Trinity::CreatureSearcher <Trinity::CreatureWithDbGUIDCheck>, GridTypeMapContainer > unit_checker(checker);
|
||||
CellLock<GridReadGuard> cell_lock(cell, p);
|
||||
cell_lock->Visit(cell_lock, unit_checker, *(((Unit*)source)->GetMap()));
|
||||
}
|
||||
else //check hashmap holders
|
||||
{
|
||||
if(CreatureData const* data = objmgr.GetCreatureData(step.script->datalong))
|
||||
target = ObjectAccessor::GetObjectInWorld<Creature>(data->mapid, data->posX, data->posY, MAKE_NEW_GUID(step.script->datalong, data->id, HIGHGUID_UNIT), target);
|
||||
}
|
||||
//sLog.outDebug("attempting to pass target...");
|
||||
if(!target)
|
||||
break;
|
||||
//sLog.outDebug("target passed");
|
||||
//Lets choose our ScriptMap map
|
||||
ScriptMapMap *datamap = NULL;
|
||||
switch(step.script->dataint)
|
||||
{
|
||||
case 1://QUEST END SCRIPTMAP
|
||||
datamap = &sQuestEndScripts;
|
||||
break;
|
||||
case 2://QUEST START SCRIPTMAP
|
||||
datamap = &sQuestStartScripts;
|
||||
break;
|
||||
case 3://SPELLS SCRIPTMAP
|
||||
datamap = &sSpellScripts;
|
||||
break;
|
||||
case 4://GAMEOBJECTS SCRIPTMAP
|
||||
datamap = &sGameObjectScripts;
|
||||
break;
|
||||
case 5://EVENTS SCRIPTMAP
|
||||
datamap = &sEventScripts;
|
||||
break;
|
||||
case 6://WAYPOINTS SCRIPTMAP
|
||||
datamap = &sWaypointScripts;
|
||||
break;
|
||||
default:
|
||||
sLog.outError("SCRIPT_COMMAND_CALLSCRIPT ERROR: no scriptmap present... ignoring");
|
||||
break;
|
||||
}
|
||||
//if no scriptmap present...
|
||||
if(!datamap)
|
||||
break;
|
||||
|
||||
uint32 script_id = step.script->datalong2;
|
||||
//insert script into schedule but do not start it
|
||||
ScriptsStart(*datamap, script_id, target, NULL/*, false*/);
|
||||
break;
|
||||
}
|
||||
|
||||
case SCRIPT_COMMAND_KILL:
|
||||
{
|
||||
if(!source || ((Creature*)source)->isDead())
|
||||
break;
|
||||
|
||||
((Creature*)source)->DealDamage(((Creature*)source), ((Creature*)source)->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false);
|
||||
|
||||
switch(step.script->dataint)
|
||||
{
|
||||
case 0: break; //return false not remove corpse
|
||||
case 1: ((Creature*)source)->RemoveCorpse(); break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case SCRIPT_COMMAND_PLAY_SOUND:
|
||||
{
|
||||
if(!source)
|
||||
{
|
||||
sLog.outError("SCRIPT_COMMAND_PLAY_SOUND call for NULL creature.");
|
||||
break;
|
||||
}
|
||||
|
||||
WorldObject* pSource = dynamic_cast<WorldObject*>(source);
|
||||
if(!pSource)
|
||||
{
|
||||
sLog.outError("SCRIPT_COMMAND_PLAY_SOUND call for non-world object (TypeId: %u), skipping.",source->GetTypeId());
|
||||
break;
|
||||
}
|
||||
|
||||
// bitmask: 0/1=anyone/target, 0/2=with distance dependent
|
||||
Player* pTarget = NULL;
|
||||
if(step.script->datalong2 & 1)
|
||||
{
|
||||
if(!target)
|
||||
{
|
||||
sLog.outError("SCRIPT_COMMAND_PLAY_SOUND in targeted mode call for NULL target.");
|
||||
break;
|
||||
}
|
||||
|
||||
if(target->GetTypeId()!=TYPEID_PLAYER)
|
||||
{
|
||||
sLog.outError("SCRIPT_COMMAND_PLAY_SOUND in targeted mode call for non-player (TypeId: %u), skipping.",target->GetTypeId());
|
||||
break;
|
||||
}
|
||||
|
||||
pTarget = (Player*)target;
|
||||
}
|
||||
|
||||
// bitmask: 0/1=anyone/target, 0/2=with distance dependent
|
||||
if(step.script->datalong2 & 2)
|
||||
pSource->PlayDistanceSound(step.script->datalong,pTarget);
|
||||
else
|
||||
pSource->PlayDirectSound(step.script->datalong,pTarget);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
sLog.outError("Unknown script command %u called.",step.script->command);
|
||||
break;
|
||||
}
|
||||
|
||||
m_scriptSchedule.erase(iter);
|
||||
sWorld.DecreaseScheduledScriptCount();
|
||||
|
||||
iter = m_scriptSchedule.begin();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
Creature*
|
||||
Map::GetCreature(uint64 guid)
|
||||
{
|
||||
|
||||
+26
-9
@@ -43,9 +43,12 @@ class WorldPacket;
|
||||
class InstanceData;
|
||||
class Group;
|
||||
class InstanceSave;
|
||||
class Object;
|
||||
class WorldObject;
|
||||
class TempSummon;
|
||||
class CreatureGroup;
|
||||
struct ScriptInfo;
|
||||
struct ScriptAction;
|
||||
|
||||
|
||||
typedef ACE_RW_Thread_Mutex GridRWLock;
|
||||
@@ -74,10 +77,11 @@ typedef MaNGOS::SingleThreaded<GridRWLock>::Lock NullGuard;
|
||||
#define MAP_MAGIC 'SPAM'
|
||||
#define MAP_VERSION_MAGIC '0.1w'
|
||||
#define MAP_AREA_MAGIC 'AERA'
|
||||
#define MAP_HEIGTH_MAGIC 'TGHM'
|
||||
#define MAP_HEIGHT_MAGIC 'TGHM'
|
||||
#define MAP_LIQUID_MAGIC 'QILM'
|
||||
|
||||
struct map_fileheader{
|
||||
struct map_fileheader
|
||||
{
|
||||
uint32 mapMagic;
|
||||
uint32 versionMagic;
|
||||
uint32 areaMapOffset;
|
||||
@@ -89,17 +93,20 @@ struct map_fileheader{
|
||||
};
|
||||
|
||||
#define MAP_AREA_NO_AREA 0x0001
|
||||
struct map_areaHeader{
|
||||
|
||||
struct map_areaHeader
|
||||
{
|
||||
uint32 fourcc;
|
||||
uint16 flags;
|
||||
uint16 gridArea;
|
||||
};
|
||||
|
||||
#define MAP_HEIGHT_NO_HIGHT 0x0001
|
||||
#define MAP_HEIGHT_NO_HEIGHT 0x0001
|
||||
#define MAP_HEIGHT_AS_INT16 0x0002
|
||||
#define MAP_HEIGHT_AS_INT8 0x0004
|
||||
|
||||
struct map_heightHeader{
|
||||
struct map_heightHeader
|
||||
{
|
||||
uint32 fourcc;
|
||||
uint32 flags;
|
||||
float gridHeight;
|
||||
@@ -107,8 +114,10 @@ struct map_heightHeader{
|
||||
};
|
||||
|
||||
#define MAP_LIQUID_NO_TYPE 0x0001
|
||||
#define MAP_LIQUID_NO_HIGHT 0x0002
|
||||
struct map_liquidHeader{
|
||||
#define MAP_LIQUID_NO_HEIGHT 0x0002
|
||||
|
||||
struct map_liquidHeader
|
||||
{
|
||||
uint32 fourcc;
|
||||
uint16 flags;
|
||||
uint16 liquidType;
|
||||
@@ -119,7 +128,8 @@ struct map_liquidHeader{
|
||||
float liquidLevel;
|
||||
};
|
||||
|
||||
enum ZLiquidStatus{
|
||||
enum ZLiquidStatus
|
||||
{
|
||||
LIQUID_MAP_NO_WATER = 0x00000000,
|
||||
LIQUID_MAP_ABOVE_WATER = 0x00000001,
|
||||
LIQUID_MAP_WATER_WALK = 0x00000002,
|
||||
@@ -138,7 +148,8 @@ enum ZLiquidStatus{
|
||||
#define MAP_LIQUID_TYPE_DARK_WATER 0x10
|
||||
#define MAP_LIQUID_TYPE_WMO_WATER 0x20
|
||||
|
||||
struct LiquidData{
|
||||
struct LiquidData
|
||||
{
|
||||
uint32 type;
|
||||
float level;
|
||||
float depth_level;
|
||||
@@ -398,6 +409,10 @@ class MANGOS_DLL_SPEC Map : public GridRefManager<NGridType>, public MaNGOS::Obj
|
||||
typedef MapRefManager PlayerList;
|
||||
PlayerList const& GetPlayers() const { return m_mapRefManager; }
|
||||
|
||||
//per-map script storage
|
||||
void ScriptsStart(std::map<uint32, std::multimap<uint32, ScriptInfo> > const& scripts, uint32 id, Object* source, Object* target);
|
||||
void ScriptCommandStart(ScriptInfo const& script, uint32 delay, Object* source, Object* target);
|
||||
|
||||
// must called with AddToWorld
|
||||
template<class T>
|
||||
void AddToActive(T* obj) { AddToActiveHelper(obj); }
|
||||
@@ -467,6 +482,7 @@ class MANGOS_DLL_SPEC Map : public GridRefManager<NGridType>, public MaNGOS::Obj
|
||||
void setGridObjectDataLoaded(bool pLoaded, uint32 x, uint32 y) { getNGrid(x,y)->setGridObjectDataLoaded(pLoaded); }
|
||||
|
||||
void setNGrid(NGridType* grid, uint32 x, uint32 y);
|
||||
void ScriptsProcess();
|
||||
|
||||
void UpdateActiveCells(const float &x, const float &y, const uint32 &t_diff);
|
||||
protected:
|
||||
@@ -508,6 +524,7 @@ class MANGOS_DLL_SPEC Map : public GridRefManager<NGridType>, public MaNGOS::Obj
|
||||
std::vector<Unit*> i_unitsToNotify;
|
||||
std::set<WorldObject *> i_objectsToRemove;
|
||||
std::map<WorldObject*, bool> i_objectsToSwitch;
|
||||
std::multimap<time_t, ScriptAction> m_scriptSchedule;
|
||||
|
||||
// Type specific code for add/remove to/from grid
|
||||
template<class T>
|
||||
|
||||
@@ -1216,15 +1216,17 @@ void WorldSession::HandleWardenDataOpcode(WorldPacket& /*recv_data*/)
|
||||
*/
|
||||
}
|
||||
|
||||
void WorldSession::HandlePlayedTime(WorldPacket& /*recv_data*/)
|
||||
void WorldSession::HandlePlayedTime(WorldPacket& recv_data)
|
||||
{
|
||||
uint32 TotalTimePlayed = GetPlayer()->GetTotalPlayedTime();
|
||||
uint32 LevelPlayedTime = GetPlayer()->GetLevelPlayedTime();
|
||||
CHECK_PACKET_SIZE(recv_data, 1);
|
||||
|
||||
WorldPacket data(SMSG_PLAYED_TIME, 9);
|
||||
data << TotalTimePlayed;
|
||||
data << LevelPlayedTime;
|
||||
data << uint8(0);
|
||||
uint8 unk1;
|
||||
recv_data >> unk1; // 0 or 1 expected
|
||||
|
||||
WorldPacket data(SMSG_PLAYED_TIME, 4 + 4 + 1);
|
||||
data << uint32(_player->GetTotalPlayedTime());
|
||||
data << uint32(_player->GetLevelPlayedTime());
|
||||
data << uint8(unk1); // 0 - will not show in chat frame
|
||||
SendPacket(&data);
|
||||
}
|
||||
|
||||
@@ -1356,7 +1358,7 @@ void WorldSession::HandleWhoisOpcode(WorldPacket& recv_data)
|
||||
|
||||
uint32 accid = plr->GetSession()->GetAccountId();
|
||||
|
||||
QueryResult *result = LoginDatabase.PQuery("SELECT username,email,last_ip FROM account WHERE id=%u", accid);
|
||||
QueryResult *result = loginDatabase.PQuery("SELECT username,email,last_ip FROM account WHERE id=%u", accid);
|
||||
if(!result)
|
||||
{
|
||||
SendNotification(LANG_ACCOUNT_FOR_PLAYER_NOT_FOUND, charname.c_str());
|
||||
|
||||
+3
-3
@@ -4110,7 +4110,7 @@ void Player::DeleteFromDB(uint64 playerguid, uint32 accountId, bool updateRealmC
|
||||
CharacterDatabase.PExecute("DELETE FROM character_equipmentsets WHERE guid = '%u'",guid);
|
||||
CharacterDatabase.CommitTransaction();
|
||||
|
||||
//LoginDatabase.PExecute("UPDATE realmcharacters SET numchars = numchars - 1 WHERE acctid = %d AND realmid = %d", accountId, realmID);
|
||||
//loginDatabase.PExecute("UPDATE realmcharacters SET numchars = numchars - 1 WHERE acctid = %d AND realmid = %d", accountId, realmID);
|
||||
if(updateRealmChars) sWorld.UpdateRealmCharCount(accountId);
|
||||
}
|
||||
|
||||
@@ -12882,7 +12882,7 @@ void Player::AddQuest( Quest const *pQuest, Object *questGiver )
|
||||
|
||||
//starting initial quest script
|
||||
if(questGiver && pQuest->GetQuestStartScript()!=0)
|
||||
sWorld.ScriptsStart(sQuestStartScripts, pQuest->GetQuestStartScript(), questGiver, this);
|
||||
GetMap()->ScriptsStart(sQuestStartScripts, pQuest->GetQuestStartScript(), questGiver, this);
|
||||
|
||||
// Some spells applied at quest activation
|
||||
SpellAreaForQuestMapBounds saBounds = spellmgr.GetSpellAreaForQuestMapBounds(quest_id,true);
|
||||
@@ -14142,7 +14142,7 @@ void Player::SendQuestReward( Quest const *pQuest, uint32 XP, Object * questGive
|
||||
GetSession()->SendPacket( &data );
|
||||
|
||||
if (pQuest->GetQuestCompleteScript() != 0)
|
||||
sWorld.ScriptsStart(sQuestEndScripts, pQuest->GetQuestCompleteScript(), questGiver, this);
|
||||
GetMap()->ScriptsStart(sQuestEndScripts, pQuest->GetQuestCompleteScript(), questGiver, this);
|
||||
}
|
||||
|
||||
void Player::SendQuestFailed( uint32 quest_id )
|
||||
|
||||
@@ -30,7 +30,6 @@ template<class T>
|
||||
void PointMovementGenerator<T>::Initialize(T &unit)
|
||||
{
|
||||
unit.StopMoving();
|
||||
unit.clearUnitState(UNIT_STAT_MOVING);
|
||||
Traveller<T> traveller(unit);
|
||||
// knockback effect has UNIT_STAT_JUMPING set,so if here we disable sentmonstermove there will be creature position sync problem between client and server
|
||||
i_destinationHolder.SetDestination(traveller,i_x,i_y,i_z, true /* !unit.hasUnitState(UNIT_STAT_JUMPING)*/);
|
||||
|
||||
@@ -475,4 +475,4 @@ void ReputationMgr::UpdateRankCounters( ReputationRank old_rank, ReputationRank
|
||||
++m_reveredFactionCount;
|
||||
if(new_rank >= REP_HONORED)
|
||||
++m_honoredFactionCount;
|
||||
}
|
||||
}
|
||||
|
||||
+194
-184
@@ -703,190 +703,194 @@ enum SpellEffects
|
||||
|
||||
enum SpellCastResult
|
||||
{
|
||||
SPELL_FAILED_AFFECTING_COMBAT = 0,
|
||||
SPELL_FAILED_ALREADY_AT_FULL_HEALTH = 1,
|
||||
SPELL_FAILED_ALREADY_AT_FULL_MANA = 2,
|
||||
SPELL_FAILED_ALREADY_AT_FULL_POWER = 3,
|
||||
SPELL_FAILED_ALREADY_BEING_TAMED = 4,
|
||||
SPELL_FAILED_ALREADY_HAVE_CHARM = 5,
|
||||
SPELL_FAILED_ALREADY_HAVE_SUMMON = 6,
|
||||
SPELL_FAILED_ALREADY_OPEN = 7,
|
||||
SPELL_FAILED_AURA_BOUNCED = 8,
|
||||
SPELL_FAILED_AUTOTRACK_INTERRUPTED = 9,
|
||||
SPELL_FAILED_BAD_IMPLICIT_TARGETS = 10,
|
||||
SPELL_FAILED_BAD_TARGETS = 11,
|
||||
SPELL_FAILED_CANT_BE_CHARMED = 12,
|
||||
SPELL_FAILED_CANT_BE_DISENCHANTED = 13,
|
||||
SPELL_FAILED_CANT_BE_DISENCHANTED_SKILL = 14,
|
||||
SPELL_FAILED_CANT_BE_MILLED = 15,
|
||||
SPELL_FAILED_CANT_BE_PROSPECTED = 16,
|
||||
SPELL_FAILED_CANT_CAST_ON_TAPPED = 17,
|
||||
SPELL_FAILED_CANT_DUEL_WHILE_INVISIBLE = 18,
|
||||
SPELL_FAILED_CANT_DUEL_WHILE_STEALTHED = 19,
|
||||
SPELL_FAILED_CANT_STEALTH = 20,
|
||||
SPELL_FAILED_CASTER_AURASTATE = 21,
|
||||
SPELL_FAILED_CASTER_DEAD = 22,
|
||||
SPELL_FAILED_CHARMED = 23,
|
||||
SPELL_FAILED_CHEST_IN_USE = 24,
|
||||
SPELL_FAILED_CONFUSED = 25,
|
||||
SPELL_FAILED_DONT_REPORT = 26,
|
||||
SPELL_FAILED_EQUIPPED_ITEM = 27,
|
||||
SPELL_FAILED_EQUIPPED_ITEM_CLASS = 28,
|
||||
SPELL_FAILED_EQUIPPED_ITEM_CLASS_MAINHAND = 29,
|
||||
SPELL_FAILED_EQUIPPED_ITEM_CLASS_OFFHAND = 30,
|
||||
SPELL_FAILED_ERROR = 31,
|
||||
SPELL_FAILED_FIZZLE = 32,
|
||||
SPELL_FAILED_FLEEING = 33,
|
||||
SPELL_FAILED_FOOD_LOWLEVEL = 34,
|
||||
SPELL_FAILED_HIGHLEVEL = 35,
|
||||
SPELL_FAILED_HUNGER_SATIATED = 36,
|
||||
SPELL_FAILED_IMMUNE = 37,
|
||||
SPELL_FAILED_INCORRECT_AREA = 38,
|
||||
SPELL_FAILED_INTERRUPTED = 39,
|
||||
SPELL_FAILED_INTERRUPTED_COMBAT = 40,
|
||||
SPELL_FAILED_ITEM_ALREADY_ENCHANTED = 41,
|
||||
SPELL_FAILED_ITEM_GONE = 42,
|
||||
SPELL_FAILED_ITEM_NOT_FOUND = 43,
|
||||
SPELL_FAILED_ITEM_NOT_READY = 44,
|
||||
SPELL_FAILED_LEVEL_REQUIREMENT = 45,
|
||||
SPELL_FAILED_LINE_OF_SIGHT = 46,
|
||||
SPELL_FAILED_LOWLEVEL = 47,
|
||||
SPELL_FAILED_LOW_CASTLEVEL = 48,
|
||||
SPELL_FAILED_MAINHAND_EMPTY = 49,
|
||||
SPELL_FAILED_MOVING = 50,
|
||||
SPELL_FAILED_NEED_AMMO = 51,
|
||||
SPELL_FAILED_NEED_AMMO_POUCH = 52,
|
||||
SPELL_FAILED_NEED_EXOTIC_AMMO = 53,
|
||||
SPELL_FAILED_NEED_MORE_ITEMS = 54,
|
||||
SPELL_FAILED_NOPATH = 55,
|
||||
SPELL_FAILED_NOT_BEHIND = 56,
|
||||
SPELL_FAILED_NOT_FISHABLE = 57,
|
||||
SPELL_FAILED_NOT_FLYING = 58,
|
||||
SPELL_FAILED_NOT_HERE = 59,
|
||||
SPELL_FAILED_NOT_INFRONT = 60,
|
||||
SPELL_FAILED_NOT_IN_CONTROL = 61,
|
||||
SPELL_FAILED_NOT_KNOWN = 62,
|
||||
SPELL_FAILED_NOT_MOUNTED = 63,
|
||||
SPELL_FAILED_NOT_ON_TAXI = 64,
|
||||
SPELL_FAILED_NOT_ON_TRANSPORT = 65,
|
||||
SPELL_FAILED_NOT_READY = 66,
|
||||
SPELL_FAILED_NOT_SHAPESHIFT = 67,
|
||||
SPELL_FAILED_NOT_STANDING = 68,
|
||||
SPELL_FAILED_NOT_TRADEABLE = 69,
|
||||
SPELL_FAILED_NOT_TRADING = 70,
|
||||
SPELL_FAILED_NOT_UNSHEATHED = 71,
|
||||
SPELL_FAILED_NOT_WHILE_GHOST = 72,
|
||||
SPELL_FAILED_NOT_WHILE_LOOTING = 73,
|
||||
SPELL_FAILED_NO_AMMO = 74,
|
||||
SPELL_FAILED_NO_CHARGES_REMAIN = 75,
|
||||
SPELL_FAILED_NO_CHAMPION = 76,
|
||||
SPELL_FAILED_NO_COMBO_POINTS = 77,
|
||||
SPELL_FAILED_NO_DUELING = 78,
|
||||
SPELL_FAILED_NO_ENDURANCE = 79,
|
||||
SPELL_FAILED_NO_FISH = 80,
|
||||
SPELL_FAILED_NO_ITEMS_WHILE_SHAPESHIFTED = 81,
|
||||
SPELL_FAILED_NO_MOUNTS_ALLOWED = 82,
|
||||
SPELL_FAILED_NO_PET = 83,
|
||||
SPELL_FAILED_NO_POWER = 84,
|
||||
SPELL_FAILED_NOTHING_TO_DISPEL = 85,
|
||||
SPELL_FAILED_NOTHING_TO_STEAL = 86,
|
||||
SPELL_FAILED_ONLY_ABOVEWATER = 87,
|
||||
SPELL_FAILED_ONLY_DAYTIME = 88,
|
||||
SPELL_FAILED_ONLY_INDOORS = 89,
|
||||
SPELL_FAILED_ONLY_MOUNTED = 90,
|
||||
SPELL_FAILED_ONLY_NIGHTTIME = 91,
|
||||
SPELL_FAILED_ONLY_OUTDOORS = 92,
|
||||
SPELL_FAILED_ONLY_SHAPESHIFT = 93,
|
||||
SPELL_FAILED_ONLY_STEALTHED = 94,
|
||||
SPELL_FAILED_ONLY_UNDERWATER = 95,
|
||||
SPELL_FAILED_OUT_OF_RANGE = 96,
|
||||
SPELL_FAILED_PACIFIED = 97,
|
||||
SPELL_FAILED_POSSESSED = 98,
|
||||
SPELL_FAILED_REAGENTS = 99,
|
||||
SPELL_FAILED_REQUIRES_AREA = 100,
|
||||
SPELL_FAILED_REQUIRES_SPELL_FOCUS = 101,
|
||||
SPELL_FAILED_ROOTED = 102,
|
||||
SPELL_FAILED_SILENCED = 103,
|
||||
SPELL_FAILED_SPELL_IN_PROGRESS = 104,
|
||||
SPELL_FAILED_SPELL_LEARNED = 105,
|
||||
SPELL_FAILED_SPELL_UNAVAILABLE = 106,
|
||||
SPELL_FAILED_STUNNED = 107,
|
||||
SPELL_FAILED_TARGETS_DEAD = 108,
|
||||
SPELL_FAILED_TARGET_AFFECTING_COMBAT = 109,
|
||||
SPELL_FAILED_TARGET_AURASTATE = 110,
|
||||
SPELL_FAILED_TARGET_DUELING = 111,
|
||||
SPELL_FAILED_TARGET_ENEMY = 112,
|
||||
SPELL_FAILED_TARGET_ENRAGED = 113,
|
||||
SPELL_FAILED_TARGET_FRIENDLY = 114,
|
||||
SPELL_FAILED_TARGET_IN_COMBAT = 115,
|
||||
SPELL_FAILED_TARGET_IS_PLAYER = 116,
|
||||
SPELL_FAILED_TARGET_IS_PLAYER_CONTROLLED = 117,
|
||||
SPELL_FAILED_TARGET_NOT_DEAD = 118,
|
||||
SPELL_FAILED_TARGET_NOT_IN_PARTY = 119,
|
||||
SPELL_FAILED_TARGET_NOT_LOOTED = 120,
|
||||
SPELL_FAILED_TARGET_NOT_PLAYER = 121,
|
||||
SPELL_FAILED_TARGET_NO_POCKETS = 122,
|
||||
SPELL_FAILED_TARGET_NO_WEAPONS = 123,
|
||||
SPELL_FAILED_TARGET_NO_RANGED_WEAPONS = 124,
|
||||
SPELL_FAILED_TARGET_UNSKINNABLE = 125,
|
||||
SPELL_FAILED_THIRST_SATIATED = 126,
|
||||
SPELL_FAILED_TOO_CLOSE = 127,
|
||||
SPELL_FAILED_TOO_MANY_OF_ITEM = 128,
|
||||
SPELL_FAILED_TOTEM_CATEGORY = 129,
|
||||
SPELL_FAILED_TOTEMS = 130,
|
||||
SPELL_FAILED_TRY_AGAIN = 131,
|
||||
SPELL_FAILED_UNIT_NOT_BEHIND = 132,
|
||||
SPELL_FAILED_UNIT_NOT_INFRONT = 133,
|
||||
SPELL_FAILED_WRONG_PET_FOOD = 134,
|
||||
SPELL_FAILED_NOT_WHILE_FATIGUED = 135,
|
||||
SPELL_FAILED_TARGET_NOT_IN_INSTANCE = 136,
|
||||
SPELL_FAILED_NOT_WHILE_TRADING = 137,
|
||||
SPELL_FAILED_TARGET_NOT_IN_RAID = 138,
|
||||
SPELL_FAILED_TARGET_FREEFORALL = 139,
|
||||
SPELL_FAILED_NO_EDIBLE_CORPSES = 140,
|
||||
SPELL_FAILED_ONLY_BATTLEGROUNDS = 141,
|
||||
SPELL_FAILED_TARGET_NOT_GHOST = 142,
|
||||
SPELL_FAILED_TRANSFORM_UNUSABLE = 143,
|
||||
SPELL_FAILED_WRONG_WEATHER = 144,
|
||||
SPELL_FAILED_DAMAGE_IMMUNE = 145,
|
||||
SPELL_FAILED_PREVENTED_BY_MECHANIC = 146,
|
||||
SPELL_FAILED_PLAY_TIME = 147,
|
||||
SPELL_FAILED_REPUTATION = 148,
|
||||
SPELL_FAILED_MIN_SKILL = 149,
|
||||
SPELL_FAILED_NOT_IN_ARENA = 150,
|
||||
SPELL_FAILED_NOT_ON_SHAPESHIFT = 151,
|
||||
SPELL_FAILED_NOT_ON_STEALTHED = 152,
|
||||
SPELL_FAILED_NOT_ON_DAMAGE_IMMUNE = 153,
|
||||
SPELL_FAILED_NOT_ON_MOUNTED = 154,
|
||||
SPELL_FAILED_TOO_SHALLOW = 155,
|
||||
SPELL_FAILED_TARGET_NOT_IN_SANCTUARY = 156,
|
||||
SPELL_FAILED_TARGET_IS_TRIVIAL = 157,
|
||||
SPELL_FAILED_BM_OR_INVISGOD = 158,
|
||||
SPELL_FAILED_EXPERT_RIDING_REQUIREMENT = 159,
|
||||
SPELL_FAILED_ARTISAN_RIDING_REQUIREMENT = 160,
|
||||
SPELL_FAILED_NOT_IDLE = 161,
|
||||
SPELL_FAILED_NOT_INACTIVE = 162,
|
||||
SPELL_FAILED_PARTIAL_PLAYTIME = 163,
|
||||
SPELL_FAILED_NO_PLAYTIME = 164,
|
||||
SPELL_FAILED_NOT_IN_BATTLEGROUND = 165,
|
||||
SPELL_FAILED_NOT_IN_RAID_INSTANCE = 166,
|
||||
SPELL_FAILED_ONLY_IN_ARENA = 167,
|
||||
SPELL_FAILED_TARGET_LOCKED_TO_RAID_INSTANCE = 168,
|
||||
SPELL_FAILED_ON_USE_ENCHANT = 169,
|
||||
SPELL_FAILED_NOT_ON_GROUND = 170,
|
||||
SPELL_FAILED_CUSTOM_ERROR = 171,
|
||||
SPELL_FAILED_CANT_DO_THAT_RIGHT_NOW = 172,
|
||||
SPELL_FAILED_TOO_MANY_SOCKETS = 173,
|
||||
SPELL_FAILED_INVALID_GLYPH = 174,
|
||||
SPELL_FAILED_UNIQUE_GLYPH = 175,
|
||||
SPELL_FAILED_GLYPH_SOCKET_LOCKED = 176,
|
||||
SPELL_FAILED_NO_VALID_TARGETS = 177,
|
||||
SPELL_FAILED_ITEM_AT_MAX_CHARGES = 178,
|
||||
SPELL_FAILED_NOT_IN_BARBERSHOP = 179,
|
||||
SPELL_FAILED_FISHING_TOO_LOW = 180,
|
||||
SPELL_FAILED_UNKNOWN = 181,
|
||||
SPELL_FAILED_AFFECTING_COMBAT = 0x00,
|
||||
SPELL_FAILED_ALREADY_AT_FULL_HEALTH = 0x01,
|
||||
SPELL_FAILED_ALREADY_AT_FULL_MANA = 0x02,
|
||||
SPELL_FAILED_ALREADY_AT_FULL_POWER = 0x03,
|
||||
SPELL_FAILED_ALREADY_BEING_TAMED = 0x04,
|
||||
SPELL_FAILED_ALREADY_HAVE_CHARM = 0x05,
|
||||
SPELL_FAILED_ALREADY_HAVE_SUMMON = 0x06,
|
||||
SPELL_FAILED_ALREADY_OPEN = 0x07,
|
||||
SPELL_FAILED_AURA_BOUNCED = 0x08,
|
||||
SPELL_FAILED_AUTOTRACK_INTERRUPTED = 0x09,
|
||||
SPELL_FAILED_BAD_IMPLICIT_TARGETS = 0x0A,
|
||||
SPELL_FAILED_BAD_TARGETS = 0x0B,
|
||||
SPELL_FAILED_CANT_BE_CHARMED = 0x0C,
|
||||
SPELL_FAILED_CANT_BE_DISENCHANTED = 0x0D,
|
||||
SPELL_FAILED_CANT_BE_DISENCHANTED_SKILL = 0x0E,
|
||||
SPELL_FAILED_CANT_BE_MILLED = 0x0F,
|
||||
SPELL_FAILED_CANT_BE_PROSPECTED = 0x10,
|
||||
SPELL_FAILED_CANT_CAST_ON_TAPPED = 0x11,
|
||||
SPELL_FAILED_CANT_DUEL_WHILE_INVISIBLE = 0x12,
|
||||
SPELL_FAILED_CANT_DUEL_WHILE_STEALTHED = 0x13,
|
||||
SPELL_FAILED_CANT_STEALTH = 0x14,
|
||||
SPELL_FAILED_CASTER_AURASTATE = 0x15,
|
||||
SPELL_FAILED_CASTER_DEAD = 0x16,
|
||||
SPELL_FAILED_CHARMED = 0x17,
|
||||
SPELL_FAILED_CHEST_IN_USE = 0x18,
|
||||
SPELL_FAILED_CONFUSED = 0x19,
|
||||
SPELL_FAILED_DONT_REPORT = 0x1A,
|
||||
SPELL_FAILED_EQUIPPED_ITEM = 0x1B,
|
||||
SPELL_FAILED_EQUIPPED_ITEM_CLASS = 0x1C,
|
||||
SPELL_FAILED_EQUIPPED_ITEM_CLASS_MAINHAND = 0x1D,
|
||||
SPELL_FAILED_EQUIPPED_ITEM_CLASS_OFFHAND = 0x1E,
|
||||
SPELL_FAILED_ERROR = 0x1F,
|
||||
SPELL_FAILED_FIZZLE = 0x20,
|
||||
SPELL_FAILED_FLEEING = 0x21,
|
||||
SPELL_FAILED_FOOD_LOWLEVEL = 0x22,
|
||||
SPELL_FAILED_HIGHLEVEL = 0x23,
|
||||
SPELL_FAILED_HUNGER_SATIATED = 0x24,
|
||||
SPELL_FAILED_IMMUNE = 0x25,
|
||||
SPELL_FAILED_INCORRECT_AREA = 0x26,
|
||||
SPELL_FAILED_INTERRUPTED = 0x27,
|
||||
SPELL_FAILED_INTERRUPTED_COMBAT = 0x28,
|
||||
SPELL_FAILED_ITEM_ALREADY_ENCHANTED = 0x29,
|
||||
SPELL_FAILED_ITEM_GONE = 0x2A,
|
||||
SPELL_FAILED_ITEM_NOT_FOUND = 0x2B,
|
||||
SPELL_FAILED_ITEM_NOT_READY = 0x2C,
|
||||
SPELL_FAILED_LEVEL_REQUIREMENT = 0x2D,
|
||||
SPELL_FAILED_LINE_OF_SIGHT = 0x2E,
|
||||
SPELL_FAILED_LOWLEVEL = 0x2F,
|
||||
SPELL_FAILED_LOW_CASTLEVEL = 0x30,
|
||||
SPELL_FAILED_MAINHAND_EMPTY = 0x31,
|
||||
SPELL_FAILED_MOVING = 0x32,
|
||||
SPELL_FAILED_NEED_AMMO = 0x33,
|
||||
SPELL_FAILED_NEED_AMMO_POUCH = 0x34,
|
||||
SPELL_FAILED_NEED_EXOTIC_AMMO = 0x35,
|
||||
SPELL_FAILED_NEED_MORE_ITEMS = 0x36,
|
||||
SPELL_FAILED_NOPATH = 0x37,
|
||||
SPELL_FAILED_NOT_BEHIND = 0x38,
|
||||
SPELL_FAILED_NOT_FISHABLE = 0x39,
|
||||
SPELL_FAILED_NOT_FLYING = 0x3A,
|
||||
SPELL_FAILED_NOT_HERE = 0x3B,
|
||||
SPELL_FAILED_NOT_INFRONT = 0x3C,
|
||||
SPELL_FAILED_NOT_IN_CONTROL = 0x3D,
|
||||
SPELL_FAILED_NOT_KNOWN = 0x3E,
|
||||
SPELL_FAILED_NOT_MOUNTED = 0x3F,
|
||||
SPELL_FAILED_NOT_ON_TAXI = 0x40,
|
||||
SPELL_FAILED_NOT_ON_TRANSPORT = 0x41,
|
||||
SPELL_FAILED_NOT_READY = 0x42,
|
||||
SPELL_FAILED_NOT_SHAPESHIFT = 0x43,
|
||||
SPELL_FAILED_NOT_STANDING = 0x44,
|
||||
SPELL_FAILED_NOT_TRADEABLE = 0x45,
|
||||
SPELL_FAILED_NOT_TRADING = 0x46,
|
||||
SPELL_FAILED_NOT_UNSHEATHED = 0x47,
|
||||
SPELL_FAILED_NOT_WHILE_GHOST = 0x48,
|
||||
SPELL_FAILED_NOT_WHILE_LOOTING = 0x49,
|
||||
SPELL_FAILED_NO_AMMO = 0x4A,
|
||||
SPELL_FAILED_NO_CHARGES_REMAIN = 0x4B,
|
||||
SPELL_FAILED_NO_CHAMPION = 0x4C,
|
||||
SPELL_FAILED_NO_COMBO_POINTS = 0x4D,
|
||||
SPELL_FAILED_NO_DUELING = 0x4E,
|
||||
SPELL_FAILED_NO_ENDURANCE = 0x4F,
|
||||
SPELL_FAILED_NO_FISH = 0x50,
|
||||
SPELL_FAILED_NO_ITEMS_WHILE_SHAPESHIFTED = 0x51,
|
||||
SPELL_FAILED_NO_MOUNTS_ALLOWED = 0x52,
|
||||
SPELL_FAILED_NO_PET = 0x53,
|
||||
SPELL_FAILED_NO_POWER = 0x54,
|
||||
SPELL_FAILED_NOTHING_TO_DISPEL = 0x55,
|
||||
SPELL_FAILED_NOTHING_TO_STEAL = 0x56,
|
||||
SPELL_FAILED_ONLY_ABOVEWATER = 0x57,
|
||||
SPELL_FAILED_ONLY_DAYTIME = 0x58,
|
||||
SPELL_FAILED_ONLY_INDOORS = 0x59,
|
||||
SPELL_FAILED_ONLY_MOUNTED = 0x5A,
|
||||
SPELL_FAILED_ONLY_NIGHTTIME = 0x5B,
|
||||
SPELL_FAILED_ONLY_OUTDOORS = 0x5C,
|
||||
SPELL_FAILED_ONLY_SHAPESHIFT = 0x5D,
|
||||
SPELL_FAILED_ONLY_STEALTHED = 0x5E,
|
||||
SPELL_FAILED_ONLY_UNDERWATER = 0x5F,
|
||||
SPELL_FAILED_OUT_OF_RANGE = 0x60,
|
||||
SPELL_FAILED_PACIFIED = 0x61,
|
||||
SPELL_FAILED_POSSESSED = 0x62,
|
||||
SPELL_FAILED_REAGENTS = 0x63,
|
||||
SPELL_FAILED_REQUIRES_AREA = 0x64,
|
||||
SPELL_FAILED_REQUIRES_SPELL_FOCUS = 0x65,
|
||||
SPELL_FAILED_ROOTED = 0x66,
|
||||
SPELL_FAILED_SILENCED = 0x67,
|
||||
SPELL_FAILED_SPELL_IN_PROGRESS = 0x68,
|
||||
SPELL_FAILED_SPELL_LEARNED = 0x69,
|
||||
SPELL_FAILED_SPELL_UNAVAILABLE = 0x6A,
|
||||
SPELL_FAILED_STUNNED = 0x6B,
|
||||
SPELL_FAILED_TARGETS_DEAD = 0x6C,
|
||||
SPELL_FAILED_TARGET_AFFECTING_COMBAT = 0x6D,
|
||||
SPELL_FAILED_TARGET_AURASTATE = 0x6E,
|
||||
SPELL_FAILED_TARGET_DUELING = 0x6F,
|
||||
SPELL_FAILED_TARGET_ENEMY = 0x70,
|
||||
SPELL_FAILED_TARGET_ENRAGED = 0x71,
|
||||
SPELL_FAILED_TARGET_FRIENDLY = 0x72,
|
||||
SPELL_FAILED_TARGET_IN_COMBAT = 0x73,
|
||||
SPELL_FAILED_TARGET_IS_PLAYER = 0x74,
|
||||
SPELL_FAILED_TARGET_IS_PLAYER_CONTROLLED = 0x75,
|
||||
SPELL_FAILED_TARGET_NOT_DEAD = 0x76,
|
||||
SPELL_FAILED_TARGET_NOT_IN_PARTY = 0x77,
|
||||
SPELL_FAILED_TARGET_NOT_LOOTED = 0x78,
|
||||
SPELL_FAILED_TARGET_NOT_PLAYER = 0x79,
|
||||
SPELL_FAILED_TARGET_NO_POCKETS = 0x7A,
|
||||
SPELL_FAILED_TARGET_NO_WEAPONS = 0x7B,
|
||||
SPELL_FAILED_TARGET_NO_RANGED_WEAPONS = 0x7C,
|
||||
SPELL_FAILED_TARGET_UNSKINNABLE = 0x7D,
|
||||
SPELL_FAILED_THIRST_SATIATED = 0x7E,
|
||||
SPELL_FAILED_TOO_CLOSE = 0x7F,
|
||||
SPELL_FAILED_TOO_MANY_OF_ITEM = 0x80,
|
||||
SPELL_FAILED_TOTEM_CATEGORY = 0x81,
|
||||
SPELL_FAILED_TOTEMS = 0x82,
|
||||
SPELL_FAILED_TRY_AGAIN = 0x83,
|
||||
SPELL_FAILED_UNIT_NOT_BEHIND = 0x84,
|
||||
SPELL_FAILED_UNIT_NOT_INFRONT = 0x85,
|
||||
SPELL_FAILED_WRONG_PET_FOOD = 0x86,
|
||||
SPELL_FAILED_NOT_WHILE_FATIGUED = 0x87,
|
||||
SPELL_FAILED_TARGET_NOT_IN_INSTANCE = 0x88,
|
||||
SPELL_FAILED_NOT_WHILE_TRADING = 0x89,
|
||||
SPELL_FAILED_TARGET_NOT_IN_RAID = 0x8A,
|
||||
SPELL_FAILED_TARGET_FREEFORALL = 0x8B,
|
||||
SPELL_FAILED_NO_EDIBLE_CORPSES = 0x8C,
|
||||
SPELL_FAILED_ONLY_BATTLEGROUNDS = 0x8D,
|
||||
SPELL_FAILED_TARGET_NOT_GHOST = 0x8E,
|
||||
SPELL_FAILED_TRANSFORM_UNUSABLE = 0x8F,
|
||||
SPELL_FAILED_WRONG_WEATHER = 0x90,
|
||||
SPELL_FAILED_DAMAGE_IMMUNE = 0x91,
|
||||
SPELL_FAILED_PREVENTED_BY_MECHANIC = 0x92,
|
||||
SPELL_FAILED_PLAY_TIME = 0x93,
|
||||
SPELL_FAILED_REPUTATION = 0x94,
|
||||
SPELL_FAILED_MIN_SKILL = 0x95,
|
||||
SPELL_FAILED_NOT_IN_ARENA = 0x96,
|
||||
SPELL_FAILED_NOT_ON_SHAPESHIFT = 0x97,
|
||||
SPELL_FAILED_NOT_ON_STEALTHED = 0x98,
|
||||
SPELL_FAILED_NOT_ON_DAMAGE_IMMUNE = 0x99,
|
||||
SPELL_FAILED_NOT_ON_MOUNTED = 0x9A,
|
||||
SPELL_FAILED_TOO_SHALLOW = 0x9B,
|
||||
SPELL_FAILED_TARGET_NOT_IN_SANCTUARY = 0x9C,
|
||||
SPELL_FAILED_TARGET_IS_TRIVIAL = 0x9D,
|
||||
SPELL_FAILED_BM_OR_INVISGOD = 0x9E,
|
||||
SPELL_FAILED_EXPERT_RIDING_REQUIREMENT = 0x9F,
|
||||
SPELL_FAILED_ARTISAN_RIDING_REQUIREMENT = 0xA0,
|
||||
SPELL_FAILED_NOT_IDLE = 0xA1,
|
||||
SPELL_FAILED_NOT_INACTIVE = 0xA2,
|
||||
SPELL_FAILED_PARTIAL_PLAYTIME = 0xA3,
|
||||
SPELL_FAILED_NO_PLAYTIME = 0xA4,
|
||||
SPELL_FAILED_NOT_IN_BATTLEGROUND = 0xA5,
|
||||
SPELL_FAILED_NOT_IN_RAID_INSTANCE = 0xA6,
|
||||
SPELL_FAILED_ONLY_IN_ARENA = 0xA7,
|
||||
SPELL_FAILED_TARGET_LOCKED_TO_RAID_INSTANCE = 0xA8,
|
||||
SPELL_FAILED_ON_USE_ENCHANT = 0xA9,
|
||||
SPELL_FAILED_NOT_ON_GROUND = 0xAA,
|
||||
SPELL_FAILED_CUSTOM_ERROR = 0xAB,
|
||||
SPELL_FAILED_CANT_DO_THAT_RIGHT_NOW = 0xAC,
|
||||
SPELL_FAILED_TOO_MANY_SOCKETS = 0xAD,
|
||||
SPELL_FAILED_INVALID_GLYPH = 0xAE,
|
||||
SPELL_FAILED_UNIQUE_GLYPH = 0xAF,
|
||||
SPELL_FAILED_GLYPH_SOCKET_LOCKED = 0xB0,
|
||||
SPELL_FAILED_NO_VALID_TARGETS = 0xB1,
|
||||
SPELL_FAILED_ITEM_AT_MAX_CHARGES = 0xB2,
|
||||
SPELL_FAILED_NOT_IN_BARBERSHOP = 0xB3,
|
||||
SPELL_FAILED_FISHING_TOO_LOW = 0xB4,
|
||||
SPELL_FAILED_ITEM_ENCHANT_TRADE_WINDOW = 0xB5,
|
||||
SPELL_FAILED_SUMMON_PENDING = 0xB6,
|
||||
SPELL_FAILED_MAX_SOCKETS = 0xB7,
|
||||
SPELL_FAILED_PET_CAN_RENAME = 0xB8,
|
||||
SPELL_FAILED_UNKNOWN = 0xB9,
|
||||
|
||||
SPELL_CAST_OK = 255 //custom value, don't must be send to client
|
||||
SPELL_CAST_OK = 0xFF // custom value, don't must be send to client
|
||||
};
|
||||
|
||||
// Spell aura states
|
||||
@@ -970,7 +974,13 @@ enum Mechanics
|
||||
(1<<MECHANIC_SHACKLE )|(1<<MECHANIC_TURN )|(1<<MECHANIC_HORROR)| \
|
||||
(1<<MECHANIC_DAZE )|(1<<MECHANIC_SAPPED ) )
|
||||
|
||||
// Spell dispel type
|
||||
// Daze and all croud control spells except polymorph are not removed
|
||||
#define MECHANIC_NOT_REMOVED_BY_SHAPESHIFT ( \
|
||||
(1<<MECHANIC_CHARM )|(1<<MECHANIC_DISORIENTED)|(1<<MECHANIC_FEAR )|(1<<MECHANIC_PACIFY )| \
|
||||
(1<<MECHANIC_STUN )|(1<<MECHANIC_FREEZE )|(1<<MECHANIC_BANISH)|(1<<MECHANIC_SHACKLE)| \
|
||||
(1<<MECHANIC_HORROR)|(1<<MECHANIC_TURN )|(1<<MECHANIC_DAZE )|(1<<MECHANIC_SAPPED ) )
|
||||
|
||||
// Spell dispell type
|
||||
enum DispelType
|
||||
{
|
||||
DISPEL_NONE = 0,
|
||||
|
||||
@@ -2222,6 +2222,7 @@ void Spell::SetTargetMap(uint32 i, uint32 cur)
|
||||
case TARGET_UNIT_AREA_ENEMY_DST:
|
||||
case TARGET_UNIT_CONE_ENEMY:
|
||||
case TARGET_UNIT_CONE_ENEMY_UNKNOWN:
|
||||
case TARGET_UNIT_AREA_PATH:
|
||||
radius = GetSpellRadius(m_spellInfo, i, false);
|
||||
targetType = SPELL_TARGETS_ENEMY;
|
||||
break;
|
||||
|
||||
@@ -3235,13 +3235,37 @@ void AuraEffect::HandleAuraModShapeshift(bool apply, bool Real, bool changeAmoun
|
||||
case FORM_FLIGHT_EPIC:
|
||||
case FORM_FLIGHT:
|
||||
case FORM_MOONKIN:
|
||||
{
|
||||
// remove movement affects
|
||||
m_target->RemoveMovementImpairingAuras();
|
||||
/*
|
||||
m_target->RemoveSpellsCausingAura(SPELL_AURA_MOD_ROOT);
|
||||
Unit::AuraList const& slowingAuras = m_target->GetAurasByType(SPELL_AURA_MOD_DECREASE_SPEED);
|
||||
for (Unit::AuraList::const_iterator iter = slowingAuras.begin(); iter != slowingAuras.end();)
|
||||
{
|
||||
SpellEntry const* aurSpellInfo = (*iter)->GetSpellProto();
|
||||
|
||||
// If spell that caused this aura has Croud Control or Daze effect
|
||||
if((GetAllSpellMechanicMask(aurSpellInfo) & MECHANIC_NOT_REMOVED_BY_SHAPESHIFT) ||
|
||||
// some Daze spells have these parameters instead of MECHANIC_DAZE
|
||||
(aurSpellInfo->SpellIconID == 15 && aurSpellInfo->Dispel == 0))
|
||||
{
|
||||
++iter;
|
||||
continue;
|
||||
}
|
||||
|
||||
// All OK, remove aura now
|
||||
m_target->RemoveAurasDueToSpellByCancel(aurSpellInfo->Id);
|
||||
iter = slowingAuras.begin();
|
||||
}
|
||||
*/
|
||||
|
||||
// and polymorphic affects
|
||||
if(m_target->IsPolymorphed())
|
||||
m_target->RemoveAurasDueToSpell(m_target->getTransForm());
|
||||
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
+18
-18
@@ -2483,7 +2483,7 @@ void Spell::EffectSendEvent(uint32 EffectIndex)
|
||||
we do not handle a flag dropping or clicking on flag in battleground by sendevent system
|
||||
*/
|
||||
sLog.outDebug("Spell ScriptStart %u for spellid %u in EffectSendEvent ", m_spellInfo->EffectMiscValue[EffectIndex], m_spellInfo->Id);
|
||||
sWorld.ScriptsStart(sEventScripts, m_spellInfo->EffectMiscValue[EffectIndex], m_caster, focusObject);
|
||||
m_caster->GetMap()->ScriptsStart(sEventScripts, m_spellInfo->EffectMiscValue[EffectIndex], m_caster, focusObject);
|
||||
}
|
||||
|
||||
void Spell::EffectPowerBurn(uint32 i)
|
||||
@@ -2880,31 +2880,31 @@ void Spell::EffectEnergize(uint32 i)
|
||||
Powers power = Powers(m_spellInfo->EffectMiscValue[i]);
|
||||
|
||||
// Some level depends spells
|
||||
int multiplier = 0;
|
||||
int level_multiplier = 0;
|
||||
int level_diff = 0;
|
||||
switch (m_spellInfo->Id)
|
||||
{
|
||||
// Restore Energy
|
||||
case 9512:
|
||||
case 9512: // Restore Energy
|
||||
level_diff = m_caster->getLevel() - 40;
|
||||
multiplier = 2;
|
||||
level_multiplier = 2;
|
||||
break;
|
||||
// Blood Fury
|
||||
case 24571:
|
||||
case 24571: // Blood Fury
|
||||
level_diff = m_caster->getLevel() - 60;
|
||||
multiplier = 10;
|
||||
level_multiplier = 10;
|
||||
break;
|
||||
// Burst of Energy
|
||||
case 24532:
|
||||
case 24532: // Burst of Energy
|
||||
level_diff = m_caster->getLevel() - 60;
|
||||
multiplier = 4;
|
||||
level_multiplier = 4;
|
||||
break;
|
||||
case 31930: // Judgements of the Wise
|
||||
case 63375: // Improved Stormstrike
|
||||
damage = damage * unitTarget->GetCreateMana() / 100;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (level_diff > 0)
|
||||
damage -= multiplier * level_diff;
|
||||
damage -= level_multiplier * level_diff;
|
||||
|
||||
if(damage < 0)
|
||||
return;
|
||||
@@ -2999,7 +2999,7 @@ void Spell::SendLoot(uint64 guid, LootType loottype)
|
||||
case GAMEOBJECT_TYPE_DOOR:
|
||||
case GAMEOBJECT_TYPE_BUTTON:
|
||||
gameObjTarget->UseDoorOrButton();
|
||||
sWorld.ScriptsStart(sGameObjectScripts, gameObjTarget->GetDBTableGUIDLow(), player, gameObjTarget);
|
||||
player->GetMap()->ScriptsStart(sGameObjectScripts, gameObjTarget->GetDBTableGUIDLow(), player, gameObjTarget);
|
||||
return;
|
||||
|
||||
case GAMEOBJECT_TYPE_QUESTGIVER:
|
||||
@@ -3019,7 +3019,7 @@ void Spell::SendLoot(uint64 guid, LootType loottype)
|
||||
if (gameObjTarget->GetGOInfo()->goober.eventId)
|
||||
{
|
||||
sLog.outDebug("Goober ScriptStart id %u for GO %u", gameObjTarget->GetGOInfo()->goober.eventId,gameObjTarget->GetDBTableGUIDLow());
|
||||
sWorld.ScriptsStart(sEventScripts, gameObjTarget->GetGOInfo()->goober.eventId, player, gameObjTarget);
|
||||
player->GetMap()->ScriptsStart(sEventScripts, gameObjTarget->GetGOInfo()->goober.eventId, player, gameObjTarget);
|
||||
gameObjTarget->EventInform(gameObjTarget->GetGOInfo()->goober.eventId);
|
||||
}
|
||||
|
||||
@@ -3030,7 +3030,7 @@ void Spell::SendLoot(uint64 guid, LootType loottype)
|
||||
return;
|
||||
|
||||
Script->GOHello(player, gameObjTarget);
|
||||
sWorld.ScriptsStart(sGameObjectScripts, gameObjTarget->GetDBTableGUIDLow(), player, gameObjTarget);
|
||||
gameObjTarget->GetMap()->ScriptsStart(sGameObjectScripts, gameObjTarget->GetDBTableGUIDLow(), player, gameObjTarget);
|
||||
|
||||
gameObjTarget->AddUniqueUse(player);
|
||||
gameObjTarget->SetLootState(GO_JUST_DEACTIVATED);
|
||||
@@ -3052,7 +3052,7 @@ void Spell::SendLoot(uint64 guid, LootType loottype)
|
||||
if (gameObjTarget->GetGOInfo()->chest.eventId)
|
||||
{
|
||||
sLog.outDebug("Chest ScriptStart id %u for GO %u", gameObjTarget->GetGOInfo()->chest.eventId,gameObjTarget->GetDBTableGUIDLow());
|
||||
sWorld.ScriptsStart(sEventScripts, gameObjTarget->GetGOInfo()->chest.eventId, player, gameObjTarget);
|
||||
player->GetMap()->ScriptsStart(sEventScripts, gameObjTarget->GetGOInfo()->chest.eventId, player, gameObjTarget);
|
||||
}
|
||||
|
||||
// triggering linked GO
|
||||
@@ -5501,7 +5501,7 @@ void Spell::EffectScriptEffect(uint32 effIndex)
|
||||
|
||||
// normal DB scripted effect
|
||||
sLog.outDebug("Spell ScriptStart spellid %u in EffectScriptEffect ", m_spellInfo->Id);
|
||||
sWorld.ScriptsStart(sSpellScripts, m_spellInfo->Id, m_caster, unitTarget);
|
||||
m_caster->GetMap()->ScriptsStart(sSpellScripts, m_spellInfo->Id, m_caster, unitTarget);
|
||||
}
|
||||
|
||||
void Spell::EffectSanctuary(uint32 /*i*/)
|
||||
@@ -5703,7 +5703,7 @@ void Spell::EffectActivateObject(uint32 effect_idx)
|
||||
|
||||
int32 delay_secs = m_spellInfo->EffectMiscValue[effect_idx];
|
||||
|
||||
sWorld.ScriptCommandStart(activateCommand, delay_secs, m_caster, gameObjTarget);
|
||||
gameObjTarget->GetMap()->ScriptCommandStart(activateCommand, delay_secs, m_caster, gameObjTarget);
|
||||
}
|
||||
|
||||
void Spell::EffectApplyGlyph(uint32 i)
|
||||
|
||||
@@ -147,6 +147,7 @@ SpellMgr::SpellMgr()
|
||||
case TARGET_UNIT_CONE_ALLY:
|
||||
case TARGET_UNIT_CONE_ENTRY:
|
||||
case TARGET_UNIT_CONE_ENEMY_UNKNOWN:
|
||||
case TARGET_UNIT_AREA_PATH:
|
||||
SpellTargetType[i] = TARGET_TYPE_AREA_CONE;
|
||||
break;
|
||||
case TARGET_DST_CASTER:
|
||||
@@ -226,6 +227,7 @@ SpellMgr::SpellMgr()
|
||||
case TARGET_UNIT_CONE_ENEMY:
|
||||
case TARGET_UNIT_CONE_ALLY:
|
||||
case TARGET_UNIT_CONE_ENEMY_UNKNOWN:
|
||||
case TARGET_UNIT_AREA_PATH:
|
||||
case TARGET_UNIT_RAID_CASTER:
|
||||
IsAreaEffectTarget[i] = true;
|
||||
break;
|
||||
@@ -3846,6 +3848,7 @@ void SpellMgr::LoadSpellCustomAttr()
|
||||
case 40810: case 43267: case 43268: // Saber Lash
|
||||
case 42384: // Brutal Swipe
|
||||
case 45150: // Meteor Slash
|
||||
case 64422: case 64688: // Sonic Screech
|
||||
mSpellCustomAttr[i] |= SPELL_ATTR_CU_SHARE_DAMAGE;
|
||||
break;
|
||||
case 59725: // Improved Spell Reflection - aoe aura
|
||||
|
||||
@@ -487,7 +487,7 @@ void Transport::CheckForEvent(uint32 entry, uint32 wp_id)
|
||||
{
|
||||
uint32 key = entry*100+wp_id;
|
||||
if(objmgr.TransportEventMap.find(key) != objmgr.TransportEventMap.end())
|
||||
sWorld.ScriptsStart(sEventScripts, objmgr.TransportEventMap[key], this, NULL);
|
||||
GetMap()->ScriptsStart(sEventScripts, objmgr.TransportEventMap[key], this, NULL);
|
||||
}
|
||||
|
||||
void Transport::Update(uint32 /*p_time*/)
|
||||
|
||||
+9
-4
@@ -6202,8 +6202,6 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, AuraEffect* trigger
|
||||
// Judgements of the Wise
|
||||
if (dummySpell->SpellIconID == 3017)
|
||||
{
|
||||
// hardcoded amount
|
||||
basepoints0 = 25 * GetCreatePowers(POWER_MANA)/100;
|
||||
target = this;
|
||||
triggered_spell_id = 31930;
|
||||
// replenishment
|
||||
@@ -7052,6 +7050,7 @@ bool Unit::HandleObsModEnergyAuraProc(Unit *pVictim, uint32 damage, AuraEffect*
|
||||
|
||||
SpellEntry const* triggerEntry = sSpellStore.LookupEntry(triggered_spell_id);
|
||||
|
||||
// Try handle unknown trigger spells
|
||||
if(!triggerEntry)
|
||||
{
|
||||
sLog.outError("Unit::HandleObsModEnergyAuraProc: Spell %u have not existed triggered spell %u",dummySpell->Id,triggered_spell_id);
|
||||
@@ -7872,9 +7871,15 @@ bool Unit::HandleProcTriggerSpell(Unit *pVictim, uint32 damage, AuraEffect* trig
|
||||
((Player*)this)->RemoveSpellCategoryCooldown(1209, true);
|
||||
break;
|
||||
}
|
||||
case 63375: // Improved Stormstrike
|
||||
// Maelstrom Weapon
|
||||
case 53817:
|
||||
{
|
||||
basepoints0 = GetCreateMana() * 0.20f;
|
||||
// have rank dependent proc chance, ignore too often cases
|
||||
// PPM = 2.5 * (rank of talent),
|
||||
uint32 rank = spellmgr.GetSpellRank(auraSpellInfo->Id);
|
||||
// 5 rank -> 100% 4 rank -> 80% and etc from full rate
|
||||
if(!roll_chance_i(20*rank))
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
// Brain Freeze
|
||||
|
||||
@@ -198,7 +198,7 @@ WaypointMovementGenerator<Creature>::Update(Creature &unit, const uint32 &diff)
|
||||
|
||||
//note: disable "start" for mtmap
|
||||
if(node->event_id && rand()%100 < node->event_chance)
|
||||
sWorld.ScriptsStart(sWaypointScripts, node->event_id, &unit, NULL, false);
|
||||
unit.GetMap()->ScriptsStart(sWaypointScripts, node->event_id, &unit, NULL/*, false*/);
|
||||
|
||||
MovementInform(unit);
|
||||
unit.UpdateWaypointID(i_currentNode);
|
||||
|
||||
+20
-861
@@ -63,7 +63,6 @@
|
||||
#include "GridNotifiersImpl.h"
|
||||
#include "CellImpl.h"
|
||||
#include "InstanceSaveMgr.h"
|
||||
#include "WaypointManager.h"
|
||||
#include "Util.h"
|
||||
#include "Language.h"
|
||||
#include "CreatureGroups.h"
|
||||
@@ -83,14 +82,6 @@ float World::m_MaxVisibleDistanceInFlight = DEFAULT_VISIBILITY_DISTANCE;
|
||||
float World::m_VisibleUnitGreyDistance = 0;
|
||||
float World::m_VisibleObjectGreyDistance = 0;
|
||||
|
||||
struct ScriptAction
|
||||
{
|
||||
uint64 sourceGUID;
|
||||
uint64 targetGUID;
|
||||
uint64 ownerGUID; // owner of source if source is item
|
||||
ScriptInfo const* script; // pointer to static script data
|
||||
};
|
||||
|
||||
/// World constructor
|
||||
World::World()
|
||||
{
|
||||
@@ -106,6 +97,7 @@ World::World()
|
||||
m_MaxPlayerCount = 0;
|
||||
m_resultQueue = NULL;
|
||||
m_NextDailyQuestReset = 0;
|
||||
m_scheduledScripts = 0;
|
||||
|
||||
m_defaultDbcLocale = LOCALE_enUS;
|
||||
m_availableDbcLocaleMask = 0;
|
||||
@@ -268,7 +260,7 @@ World::AddSession_ (WorldSession* s)
|
||||
float popu = GetActiveSessionCount (); //updated number of users on the server
|
||||
popu /= pLimit;
|
||||
popu *= 2;
|
||||
LoginDatabase.PExecute ("UPDATE realmlist SET population = '%f' WHERE id = '%d'", popu, realmID);
|
||||
loginDatabase.PExecute ("UPDATE realmlist SET population = '%f' WHERE id = '%d'", popu, realmID);
|
||||
sLog.outDetail ("Server Population (%f).", popu);
|
||||
}
|
||||
}
|
||||
@@ -1180,7 +1172,7 @@ void World::SetInitialWorldSettings()
|
||||
// not send custom type REALM_FFA_PVP to realm list
|
||||
uint32 server_type = IsFFAPvPRealm() ? REALM_TYPE_PVP : getConfig(CONFIG_GAME_TYPE);
|
||||
uint32 realm_zone = getConfig(CONFIG_REALM_ZONE);
|
||||
LoginDatabase.PExecute("UPDATE realmlist SET icon = %u, timezone = %u WHERE id = '%d'", server_type, realm_zone, realmID);
|
||||
loginDatabase.PExecute("UPDATE realmlist SET icon = %u, timezone = %u WHERE id = '%d'", server_type, realm_zone, realmID);
|
||||
|
||||
///- Remove the bones after a restart
|
||||
CharacterDatabase.PExecute("DELETE FROM corpse WHERE corpse_type = '0'");
|
||||
@@ -1535,7 +1527,7 @@ void World::SetInitialWorldSettings()
|
||||
sprintf( isoDate, "%04d-%02d-%02d %02d:%02d:%02d",
|
||||
local.tm_year+1900, local.tm_mon+1, local.tm_mday, local.tm_hour, local.tm_min, local.tm_sec);
|
||||
|
||||
LoginDatabase.PExecute("INSERT INTO uptime (realmid, starttime, startstring, uptime) VALUES('%u', " UI64FMTD ", '%s', 0)",
|
||||
loginDatabase.PExecute("INSERT INTO uptime (realmid, starttime, startstring, uptime) VALUES('%u', " UI64FMTD ", '%s', 0)",
|
||||
realmID, uint64(m_startTime), isoDate);
|
||||
|
||||
m_timers[WUPDATE_OBJECTS].SetInterval(IN_MILISECONDS/2);
|
||||
@@ -1586,7 +1578,7 @@ void World::SetInitialWorldSettings()
|
||||
objmgr.LoadTransportEvents();
|
||||
|
||||
sLog.outString("Deleting expired bans..." );
|
||||
LoginDatabase.Execute("DELETE FROM ip_banned WHERE unbandate<=UNIX_TIMESTAMP() AND unbandate<>bandate");
|
||||
loginDatabase.Execute("DELETE FROM ip_banned WHERE unbandate<=UNIX_TIMESTAMP() AND unbandate<>bandate");
|
||||
|
||||
sLog.outString("Calculate next daily quest reset time..." );
|
||||
InitDailyQuestResetTime();
|
||||
@@ -1769,7 +1761,7 @@ void World::Update(uint32 diff)
|
||||
uint32 maxClientsNum = GetMaxActiveSessionCount();
|
||||
|
||||
m_timers[WUPDATE_UPTIME].Reset();
|
||||
LoginDatabase.PExecute("UPDATE uptime SET uptime = %u, maxplayers = %u WHERE realmid = %u AND starttime = " UI64FMTD, tmpDiff, maxClientsNum, realmID, uint64(m_startTime));
|
||||
loginDatabase.PExecute("UPDATE uptime SET uptime = %u, maxplayers = %u WHERE realmid = %u AND starttime = " UI64FMTD, tmpDiff, maxClientsNum, realmID, uint64(m_startTime));
|
||||
}
|
||||
|
||||
/// <li> Clean logs table
|
||||
@@ -1781,7 +1773,7 @@ void World::Update(uint32 diff)
|
||||
uint32 maxClientsNum = sWorld.GetMaxActiveSessionCount();
|
||||
|
||||
m_timers[WUPDATE_CLEANDB].Reset();
|
||||
LoginDatabase.PExecute("DELETE FROM logs WHERE (time + %u) < "UI64FMTD";",
|
||||
loginDatabase.PExecute("DELETE FROM logs WHERE (time + %u) < "UI64FMTD";",
|
||||
sWorld.getConfig(CONFIG_LOGDB_CLEARTIME), uint64(time(0)));
|
||||
}
|
||||
}
|
||||
@@ -1796,14 +1788,6 @@ void World::Update(uint32 diff)
|
||||
MapManager::Instance().DoDelayedMovesAndRemoves();
|
||||
}*/
|
||||
|
||||
///- Process necessary scripts
|
||||
if (!m_scriptSchedule.empty())
|
||||
{
|
||||
RecordTimeDiff(NULL);
|
||||
ScriptsProcess();
|
||||
RecordTimeDiff("UpdateScriptsProcess");
|
||||
}
|
||||
|
||||
sBattleGroundMgr.Update(diff);
|
||||
RecordTimeDiff("UpdateBattleGroundMgr");
|
||||
|
||||
@@ -1848,831 +1832,6 @@ void World::ForceGameEventUpdate()
|
||||
m_timers[WUPDATE_EVENTS].Reset();
|
||||
}
|
||||
|
||||
/// Put scripts in the execution queue
|
||||
void World::ScriptsStart(ScriptMapMap const& scripts, uint32 id, Object* source, Object* target, bool start)
|
||||
{
|
||||
///- Find the script map
|
||||
ScriptMapMap::const_iterator s = scripts.find(id);
|
||||
if (s == scripts.end())
|
||||
return;
|
||||
|
||||
// prepare static data
|
||||
uint64 sourceGUID = source ? source->GetGUID() : (uint64)0; //some script commands doesn't have source
|
||||
uint64 targetGUID = target ? target->GetGUID() : (uint64)0;
|
||||
uint64 ownerGUID = (source->GetTypeId()==TYPEID_ITEM) ? ((Item*)source)->GetOwnerGUID() : (uint64)0;
|
||||
|
||||
///- Schedule script execution for all scripts in the script map
|
||||
ScriptMap const *s2 = &(s->second);
|
||||
bool immedScript = false;
|
||||
for (ScriptMap::const_iterator iter = s2->begin(); iter != s2->end(); ++iter)
|
||||
{
|
||||
ScriptAction sa;
|
||||
sa.sourceGUID = sourceGUID;
|
||||
sa.targetGUID = targetGUID;
|
||||
sa.ownerGUID = ownerGUID;
|
||||
|
||||
sa.script = &iter->second;
|
||||
m_scriptSchedule.insert(std::pair<time_t, ScriptAction>(m_gameTime + iter->first, sa));
|
||||
if (iter->first == 0)
|
||||
immedScript = true;
|
||||
}
|
||||
///- If one of the effects should be immediate, launch the script execution
|
||||
if (start && immedScript)
|
||||
ScriptsProcess();
|
||||
}
|
||||
|
||||
void World::ScriptCommandStart(ScriptInfo const& script, uint32 delay, Object* source, Object* target)
|
||||
{
|
||||
// NOTE: script record _must_ exist until command executed
|
||||
|
||||
// prepare static data
|
||||
uint64 sourceGUID = source ? source->GetGUID() : (uint64)0;
|
||||
uint64 targetGUID = target ? target->GetGUID() : (uint64)0;
|
||||
uint64 ownerGUID = (source->GetTypeId()==TYPEID_ITEM) ? ((Item*)source)->GetOwnerGUID() : (uint64)0;
|
||||
|
||||
ScriptAction sa;
|
||||
sa.sourceGUID = sourceGUID;
|
||||
sa.targetGUID = targetGUID;
|
||||
sa.ownerGUID = ownerGUID;
|
||||
|
||||
sa.script = &script;
|
||||
m_scriptSchedule.insert(std::pair<time_t, ScriptAction>(m_gameTime + delay, sa));
|
||||
|
||||
///- If effects should be immediate, launch the script execution
|
||||
if(delay == 0)
|
||||
ScriptsProcess();
|
||||
}
|
||||
|
||||
/// Process queued scripts
|
||||
void World::ScriptsProcess()
|
||||
{
|
||||
if (m_scriptSchedule.empty())
|
||||
return;
|
||||
|
||||
///- Process overdue queued scripts
|
||||
std::multimap<time_t, ScriptAction>::iterator iter = m_scriptSchedule.begin();
|
||||
// ok as multimap is a *sorted* associative container
|
||||
while (!m_scriptSchedule.empty() && (iter->first <= m_gameTime))
|
||||
{
|
||||
ScriptAction const& step = iter->second;
|
||||
|
||||
Object* source = NULL;
|
||||
|
||||
if(step.sourceGUID)
|
||||
{
|
||||
switch(GUID_HIPART(step.sourceGUID))
|
||||
{
|
||||
case HIGHGUID_ITEM:
|
||||
// case HIGHGUID_CONTAINER: ==HIGHGUID_ITEM
|
||||
{
|
||||
Player* player = HashMapHolder<Player>::Find(step.ownerGUID);
|
||||
if(player)
|
||||
source = player->GetItemByGuid(step.sourceGUID);
|
||||
break;
|
||||
}
|
||||
case HIGHGUID_UNIT:
|
||||
source = HashMapHolder<Creature>::Find(step.sourceGUID);
|
||||
break;
|
||||
case HIGHGUID_PET:
|
||||
source = HashMapHolder<Pet>::Find(step.sourceGUID);
|
||||
break;
|
||||
case HIGHGUID_VEHICLE:
|
||||
source = HashMapHolder<Vehicle>::Find(step.sourceGUID);
|
||||
break;
|
||||
case HIGHGUID_PLAYER:
|
||||
source = HashMapHolder<Player>::Find(step.sourceGUID);
|
||||
break;
|
||||
case HIGHGUID_GAMEOBJECT:
|
||||
source = HashMapHolder<GameObject>::Find(step.sourceGUID);
|
||||
break;
|
||||
case HIGHGUID_CORPSE:
|
||||
source = HashMapHolder<Corpse>::Find(step.sourceGUID);
|
||||
break;
|
||||
case HIGHGUID_MO_TRANSPORT:
|
||||
for (MapManager::TransportSet::iterator iter = MapManager::Instance().m_Transports.begin(); iter != MapManager::Instance().m_Transports.end(); ++iter)
|
||||
{
|
||||
if((*iter)->GetGUID() == step.sourceGUID)
|
||||
{
|
||||
source = reinterpret_cast<Object*>(*iter);
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
sLog.outError("*_script source with unsupported high guid value %u",GUID_HIPART(step.sourceGUID));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//if(source && !source->IsInWorld()) source = NULL;
|
||||
|
||||
Object* target = NULL;
|
||||
|
||||
if(step.targetGUID)
|
||||
{
|
||||
switch(GUID_HIPART(step.targetGUID))
|
||||
{
|
||||
case HIGHGUID_UNIT:
|
||||
target = HashMapHolder<Creature>::Find(step.targetGUID);
|
||||
break;
|
||||
case HIGHGUID_PET:
|
||||
target = HashMapHolder<Pet>::Find(step.targetGUID);
|
||||
break;
|
||||
case HIGHGUID_VEHICLE:
|
||||
target = HashMapHolder<Vehicle>::Find(step.targetGUID);
|
||||
break;
|
||||
case HIGHGUID_PLAYER: // empty GUID case also
|
||||
target = HashMapHolder<Player>::Find(step.targetGUID);
|
||||
break;
|
||||
case HIGHGUID_GAMEOBJECT:
|
||||
target = HashMapHolder<GameObject>::Find(step.targetGUID);
|
||||
break;
|
||||
case HIGHGUID_CORPSE:
|
||||
target = HashMapHolder<Corpse>::Find(step.targetGUID);
|
||||
break;
|
||||
default:
|
||||
sLog.outError("*_script source with unsupported high guid value %u",GUID_HIPART(step.targetGUID));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//if(target && !target->IsInWorld()) target = NULL;
|
||||
|
||||
switch (step.script->command)
|
||||
{
|
||||
case SCRIPT_COMMAND_TALK:
|
||||
{
|
||||
if(!source)
|
||||
{
|
||||
sLog.outError("SCRIPT_COMMAND_TALK call for NULL creature.");
|
||||
break;
|
||||
}
|
||||
|
||||
if(source->GetTypeId()!=TYPEID_UNIT)
|
||||
{
|
||||
sLog.outError("SCRIPT_COMMAND_TALK call for non-creature (TypeId: %u), skipping.",source->GetTypeId());
|
||||
break;
|
||||
}
|
||||
if(step.script->datalong > 3)
|
||||
{
|
||||
sLog.outError("SCRIPT_COMMAND_TALK invalid chat type (%u), skipping.",step.script->datalong);
|
||||
break;
|
||||
}
|
||||
|
||||
uint64 unit_target = target ? target->GetGUID() : 0;
|
||||
|
||||
//datalong 0=normal say, 1=whisper, 2=yell, 3=emote text
|
||||
switch(step.script->datalong)
|
||||
{
|
||||
case 0: // Say
|
||||
((Creature *)source)->Say(step.script->dataint, LANG_UNIVERSAL, unit_target);
|
||||
break;
|
||||
case 1: // Whisper
|
||||
if(!unit_target)
|
||||
{
|
||||
sLog.outError("SCRIPT_COMMAND_TALK attempt to whisper (%u) NULL, skipping.",step.script->datalong);
|
||||
break;
|
||||
}
|
||||
((Creature *)source)->Whisper(step.script->dataint,unit_target);
|
||||
break;
|
||||
case 2: // Yell
|
||||
((Creature *)source)->Yell(step.script->dataint, LANG_UNIVERSAL, unit_target);
|
||||
break;
|
||||
case 3: // Emote text
|
||||
((Creature *)source)->TextEmote(step.script->dataint, unit_target);
|
||||
break;
|
||||
default:
|
||||
break; // must be already checked at load
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case SCRIPT_COMMAND_EMOTE:
|
||||
if(!source)
|
||||
{
|
||||
sLog.outError("SCRIPT_COMMAND_EMOTE call for NULL creature.");
|
||||
break;
|
||||
}
|
||||
|
||||
if(source->GetTypeId()!=TYPEID_UNIT)
|
||||
{
|
||||
sLog.outError("SCRIPT_COMMAND_EMOTE call for non-creature (TypeId: %u), skipping.",source->GetTypeId());
|
||||
break;
|
||||
}
|
||||
|
||||
((Creature *)source)->HandleEmoteCommand(step.script->datalong);
|
||||
break;
|
||||
case SCRIPT_COMMAND_FIELD_SET:
|
||||
if(!source)
|
||||
{
|
||||
sLog.outError("SCRIPT_COMMAND_FIELD_SET call for NULL object.");
|
||||
break;
|
||||
}
|
||||
if(step.script->datalong <= OBJECT_FIELD_ENTRY || step.script->datalong >= source->GetValuesCount())
|
||||
{
|
||||
sLog.outError("SCRIPT_COMMAND_FIELD_SET call for wrong field %u (max count: %u) in object (TypeId: %u).",
|
||||
step.script->datalong,source->GetValuesCount(),source->GetTypeId());
|
||||
break;
|
||||
}
|
||||
|
||||
source->SetUInt32Value(step.script->datalong, step.script->datalong2);
|
||||
break;
|
||||
case SCRIPT_COMMAND_MOVE_TO:
|
||||
if(!source)
|
||||
{
|
||||
sLog.outError("SCRIPT_COMMAND_MOVE_TO call for NULL creature.");
|
||||
break;
|
||||
}
|
||||
|
||||
if(source->GetTypeId()!=TYPEID_UNIT)
|
||||
{
|
||||
sLog.outError("SCRIPT_COMMAND_MOVE_TO call for non-creature (TypeId: %u), skipping.",source->GetTypeId());
|
||||
break;
|
||||
}
|
||||
((Creature*)source)->SendMonsterMoveWithSpeed(step.script->x, step.script->y, step.script->z, step.script->datalong2 );
|
||||
((Creature*)source)->GetMap()->CreatureRelocation(((Creature*)source), step.script->x, step.script->y, step.script->z, 0);
|
||||
break;
|
||||
case SCRIPT_COMMAND_FLAG_SET:
|
||||
if(!source)
|
||||
{
|
||||
sLog.outError("SCRIPT_COMMAND_FLAG_SET call for NULL object.");
|
||||
break;
|
||||
}
|
||||
if(step.script->datalong <= OBJECT_FIELD_ENTRY || step.script->datalong >= source->GetValuesCount())
|
||||
{
|
||||
sLog.outError("SCRIPT_COMMAND_FLAG_SET call for wrong field %u (max count: %u) in object (TypeId: %u).",
|
||||
step.script->datalong,source->GetValuesCount(),source->GetTypeId());
|
||||
break;
|
||||
}
|
||||
|
||||
source->SetFlag(step.script->datalong, step.script->datalong2);
|
||||
break;
|
||||
case SCRIPT_COMMAND_FLAG_REMOVE:
|
||||
if(!source)
|
||||
{
|
||||
sLog.outError("SCRIPT_COMMAND_FLAG_REMOVE call for NULL object.");
|
||||
break;
|
||||
}
|
||||
if(step.script->datalong <= OBJECT_FIELD_ENTRY || step.script->datalong >= source->GetValuesCount())
|
||||
{
|
||||
sLog.outError("SCRIPT_COMMAND_FLAG_REMOVE call for wrong field %u (max count: %u) in object (TypeId: %u).",
|
||||
step.script->datalong,source->GetValuesCount(),source->GetTypeId());
|
||||
break;
|
||||
}
|
||||
|
||||
source->RemoveFlag(step.script->datalong, step.script->datalong2);
|
||||
break;
|
||||
|
||||
case SCRIPT_COMMAND_TELEPORT_TO:
|
||||
{
|
||||
// accept player in any one from target/source arg
|
||||
if (!target && !source)
|
||||
{
|
||||
sLog.outError("SCRIPT_COMMAND_TELEPORT_TO call for NULL object.");
|
||||
break;
|
||||
}
|
||||
|
||||
// must be only Player
|
||||
if((!target || target->GetTypeId() != TYPEID_PLAYER) && (!source || source->GetTypeId() != TYPEID_PLAYER))
|
||||
{
|
||||
sLog.outError("SCRIPT_COMMAND_TELEPORT_TO call for non-player (TypeIdSource: %u)(TypeIdTarget: %u), skipping.", source ? source->GetTypeId() : 0, target ? target->GetTypeId() : 0);
|
||||
break;
|
||||
}
|
||||
|
||||
Player* pSource = target && target->GetTypeId() == TYPEID_PLAYER ? (Player*)target : (Player*)source;
|
||||
|
||||
pSource->TeleportTo(step.script->datalong, step.script->x, step.script->y, step.script->z, step.script->o);
|
||||
break;
|
||||
}
|
||||
|
||||
case SCRIPT_COMMAND_TEMP_SUMMON_CREATURE:
|
||||
{
|
||||
if(!step.script->datalong) // creature not specified
|
||||
{
|
||||
sLog.outError("SCRIPT_COMMAND_TEMP_SUMMON_CREATURE call for NULL creature.");
|
||||
break;
|
||||
}
|
||||
|
||||
if(!source)
|
||||
{
|
||||
sLog.outError("SCRIPT_COMMAND_TEMP_SUMMON_CREATURE call for NULL world object.");
|
||||
break;
|
||||
}
|
||||
|
||||
WorldObject* summoner = dynamic_cast<WorldObject*>(source);
|
||||
|
||||
if(!summoner)
|
||||
{
|
||||
sLog.outError("SCRIPT_COMMAND_TEMP_SUMMON_CREATURE call for non-WorldObject (TypeId: %u), skipping.",source->GetTypeId());
|
||||
break;
|
||||
}
|
||||
|
||||
float x = step.script->x;
|
||||
float y = step.script->y;
|
||||
float z = step.script->z;
|
||||
float o = step.script->o;
|
||||
|
||||
Creature* pCreature = summoner->SummonCreature(step.script->datalong, x, y, z, o,TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,step.script->datalong2);
|
||||
if (!pCreature)
|
||||
{
|
||||
sLog.outError("SCRIPT_COMMAND_TEMP_SUMMON failed for creature (entry: %u).",step.script->datalong);
|
||||
break;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case SCRIPT_COMMAND_RESPAWN_GAMEOBJECT:
|
||||
{
|
||||
if(!step.script->datalong) // gameobject not specified
|
||||
{
|
||||
sLog.outError("SCRIPT_COMMAND_RESPAWN_GAMEOBJECT call for NULL gameobject.");
|
||||
break;
|
||||
}
|
||||
|
||||
if(!source)
|
||||
{
|
||||
sLog.outError("SCRIPT_COMMAND_RESPAWN_GAMEOBJECT call for NULL world object.");
|
||||
break;
|
||||
}
|
||||
|
||||
WorldObject* summoner = dynamic_cast<WorldObject*>(source);
|
||||
|
||||
if(!summoner)
|
||||
{
|
||||
sLog.outError("SCRIPT_COMMAND_RESPAWN_GAMEOBJECT call for non-WorldObject (TypeId: %u), skipping.",source->GetTypeId());
|
||||
break;
|
||||
}
|
||||
|
||||
GameObject *go = NULL;
|
||||
int32 time_to_despawn = step.script->datalong2<5 ? 5 : (int32)step.script->datalong2;
|
||||
|
||||
CellPair p(Trinity::ComputeCellPair(summoner->GetPositionX(), summoner->GetPositionY()));
|
||||
Cell cell(p);
|
||||
cell.data.Part.reserved = ALL_DISTRICT;
|
||||
|
||||
MaNGOS::GameObjectWithDbGUIDCheck go_check(*summoner,step.script->datalong);
|
||||
MaNGOS::GameObjectSearcher<MaNGOS::GameObjectWithDbGUIDCheck> checker(summoner, go,go_check);
|
||||
|
||||
TypeContainerVisitor<Trinity::GameObjectSearcher<Trinity::GameObjectWithDbGUIDCheck>, GridTypeMapContainer > object_checker(checker);
|
||||
CellLock<GridReadGuard> cell_lock(cell, p);
|
||||
cell_lock->Visit(cell_lock, object_checker, *summoner->GetMap());
|
||||
|
||||
if ( !go )
|
||||
{
|
||||
sLog.outError("SCRIPT_COMMAND_RESPAWN_GAMEOBJECT failed for gameobject(guid: %u).", step.script->datalong);
|
||||
break;
|
||||
}
|
||||
|
||||
if( go->GetGoType()==GAMEOBJECT_TYPE_FISHINGNODE ||
|
||||
go->GetGoType()==GAMEOBJECT_TYPE_DOOR ||
|
||||
go->GetGoType()==GAMEOBJECT_TYPE_BUTTON ||
|
||||
go->GetGoType()==GAMEOBJECT_TYPE_TRAP )
|
||||
{
|
||||
sLog.outError("SCRIPT_COMMAND_RESPAWN_GAMEOBJECT can not be used with gameobject of type %u (guid: %u).", uint32(go->GetGoType()), step.script->datalong);
|
||||
break;
|
||||
}
|
||||
|
||||
if( go->isSpawned() )
|
||||
break; //gameobject already spawned
|
||||
|
||||
go->SetLootState(GO_READY);
|
||||
go->SetRespawnTime(time_to_despawn); //despawn object in ? seconds
|
||||
|
||||
go->GetMap()->Add(go);
|
||||
break;
|
||||
}
|
||||
case SCRIPT_COMMAND_OPEN_DOOR:
|
||||
{
|
||||
if(!step.script->datalong) // door not specified
|
||||
{
|
||||
sLog.outError("SCRIPT_COMMAND_OPEN_DOOR call for NULL door.");
|
||||
break;
|
||||
}
|
||||
|
||||
if(!source)
|
||||
{
|
||||
sLog.outError("SCRIPT_COMMAND_OPEN_DOOR call for NULL unit.");
|
||||
break;
|
||||
}
|
||||
|
||||
if(!source->isType(TYPEMASK_UNIT)) // must be any Unit (creature or player)
|
||||
{
|
||||
sLog.outError("SCRIPT_COMMAND_OPEN_DOOR call for non-unit (TypeId: %u), skipping.",source->GetTypeId());
|
||||
break;
|
||||
}
|
||||
|
||||
Unit* caster = (Unit*)source;
|
||||
|
||||
GameObject *door = NULL;
|
||||
int32 time_to_close = step.script->datalong2 < 15 ? 15 : (int32)step.script->datalong2;
|
||||
|
||||
CellPair p(Trinity::ComputeCellPair(caster->GetPositionX(), caster->GetPositionY()));
|
||||
Cell cell(p);
|
||||
cell.data.Part.reserved = ALL_DISTRICT;
|
||||
|
||||
MaNGOS::GameObjectWithDbGUIDCheck go_check(*caster,step.script->datalong);
|
||||
MaNGOS::GameObjectSearcher<MaNGOS::GameObjectWithDbGUIDCheck> checker(caster,door,go_check);
|
||||
|
||||
TypeContainerVisitor<Trinity::GameObjectSearcher<Trinity::GameObjectWithDbGUIDCheck>, GridTypeMapContainer > object_checker(checker);
|
||||
CellLock<GridReadGuard> cell_lock(cell, p);
|
||||
cell_lock->Visit(cell_lock, object_checker, *caster->GetMap());
|
||||
|
||||
if (!door)
|
||||
{
|
||||
sLog.outError("SCRIPT_COMMAND_OPEN_DOOR failed for gameobject(guid: %u).", step.script->datalong);
|
||||
break;
|
||||
}
|
||||
if (door->GetGoType() != GAMEOBJECT_TYPE_DOOR)
|
||||
{
|
||||
sLog.outError("SCRIPT_COMMAND_OPEN_DOOR failed for non-door(GoType: %u).", door->GetGoType());
|
||||
break;
|
||||
}
|
||||
|
||||
if (door->GetGoState() != GO_STATE_READY)
|
||||
break; //door already open
|
||||
|
||||
door->UseDoorOrButton(time_to_close);
|
||||
|
||||
if(target && target->isType(TYPEMASK_GAMEOBJECT) && ((GameObject*)target)->GetGoType()==GAMEOBJECT_TYPE_BUTTON)
|
||||
((GameObject*)target)->UseDoorOrButton(time_to_close);
|
||||
break;
|
||||
}
|
||||
case SCRIPT_COMMAND_CLOSE_DOOR:
|
||||
{
|
||||
if(!step.script->datalong) // guid for door not specified
|
||||
{
|
||||
sLog.outError("SCRIPT_COMMAND_CLOSE_DOOR call for NULL door.");
|
||||
break;
|
||||
}
|
||||
|
||||
if(!source)
|
||||
{
|
||||
sLog.outError("SCRIPT_COMMAND_CLOSE_DOOR call for NULL unit.");
|
||||
break;
|
||||
}
|
||||
|
||||
if(!source->isType(TYPEMASK_UNIT)) // must be any Unit (creature or player)
|
||||
{
|
||||
sLog.outError("SCRIPT_COMMAND_CLOSE_DOOR call for non-unit (TypeId: %u), skipping.",source->GetTypeId());
|
||||
break;
|
||||
}
|
||||
|
||||
Unit* caster = (Unit*)source;
|
||||
|
||||
GameObject *door = NULL;
|
||||
int32 time_to_open = step.script->datalong2 < 15 ? 15 : (int32)step.script->datalong2;
|
||||
|
||||
CellPair p(Trinity::ComputeCellPair(caster->GetPositionX(), caster->GetPositionY()));
|
||||
Cell cell(p);
|
||||
cell.data.Part.reserved = ALL_DISTRICT;
|
||||
|
||||
MaNGOS::GameObjectWithDbGUIDCheck go_check(*caster,step.script->datalong);
|
||||
MaNGOS::GameObjectSearcher<MaNGOS::GameObjectWithDbGUIDCheck> checker(caster,door,go_check);
|
||||
|
||||
TypeContainerVisitor<Trinity::GameObjectSearcher<Trinity::GameObjectWithDbGUIDCheck>, GridTypeMapContainer > object_checker(checker);
|
||||
CellLock<GridReadGuard> cell_lock(cell, p);
|
||||
cell_lock->Visit(cell_lock, object_checker, *caster->GetMap());
|
||||
|
||||
if ( !door )
|
||||
{
|
||||
sLog.outError("SCRIPT_COMMAND_CLOSE_DOOR failed for gameobject(guid: %u).", step.script->datalong);
|
||||
break;
|
||||
}
|
||||
if ( door->GetGoType() != GAMEOBJECT_TYPE_DOOR )
|
||||
{
|
||||
sLog.outError("SCRIPT_COMMAND_CLOSE_DOOR failed for non-door(GoType: %u).", door->GetGoType());
|
||||
break;
|
||||
}
|
||||
|
||||
if( door->GetGoState() == GO_STATE_READY )
|
||||
break; //door already closed
|
||||
|
||||
door->UseDoorOrButton(time_to_open);
|
||||
|
||||
if(target && target->isType(TYPEMASK_GAMEOBJECT) && ((GameObject*)target)->GetGoType()==GAMEOBJECT_TYPE_BUTTON)
|
||||
((GameObject*)target)->UseDoorOrButton(time_to_open);
|
||||
|
||||
break;
|
||||
}
|
||||
case SCRIPT_COMMAND_QUEST_EXPLORED:
|
||||
{
|
||||
if(!source)
|
||||
{
|
||||
sLog.outError("SCRIPT_COMMAND_QUEST_EXPLORED call for NULL source.");
|
||||
break;
|
||||
}
|
||||
|
||||
if(!target)
|
||||
{
|
||||
sLog.outError("SCRIPT_COMMAND_QUEST_EXPLORED call for NULL target.");
|
||||
break;
|
||||
}
|
||||
|
||||
// when script called for item spell casting then target == (unit or GO) and source is player
|
||||
WorldObject* worldObject;
|
||||
Player* player;
|
||||
|
||||
if(target->GetTypeId()==TYPEID_PLAYER)
|
||||
{
|
||||
if(source->GetTypeId()!=TYPEID_UNIT && source->GetTypeId()!=TYPEID_GAMEOBJECT)
|
||||
{
|
||||
sLog.outError("SCRIPT_COMMAND_QUEST_EXPLORED call for non-creature and non-gameobject (TypeId: %u), skipping.",source->GetTypeId());
|
||||
break;
|
||||
}
|
||||
|
||||
worldObject = (WorldObject*)source;
|
||||
player = (Player*)target;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(target->GetTypeId()!=TYPEID_UNIT && target->GetTypeId()!=TYPEID_GAMEOBJECT)
|
||||
{
|
||||
sLog.outError("SCRIPT_COMMAND_QUEST_EXPLORED call for non-creature and non-gameobject (TypeId: %u), skipping.",target->GetTypeId());
|
||||
break;
|
||||
}
|
||||
|
||||
if(source->GetTypeId()!=TYPEID_PLAYER)
|
||||
{
|
||||
sLog.outError("SCRIPT_COMMAND_QUEST_EXPLORED call for non-player(TypeId: %u), skipping.",source->GetTypeId());
|
||||
break;
|
||||
}
|
||||
|
||||
worldObject = (WorldObject*)target;
|
||||
player = (Player*)source;
|
||||
}
|
||||
|
||||
// quest id and flags checked at script loading
|
||||
if( (worldObject->GetTypeId()!=TYPEID_UNIT || ((Unit*)worldObject)->isAlive()) &&
|
||||
(step.script->datalong2==0 || worldObject->IsWithinDistInMap(player,float(step.script->datalong2))) )
|
||||
player->AreaExploredOrEventHappens(step.script->datalong);
|
||||
else
|
||||
player->FailQuest(step.script->datalong);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case SCRIPT_COMMAND_ACTIVATE_OBJECT:
|
||||
{
|
||||
if(!source)
|
||||
{
|
||||
sLog.outError("SCRIPT_COMMAND_ACTIVATE_OBJECT must have source caster.");
|
||||
break;
|
||||
}
|
||||
|
||||
if(!source->isType(TYPEMASK_UNIT))
|
||||
{
|
||||
sLog.outError("SCRIPT_COMMAND_ACTIVATE_OBJECT source caster isn't unit (TypeId: %u), skipping.",source->GetTypeId());
|
||||
break;
|
||||
}
|
||||
|
||||
if(!target)
|
||||
{
|
||||
sLog.outError("SCRIPT_COMMAND_ACTIVATE_OBJECT call for NULL gameobject.");
|
||||
break;
|
||||
}
|
||||
|
||||
if(target->GetTypeId()!=TYPEID_GAMEOBJECT)
|
||||
{
|
||||
sLog.outError("SCRIPT_COMMAND_ACTIVATE_OBJECT call for non-gameobject (TypeId: %u), skipping.",target->GetTypeId());
|
||||
break;
|
||||
}
|
||||
|
||||
Unit* caster = (Unit*)source;
|
||||
|
||||
GameObject *go = (GameObject*)target;
|
||||
|
||||
go->Use(caster);
|
||||
break;
|
||||
}
|
||||
|
||||
case SCRIPT_COMMAND_REMOVE_AURA:
|
||||
{
|
||||
Object* cmdTarget = step.script->datalong2 ? source : target;
|
||||
|
||||
if(!cmdTarget)
|
||||
{
|
||||
sLog.outError("SCRIPT_COMMAND_REMOVE_AURA call for NULL %s.",step.script->datalong2 ? "source" : "target");
|
||||
break;
|
||||
}
|
||||
|
||||
if(!cmdTarget->isType(TYPEMASK_UNIT))
|
||||
{
|
||||
sLog.outError("SCRIPT_COMMAND_REMOVE_AURA %s isn't unit (TypeId: %u), skipping.",step.script->datalong2 ? "source" : "target",cmdTarget->GetTypeId());
|
||||
break;
|
||||
}
|
||||
|
||||
((Unit*)cmdTarget)->RemoveAurasDueToSpell(step.script->datalong);
|
||||
break;
|
||||
}
|
||||
|
||||
case SCRIPT_COMMAND_CAST_SPELL:
|
||||
{
|
||||
if(!source)
|
||||
{
|
||||
sLog.outError("SCRIPT_COMMAND_CAST_SPELL must have source caster.");
|
||||
break;
|
||||
}
|
||||
|
||||
Object* cmdTarget = step.script->datalong2 & 0x01 ? source : target;
|
||||
|
||||
if(!cmdTarget)
|
||||
{
|
||||
sLog.outError("SCRIPT_COMMAND_CAST_SPELL call for NULL %s.",step.script->datalong2 & 0x01 ? "source" : "target");
|
||||
break;
|
||||
}
|
||||
|
||||
if(!cmdTarget->isType(TYPEMASK_UNIT))
|
||||
{
|
||||
sLog.outError("SCRIPT_COMMAND_CAST_SPELL %s isn't unit (TypeId: %u), skipping.",step.script->datalong2 & 0x01 ? "source" : "target",cmdTarget->GetTypeId());
|
||||
break;
|
||||
}
|
||||
|
||||
Unit* spellTarget = (Unit*)cmdTarget;
|
||||
|
||||
Object* cmdSource = step.script->datalong2 & 0x02 ? target : source;
|
||||
|
||||
if(!cmdSource)
|
||||
{
|
||||
sLog.outError("SCRIPT_COMMAND_CAST_SPELL call for NULL %s.",step.script->datalong2 & 0x02 ? "target" : "source");
|
||||
break;
|
||||
}
|
||||
|
||||
if(!cmdSource->isType(TYPEMASK_UNIT))
|
||||
{
|
||||
sLog.outError("SCRIPT_COMMAND_CAST_SPELL %s isn't unit (TypeId: %u), skipping.",step.script->datalong2 & 0x02 ? "target" : "source", cmdSource->GetTypeId());
|
||||
break;
|
||||
}
|
||||
|
||||
Unit* spellSource = (Unit*)cmdSource;
|
||||
|
||||
//TODO: when GO cast implemented, code below must be updated accordingly to also allow GO spell cast
|
||||
spellSource->CastSpell(spellTarget,step.script->datalong,false);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case SCRIPT_COMMAND_LOAD_PATH:
|
||||
{
|
||||
if(!source)
|
||||
{
|
||||
sLog.outError("SCRIPT_COMMAND_START_MOVE is tried to apply to NON-existing unit.");
|
||||
break;
|
||||
}
|
||||
|
||||
if(!source->isType(TYPEMASK_UNIT))
|
||||
{
|
||||
sLog.outError("SCRIPT_COMMAND_START_MOVE source mover isn't unit (TypeId: %u), skipping.",source->GetTypeId());
|
||||
break;
|
||||
}
|
||||
|
||||
if(!WaypointMgr.GetPath(step.script->datalong))
|
||||
{
|
||||
sLog.outError("SCRIPT_COMMAND_START_MOVE source mover has an invallid path, skipping.", step.script->datalong2);
|
||||
break;
|
||||
}
|
||||
|
||||
dynamic_cast<Unit*>(source)->GetMotionMaster()->MovePath(step.script->datalong, step.script->datalong2);
|
||||
break;
|
||||
}
|
||||
|
||||
case SCRIPT_COMMAND_CALLSCRIPT_TO_UNIT:
|
||||
{
|
||||
if(!step.script->datalong || !step.script->datalong2)
|
||||
{
|
||||
sLog.outError("SCRIPT_COMMAND_CALLSCRIPT calls invallid db_script_id or lowguid not present: skipping.");
|
||||
break;
|
||||
}
|
||||
//our target
|
||||
Creature* target = NULL;
|
||||
|
||||
if(source) //using grid searcher
|
||||
{
|
||||
CellPair p(Trinity::ComputeCellPair(((Unit*)source)->GetPositionX(), ((Unit*)source)->GetPositionY()));
|
||||
Cell cell(p);
|
||||
cell.data.Part.reserved = ALL_DISTRICT;
|
||||
|
||||
//sLog.outDebug("Attempting to find Creature: Db GUID: %i", step.script->datalong);
|
||||
Trinity::CreatureWithDbGUIDCheck target_check(((Unit*)source), step.script->datalong);
|
||||
Trinity::CreatureSearcher<Trinity::CreatureWithDbGUIDCheck> checker(((Unit*)source), target, target_check);
|
||||
|
||||
TypeContainerVisitor<Trinity::CreatureSearcher <Trinity::CreatureWithDbGUIDCheck>, GridTypeMapContainer > unit_checker(checker);
|
||||
CellLock<GridReadGuard> cell_lock(cell, p);
|
||||
cell_lock->Visit(cell_lock, unit_checker, *(((Unit*)source)->GetMap()));
|
||||
}
|
||||
else //check hashmap holders
|
||||
{
|
||||
if(CreatureData const* data = objmgr.GetCreatureData(step.script->datalong))
|
||||
target = ObjectAccessor::GetObjectInWorld<Creature>(data->mapid, data->posX, data->posY, MAKE_NEW_GUID(step.script->datalong, data->id, HIGHGUID_UNIT), target);
|
||||
}
|
||||
//sLog.outDebug("attempting to pass target...");
|
||||
if(!target)
|
||||
break;
|
||||
//sLog.outDebug("target passed");
|
||||
//Lets choose our ScriptMap map
|
||||
ScriptMapMap *datamap = NULL;
|
||||
switch(step.script->dataint)
|
||||
{
|
||||
case 1://QUEST END SCRIPTMAP
|
||||
datamap = &sQuestEndScripts;
|
||||
break;
|
||||
case 2://QUEST START SCRIPTMAP
|
||||
datamap = &sQuestStartScripts;
|
||||
break;
|
||||
case 3://SPELLS SCRIPTMAP
|
||||
datamap = &sSpellScripts;
|
||||
break;
|
||||
case 4://GAMEOBJECTS SCRIPTMAP
|
||||
datamap = &sGameObjectScripts;
|
||||
break;
|
||||
case 5://EVENTS SCRIPTMAP
|
||||
datamap = &sEventScripts;
|
||||
break;
|
||||
case 6://WAYPOINTS SCRIPTMAP
|
||||
datamap = &sWaypointScripts;
|
||||
break;
|
||||
default:
|
||||
sLog.outError("SCRIPT_COMMAND_CALLSCRIPT ERROR: no scriptmap present... ignoring");
|
||||
break;
|
||||
}
|
||||
//if no scriptmap present...
|
||||
if(!datamap)
|
||||
break;
|
||||
|
||||
uint32 script_id = step.script->datalong2;
|
||||
//insert script into schedule but do not start it
|
||||
ScriptsStart(*datamap, script_id, target, NULL, false);
|
||||
break;
|
||||
}
|
||||
|
||||
case SCRIPT_COMMAND_KILL:
|
||||
{
|
||||
if(!source || ((Creature*)source)->isDead())
|
||||
break;
|
||||
|
||||
((Creature*)source)->DealDamage(((Creature*)source), ((Creature*)source)->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false);
|
||||
|
||||
switch(step.script->dataint)
|
||||
{
|
||||
case 0: break; //return false not remove corpse
|
||||
case 1: ((Creature*)source)->RemoveCorpse(); break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case SCRIPT_COMMAND_PLAY_SOUND:
|
||||
{
|
||||
if(!source)
|
||||
{
|
||||
sLog.outError("SCRIPT_COMMAND_PLAY_SOUND call for NULL creature.");
|
||||
break;
|
||||
}
|
||||
|
||||
WorldObject* pSource = dynamic_cast<WorldObject*>(source);
|
||||
if(!pSource)
|
||||
{
|
||||
sLog.outError("SCRIPT_COMMAND_PLAY_SOUND call for non-world object (TypeId: %u), skipping.",source->GetTypeId());
|
||||
break;
|
||||
}
|
||||
|
||||
// bitmask: 0/1=anyone/target, 0/2=with distance dependent
|
||||
Player* pTarget = NULL;
|
||||
if(step.script->datalong2 & 1)
|
||||
{
|
||||
if(!target)
|
||||
{
|
||||
sLog.outError("SCRIPT_COMMAND_PLAY_SOUND in targeted mode call for NULL target.");
|
||||
break;
|
||||
}
|
||||
|
||||
if(target->GetTypeId()!=TYPEID_PLAYER)
|
||||
{
|
||||
sLog.outError("SCRIPT_COMMAND_PLAY_SOUND in targeted mode call for non-player (TypeId: %u), skipping.",target->GetTypeId());
|
||||
break;
|
||||
}
|
||||
|
||||
pTarget = (Player*)target;
|
||||
}
|
||||
|
||||
// bitmask: 0/1=anyone/target, 0/2=with distance dependent
|
||||
if(step.script->datalong2 & 2)
|
||||
pSource->PlayDistanceSound(step.script->datalong,pTarget);
|
||||
else
|
||||
pSource->PlayDirectSound(step.script->datalong,pTarget);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
sLog.outError("Unknown script command %u called.",step.script->command);
|
||||
break;
|
||||
}
|
||||
|
||||
m_scriptSchedule.erase(iter);
|
||||
|
||||
iter = m_scriptSchedule.begin();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/// Send a packet to all players (except self if mentioned)
|
||||
void World::SendGlobalMessage(WorldPacket *packet, WorldSession *self, uint32 team)
|
||||
{
|
||||
@@ -2872,10 +2031,10 @@ void World::KickAllLess(AccountTypes sec)
|
||||
/// Ban an account or ban an IP address, duration will be parsed using TimeStringToSecs if it is positive, otherwise permban
|
||||
BanReturn World::BanAccount(BanMode mode, std::string nameOrIP, std::string duration, std::string reason, std::string author)
|
||||
{
|
||||
LoginDatabase.escape_string(nameOrIP);
|
||||
LoginDatabase.escape_string(reason);
|
||||
loginDatabase.escape_string(nameOrIP);
|
||||
loginDatabase.escape_string(reason);
|
||||
std::string safe_author=author;
|
||||
LoginDatabase.escape_string(safe_author);
|
||||
loginDatabase.escape_string(safe_author);
|
||||
|
||||
uint32 duration_secs = TimeStringToSecs(duration);
|
||||
QueryResult *resultAccounts = NULL; //used for kicking
|
||||
@@ -2885,12 +2044,12 @@ BanReturn World::BanAccount(BanMode mode, std::string nameOrIP, std::string dura
|
||||
{
|
||||
case BAN_IP:
|
||||
//No SQL injection as strings are escaped
|
||||
resultAccounts = LoginDatabase.PQuery("SELECT id FROM account WHERE last_ip = '%s'",nameOrIP.c_str());
|
||||
LoginDatabase.PExecute("INSERT INTO ip_banned VALUES ('%s',UNIX_TIMESTAMP(),UNIX_TIMESTAMP()+%u,'%s','%s')",nameOrIP.c_str(),duration_secs,safe_author.c_str(),reason.c_str());
|
||||
resultAccounts = loginDatabase.PQuery("SELECT id FROM account WHERE last_ip = '%s'",nameOrIP.c_str());
|
||||
loginDatabase.PExecute("INSERT INTO ip_banned VALUES ('%s',UNIX_TIMESTAMP(),UNIX_TIMESTAMP()+%u,'%s','%s')",nameOrIP.c_str(),duration_secs,safe_author.c_str(),reason.c_str());
|
||||
break;
|
||||
case BAN_ACCOUNT:
|
||||
//No SQL injection as string is escaped
|
||||
resultAccounts = LoginDatabase.PQuery("SELECT id FROM account WHERE username = '%s'",nameOrIP.c_str());
|
||||
resultAccounts = loginDatabase.PQuery("SELECT id FROM account WHERE username = '%s'",nameOrIP.c_str());
|
||||
break;
|
||||
case BAN_CHARACTER:
|
||||
//No SQL injection as string is escaped
|
||||
@@ -2917,7 +2076,7 @@ BanReturn World::BanAccount(BanMode mode, std::string nameOrIP, std::string dura
|
||||
if(mode!=BAN_IP)
|
||||
{
|
||||
//No SQL injection as strings are escaped
|
||||
LoginDatabase.PExecute("INSERT INTO account_banned VALUES ('%u', UNIX_TIMESTAMP(), UNIX_TIMESTAMP()+%u, '%s', '%s', '1')",
|
||||
loginDatabase.PExecute("INSERT INTO account_banned VALUES ('%u', UNIX_TIMESTAMP(), UNIX_TIMESTAMP()+%u, '%s', '%s', '1')",
|
||||
account,duration_secs,safe_author.c_str(),reason.c_str());
|
||||
}
|
||||
|
||||
@@ -2936,8 +2095,8 @@ bool World::RemoveBanAccount(BanMode mode, std::string nameOrIP)
|
||||
{
|
||||
if (mode == BAN_IP)
|
||||
{
|
||||
LoginDatabase.escape_string(nameOrIP);
|
||||
LoginDatabase.PExecute("DELETE FROM ip_banned WHERE ip = '%s'",nameOrIP.c_str());
|
||||
loginDatabase.escape_string(nameOrIP);
|
||||
loginDatabase.PExecute("DELETE FROM ip_banned WHERE ip = '%s'",nameOrIP.c_str());
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -2951,7 +2110,7 @@ bool World::RemoveBanAccount(BanMode mode, std::string nameOrIP)
|
||||
return false;
|
||||
|
||||
//NO SQL injection as account is uint32
|
||||
LoginDatabase.PExecute("UPDATE account_banned SET active = '0' WHERE id = '%u'",account);
|
||||
loginDatabase.PExecute("UPDATE account_banned SET active = '0' WHERE id = '%u'",account);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -3149,8 +2308,8 @@ void World::_UpdateRealmCharCount(QueryResult *resultCharCount, uint32 accountId
|
||||
Field *fields = resultCharCount->Fetch();
|
||||
uint32 charCount = fields[0].GetUInt32();
|
||||
delete resultCharCount;
|
||||
LoginDatabase.PExecute("DELETE FROM realmcharacters WHERE acctid= '%d' AND realmid = '%d'", accountId, realmID);
|
||||
LoginDatabase.PExecute("INSERT INTO realmcharacters (numchars, acctid, realmid) VALUES (%u, %u, %u)", charCount, accountId, realmID);
|
||||
loginDatabase.PExecute("DELETE FROM realmcharacters WHERE acctid= '%d' AND realmid = '%d'", accountId, realmID);
|
||||
loginDatabase.PExecute("INSERT INTO realmcharacters (numchars, acctid, realmid) VALUES (%u, %u, %u)", charCount, accountId, realmID);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3213,7 +2372,7 @@ void World::SetPlayerLimit( int32 limit, bool needUpdate )
|
||||
m_playerLimit = limit;
|
||||
|
||||
if(db_update_need)
|
||||
LoginDatabase.PExecute("UPDATE realmlist SET allowedSecurityLevel = '%u' WHERE id = '%d'",uint8(GetPlayerSecurityLimit()),realmID);
|
||||
loginDatabase.PExecute("UPDATE realmlist SET allowedSecurityLevel = '%u' WHERE id = '%d'",uint8(GetPlayerSecurityLimit()),realmID);
|
||||
}
|
||||
|
||||
void World::UpdateMaxSessionCounters()
|
||||
|
||||
+8
-6
@@ -29,6 +29,7 @@
|
||||
#include "Timer.h"
|
||||
#include "Policies/Singleton.h"
|
||||
#include "SharedDefines.h"
|
||||
#include "ace/Atomic_Op.h"
|
||||
|
||||
#include <map>
|
||||
#include <set>
|
||||
@@ -553,9 +554,10 @@ class World
|
||||
BanReturn BanAccount(BanMode mode, std::string nameOrIP, std::string duration, std::string reason, std::string author);
|
||||
bool RemoveBanAccount(BanMode mode, std::string nameOrIP);
|
||||
|
||||
void ScriptsStart(std::map<uint32, std::multimap<uint32, ScriptInfo> > const& scripts, uint32 id, Object* source, Object* target, bool start = true);
|
||||
void ScriptCommandStart(ScriptInfo const& script, uint32 delay, Object* source, Object* target);
|
||||
bool IsScriptScheduled() const { return !m_scriptSchedule.empty(); }
|
||||
uint32 IncreaseScheduledScriptsCount() { return (uint32)++m_scheduledScripts; }
|
||||
uint32 DecreaseScheduledScriptCount() { return (uint32)--m_scheduledScripts; }
|
||||
uint32 DecreaseScheduledScriptCount(size_t count) { return (uint32)(m_scheduledScripts -= count); }
|
||||
bool IsScriptScheduled() const { return m_scheduledScripts > 0; }
|
||||
|
||||
bool IsAllowedMap(uint32 mapid) { return m_forbiddenMapIds.count(mapid) == 0 ;}
|
||||
|
||||
@@ -592,7 +594,6 @@ class World
|
||||
void RecordTimeDiff(const char * text, ...);
|
||||
protected:
|
||||
void _UpdateGameTime();
|
||||
void ScriptsProcess();
|
||||
// callback for UpdateRealmCharacters
|
||||
void _UpdateRealmCharCount(QueryResult *resultCharCount, uint32 accountId);
|
||||
|
||||
@@ -606,6 +607,9 @@ class World
|
||||
|
||||
bool m_isClosed;
|
||||
|
||||
//atomic op counter for active scripts amount
|
||||
ACE_Atomic_Op<ACE_Thread_Mutex, long> m_scheduledScripts;
|
||||
|
||||
time_t m_startTime;
|
||||
time_t m_gameTime;
|
||||
IntervalTimer m_timers[WUPDATE_COUNT];
|
||||
@@ -626,8 +630,6 @@ class World
|
||||
uint32 m_PlayerCount;
|
||||
uint32 m_MaxPlayerCount;
|
||||
|
||||
std::multimap<time_t, ScriptAction> m_scriptSchedule;
|
||||
|
||||
std::string m_newCharString;
|
||||
|
||||
float rate_values[MAX_RATES];
|
||||
|
||||
@@ -53,7 +53,7 @@ m_latency(0), m_TutorialsChanged(false)
|
||||
{
|
||||
m_Address = sock->GetRemoteAddress ();
|
||||
sock->AddReference ();
|
||||
LoginDatabase.PExecute("UPDATE account SET online = 1 WHERE id = %u;", GetAccountId());
|
||||
loginDatabase.PExecute("UPDATE account SET online = 1 WHERE id = %u;", GetAccountId());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -78,7 +78,7 @@ WorldSession::~WorldSession()
|
||||
WorldPacket *packet = _recvQueue.next ();
|
||||
delete packet;
|
||||
}
|
||||
LoginDatabase.PExecute("UPDATE account SET online = 0 WHERE id = %u;", GetAccountId());
|
||||
loginDatabase.PExecute("UPDATE account SET online = 0 WHERE id = %u;", GetAccountId());
|
||||
CharacterDatabase.PExecute("UPDATE characters SET online = 0 WHERE account = %u;", GetAccountId());
|
||||
}
|
||||
|
||||
|
||||
@@ -678,7 +678,7 @@ int WorldSocket::HandleAuthSession (WorldPacket& recvPacket)
|
||||
|
||||
BigNumber K;
|
||||
|
||||
if (recvPacket.size () < (4 + 4 + 1 + 4 + 20))
|
||||
if (recvPacket.size () < (4 + 4 + 1 + 4 + 4 + 20))
|
||||
{
|
||||
sLog.outError ("WorldSocket::HandleAuthSession: wrong packet size");
|
||||
return -1;
|
||||
@@ -700,7 +700,7 @@ int WorldSocket::HandleAuthSession (WorldPacket& recvPacket)
|
||||
recvPacket >> account;
|
||||
recvPacket >> unk3;
|
||||
|
||||
if (recvPacket.size () < (4 + 4 + (account.size () + 1) + 4 + 20))
|
||||
if (recvPacket.size () < (4 + 4 + (account.size () + 1) + 4 + 4 + 20))
|
||||
{
|
||||
sLog.outError ("WorldSocket::HandleAuthSession: wrong packet size second check");
|
||||
return -1;
|
||||
@@ -709,19 +709,20 @@ int WorldSocket::HandleAuthSession (WorldPacket& recvPacket)
|
||||
recvPacket >> clientSeed;
|
||||
recvPacket.read (digest, 20);
|
||||
|
||||
DEBUG_LOG ("WorldSocket::HandleAuthSession: client %u, unk2 %u, account %s, clientseed %u",
|
||||
DEBUG_LOG ("WorldSocket::HandleAuthSession: client %u, unk2 %u, account %s, unk3 %u, clientseed %u",
|
||||
BuiltNumberClient,
|
||||
unk2,
|
||||
account.c_str (),
|
||||
unk3,
|
||||
clientSeed);
|
||||
|
||||
// Get the account information from the realmd database
|
||||
std::string safe_account = account; // Duplicate, else will screw the SHA hash verification below
|
||||
LoginDatabase.escape_string (safe_account);
|
||||
loginDatabase.escape_string (safe_account);
|
||||
// No SQL injection, username escaped.
|
||||
|
||||
QueryResult *result =
|
||||
LoginDatabase.PQuery ("SELECT "
|
||||
loginDatabase.PQuery ("SELECT "
|
||||
"id, " //0
|
||||
"gmlevel, " //1
|
||||
"sessionkey, " //2
|
||||
@@ -786,7 +787,7 @@ int WorldSocket::HandleAuthSession (WorldPacket& recvPacket)
|
||||
vold,
|
||||
vStr);
|
||||
|
||||
LoginDatabase.PExecute ("UPDATE account "
|
||||
loginDatabase.PExecute ("UPDATE account "
|
||||
"SET "
|
||||
"v = '0', "
|
||||
"s = '0' "
|
||||
@@ -843,7 +844,7 @@ int WorldSocket::HandleAuthSession (WorldPacket& recvPacket)
|
||||
|
||||
// Re-check account ban (same check as in realmd)
|
||||
QueryResult *banresult =
|
||||
LoginDatabase.PQuery ("SELECT "
|
||||
loginDatabase.PQuery ("SELECT "
|
||||
"bandate, "
|
||||
"unbandate "
|
||||
"FROM account_banned "
|
||||
@@ -909,9 +910,9 @@ int WorldSocket::HandleAuthSession (WorldPacket& recvPacket)
|
||||
|
||||
// Update the last_ip in the database
|
||||
// No SQL injection, username escaped.
|
||||
LoginDatabase.escape_string (address);
|
||||
loginDatabase.escape_string (address);
|
||||
|
||||
LoginDatabase.PExecute ("UPDATE account "
|
||||
loginDatabase.PExecute ("UPDATE account "
|
||||
"SET last_ip = '%s' "
|
||||
"WHERE username = '%s'",
|
||||
address.c_str (),
|
||||
|
||||
@@ -50,7 +50,7 @@ typedef DatabaseMysql DatabaseType;
|
||||
|
||||
extern DatabaseType WorldDatabase;
|
||||
extern DatabaseType CharacterDatabase;
|
||||
extern DatabaseType LoginDatabase;
|
||||
extern DatabaseType loginDatabase;
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
+2
-2
@@ -359,9 +359,9 @@ void Log::outDB( LogTypes type, const char * str )
|
||||
std::string new_str(str);
|
||||
if (new_str.empty())
|
||||
return;
|
||||
LoginDatabase.escape_string(new_str);
|
||||
loginDatabase.escape_string(new_str);
|
||||
|
||||
LoginDatabase.PExecute("INSERT INTO logs (time, realm, type, string) "
|
||||
loginDatabase.PExecute("INSERT INTO logs (time, realm, type, string) "
|
||||
"VALUES (" UI64FMTD ", %u, %u, '%s');", uint64(time(0)), realm, type, new_str.c_str());
|
||||
}
|
||||
|
||||
|
||||
@@ -446,7 +446,7 @@ namespace VMAP
|
||||
|
||||
//=========================================================
|
||||
/**
|
||||
get height or INVALID_HEIGHT if to hight was calculated
|
||||
get height or INVALID_HEIGHT if to height was calculated
|
||||
*/
|
||||
|
||||
//int gGetHeightCounter = 0;
|
||||
|
||||
@@ -19,12 +19,12 @@
|
||||
## CPP flags for includes, defines, etc.
|
||||
AM_CPPFLAGS = -I$(srcdir)
|
||||
|
||||
## Build world list daemon as standalone program
|
||||
## Build as standalone program
|
||||
bin_PROGRAMS = genrevision
|
||||
genrevision_SOURCES = \
|
||||
genrevision.cpp
|
||||
|
||||
## Link world daemon against the shared library
|
||||
## Link against the shared library
|
||||
genrevision_LDADD =
|
||||
genrevision_LDFLAGS = -L$(libdir)
|
||||
|
||||
|
||||
@@ -239,7 +239,7 @@ bool ChatHandler::HandleAccountOnlineListCommand(const char* /*args*/)
|
||||
///- Get the username, last IP and GM level of each account
|
||||
// No SQL injection. account is uint32.
|
||||
// 0 1 2 3
|
||||
QueryResult *resultLogin = LoginDatabase.PQuery("SELECT username, last_ip, gmlevel, expansion FROM account WHERE id = '%u'",account);
|
||||
QueryResult *resultLogin = loginDatabase.PQuery("SELECT username, last_ip, gmlevel, expansion FROM account WHERE id = '%u'",account);
|
||||
|
||||
if(resultLogin)
|
||||
{
|
||||
|
||||
@@ -59,7 +59,7 @@ int m_ServiceStatus = -1;
|
||||
|
||||
DatabaseType WorldDatabase; ///< Accessor to the world database
|
||||
DatabaseType CharacterDatabase; ///< Accessor to the character database
|
||||
DatabaseType LoginDatabase; ///< Accessor to the realm/login database
|
||||
DatabaseType loginDatabase; ///< Accessor to the realm/login database
|
||||
|
||||
uint32 realmID; ///< Id of the realm
|
||||
|
||||
|
||||
@@ -136,7 +136,7 @@ public:
|
||||
loopCounter = 0;
|
||||
sLog.outDetail ("Ping MySQL to keep connection alive");
|
||||
delete WorldDatabase.Query ("SELECT 1 FROM command LIMIT 1");
|
||||
delete LoginDatabase.Query ("SELECT 1 FROM realmlist LIMIT 1");
|
||||
delete loginDatabase.Query ("SELECT 1 FROM realmlist LIMIT 1");
|
||||
delete CharacterDatabase.Query ("SELECT 1 FROM bugreport LIMIT 1");
|
||||
}
|
||||
}
|
||||
@@ -242,7 +242,7 @@ int Master::Run()
|
||||
t.setPriority ((ACE_Based::Priority )2);
|
||||
|
||||
// set server online
|
||||
LoginDatabase.PExecute("UPDATE realmlist SET color = 0, population = 0 WHERE id = '%d'",realmID);
|
||||
loginDatabase.PExecute("UPDATE realmlist SET color = 0, population = 0 WHERE id = '%d'",realmID);
|
||||
|
||||
#ifdef WIN32
|
||||
if (sConfig.GetBoolDefault("Console.Enable", true) && (m_ServiceStatus == -1)/* need disable console in service mode*/)
|
||||
@@ -333,7 +333,7 @@ int Master::Run()
|
||||
sWorldSocketMgr->Wait ();
|
||||
|
||||
// set server offline
|
||||
LoginDatabase.PExecute("UPDATE realmlist SET color = 2 WHERE id = '%d'",realmID);
|
||||
loginDatabase.PExecute("UPDATE realmlist SET color = 2 WHERE id = '%d'",realmID);
|
||||
|
||||
///- Remove signal handling before leaving
|
||||
_UnhookSignals();
|
||||
@@ -349,7 +349,7 @@ int Master::Run()
|
||||
///- Wait for delay threads to end
|
||||
CharacterDatabase.HaltDelayThread();
|
||||
WorldDatabase.HaltDelayThread();
|
||||
LoginDatabase.HaltDelayThread();
|
||||
loginDatabase.HaltDelayThread();
|
||||
|
||||
sLog.outString( "Halting process..." );
|
||||
|
||||
@@ -438,7 +438,7 @@ bool Master::_StartDB()
|
||||
}
|
||||
|
||||
///- Get login database info from configuration file
|
||||
dbstring = sConfig.GetStringDefault("LoginDatabaseInfo", "");
|
||||
dbstring = sConfig.GetStringDefault("loginDatabaseInfo", "");
|
||||
if(dbstring.empty())
|
||||
{
|
||||
sLog.outError("Login database not specified in configuration file");
|
||||
@@ -446,7 +446,7 @@ bool Master::_StartDB()
|
||||
}
|
||||
|
||||
///- Initialise the login database
|
||||
if(!LoginDatabase.Initialize(dbstring.c_str()))
|
||||
if(!loginDatabase.Initialize(dbstring.c_str()))
|
||||
{
|
||||
sLog.outError("Cannot connect to login database %s",dbstring.c_str());
|
||||
return false;
|
||||
@@ -494,7 +494,7 @@ void Master::clearOnlineAccounts()
|
||||
{
|
||||
// Cleanup online status for characters hosted at current realm
|
||||
/// \todo Only accounts with characters logged on *this* realm should have online status reset. Move the online column from 'account' to 'realmcharacters'?
|
||||
LoginDatabase.PExecute(
|
||||
loginDatabase.PExecute(
|
||||
"UPDATE account SET online = 0 WHERE online > 0 "
|
||||
"AND id IN (SELECT acctid FROM realmcharacters WHERE realmid = '%d')",realmID);
|
||||
|
||||
|
||||
@@ -152,9 +152,9 @@ void RASocket::OnRead()
|
||||
AccountMgr::normalizeString(login);
|
||||
|
||||
///- Escape the Login to allow quotes in names
|
||||
LoginDatabase.escape_string(login);
|
||||
loginDatabase.escape_string(login);
|
||||
|
||||
QueryResult* result = LoginDatabase.PQuery("SELECT gmlevel FROM account WHERE username = '%s'",login.c_str());
|
||||
QueryResult* result = loginDatabase.PQuery("SELECT gmlevel FROM account WHERE username = '%s'",login.c_str());
|
||||
|
||||
///- If the user is not found, deny access
|
||||
if(!result)
|
||||
@@ -193,10 +193,10 @@ void RASocket::OnRead()
|
||||
|
||||
AccountMgr::normalizeString(login);
|
||||
AccountMgr::normalizeString(pw);
|
||||
LoginDatabase.escape_string(login);
|
||||
LoginDatabase.escape_string(pw);
|
||||
loginDatabase.escape_string(login);
|
||||
loginDatabase.escape_string(pw);
|
||||
|
||||
QueryResult *check = LoginDatabase.PQuery(
|
||||
QueryResult *check = loginDatabase.PQuery(
|
||||
"SELECT 1 FROM account WHERE username = '%s' AND sha_pass_hash=SHA1(CONCAT('%s',':','%s'))",
|
||||
login.c_str(), login.c_str(), pw.c_str());
|
||||
|
||||
|
||||
@@ -50,7 +50,7 @@ void WorldRunnable::run()
|
||||
///- Init new SQL thread for the world database
|
||||
WorldDatabase.ThreadStart(); // let thread do safe mySQL requests (one connection call enough)
|
||||
CharacterDatabase.ThreadStart();
|
||||
LoginDatabase.ThreadStart();
|
||||
loginDatabase.ThreadStart();
|
||||
sWorld.InitResultQueue();
|
||||
|
||||
uint32 realCurrTime = 0;
|
||||
@@ -100,5 +100,5 @@ void WorldRunnable::run()
|
||||
///- End the database thread
|
||||
WorldDatabase.ThreadEnd(); // free mySQL thread resources
|
||||
CharacterDatabase.ThreadStart();
|
||||
LoginDatabase.ThreadEnd();
|
||||
loginDatabase.ThreadEnd();
|
||||
}
|
||||
|
||||
@@ -70,6 +70,6 @@ enum LoginResult
|
||||
// others will not and opposite
|
||||
// will only support WoW, WoW:TBC and WoW:WotLK 3.1.3 client build 9947...
|
||||
|
||||
#define EXPECTED_TRINITY_CLIENT_BUILD {9947, 0}
|
||||
#define EXPECTED_MANGOS_CLIENT_BUILD {9947, 0}
|
||||
|
||||
#endif
|
||||
|
||||
+117
-101
@@ -36,7 +36,7 @@
|
||||
|
||||
extern RealmList m_realmList;
|
||||
|
||||
extern DatabaseType LoginDatabase;
|
||||
extern DatabaseType loginDatabase;
|
||||
|
||||
#define ChunkSize 2048
|
||||
|
||||
@@ -112,7 +112,7 @@ typedef struct AUTH_LOGON_PROOF_C
|
||||
uint8 M1[20];
|
||||
uint8 crc_hash[20];
|
||||
uint8 number_of_keys;
|
||||
uint8 unk; // Added in 1.12.x client branch
|
||||
uint8 securityFlags; // 0x00-0x04
|
||||
} sAuthLogonProof_C;
|
||||
/*
|
||||
typedef struct
|
||||
@@ -264,17 +264,11 @@ void AuthSocket::OnRead()
|
||||
|
||||
///- Get the command out of it
|
||||
ibuf.SoftRead((char *)&_cmd, 1); // UQ1: No longer exists in new net code ???
|
||||
//ibuf.Read((char *)&_cmd, 1);
|
||||
/*char *command = (char *)malloc(1);
|
||||
|
||||
ibuf.Read(command, 1);
|
||||
|
||||
_cmd = (uint8)command;*/
|
||||
// assert(0);
|
||||
size_t i;
|
||||
|
||||
///- Circle through known commands and call the correct command handler
|
||||
for (i=0;i<AUTH_TOTAL_COMMANDS; i++)
|
||||
for (i = 0; i < AUTH_TOTAL_COMMANDS; ++i)
|
||||
{
|
||||
if ((uint8)table[i].cmd == _cmd &&
|
||||
(table[i].status == STATUS_CONNECTED ||
|
||||
@@ -292,7 +286,7 @@ void AuthSocket::OnRead()
|
||||
}
|
||||
|
||||
///- Report unknown commands in the debug log
|
||||
if (i==AUTH_TOTAL_COMMANDS)
|
||||
if (i == AUTH_TOTAL_COMMANDS)
|
||||
{
|
||||
DEBUG_LOG("[Auth] got unknown packet %u", (uint32)_cmd);
|
||||
return;
|
||||
@@ -306,13 +300,13 @@ void AuthSocket::_SetVSFields(const std::string& rI)
|
||||
BigNumber I;
|
||||
I.SetHexStr(rI.c_str());
|
||||
|
||||
//In case of leading zeroes in the rI hash, restore them
|
||||
// In case of leading zeros in the rI hash, restore them
|
||||
uint8 mDigest[SHA_DIGEST_LENGTH];
|
||||
memset(mDigest,0,SHA_DIGEST_LENGTH);
|
||||
memset(mDigest, 0, SHA_DIGEST_LENGTH);
|
||||
if (I.GetNumBytes() <= SHA_DIGEST_LENGTH)
|
||||
memcpy(mDigest,I.AsByteArray(),I.GetNumBytes());
|
||||
memcpy(mDigest, I.AsByteArray(), I.GetNumBytes());
|
||||
|
||||
std::reverse(mDigest,mDigest+SHA_DIGEST_LENGTH);
|
||||
std::reverse(mDigest, mDigest + SHA_DIGEST_LENGTH);
|
||||
|
||||
Sha1Hash sha;
|
||||
sha.UpdateData(s.AsByteArray(), s.GetNumBytes());
|
||||
@@ -325,7 +319,7 @@ void AuthSocket::_SetVSFields(const std::string& rI)
|
||||
const char *v_hex, *s_hex;
|
||||
v_hex = v.AsHexStr();
|
||||
s_hex = s.AsHexStr();
|
||||
LoginDatabase.PExecute("UPDATE account SET v = '%s', s = '%s' WHERE username = '%s'",v_hex,s_hex, _safelogin.c_str() );
|
||||
loginDatabase.PExecute("UPDATE account SET v = '%s', s = '%s' WHERE username = '%s'", v_hex, s_hex, _safelogin.c_str() );
|
||||
OPENSSL_free((void*)v_hex);
|
||||
OPENSSL_free((void*)s_hex);
|
||||
}
|
||||
@@ -380,19 +374,19 @@ bool AuthSocket::_HandleLogonChallenge()
|
||||
|
||||
//Escape the user login to avoid further SQL injection
|
||||
//Memory will be freed on AuthSocket object destruction
|
||||
_safelogin=_login;
|
||||
LoginDatabase.escape_string(_safelogin);
|
||||
_safelogin = _login;
|
||||
loginDatabase.escape_string(_safelogin);
|
||||
|
||||
pkt << (uint8) AUTH_LOGON_CHALLENGE;
|
||||
pkt << (uint8) 0x00;
|
||||
|
||||
///- Verify that this IP is not in the ip_banned table
|
||||
// No SQL injection possible (paste the IP address as passed by the socket)
|
||||
LoginDatabase.Execute("DELETE FROM ip_banned WHERE unbandate<=UNIX_TIMESTAMP() AND unbandate<>bandate");
|
||||
loginDatabase.Execute("DELETE FROM ip_banned WHERE unbandate<=UNIX_TIMESTAMP() AND unbandate<>bandate");
|
||||
|
||||
std::string address = GetRemoteAddress();
|
||||
LoginDatabase.escape_string(address);
|
||||
QueryResult *result = LoginDatabase.PQuery( "SELECT * FROM ip_banned WHERE ip = '%s'",address.c_str());
|
||||
loginDatabase.escape_string(address);
|
||||
QueryResult *result = loginDatabase.PQuery( "SELECT * FROM ip_banned WHERE ip = '%s'",address.c_str());
|
||||
if(result)
|
||||
{
|
||||
pkt << (uint8)REALM_AUTH_ACCOUNT_BANNED;
|
||||
@@ -404,7 +398,7 @@ bool AuthSocket::_HandleLogonChallenge()
|
||||
///- Get the account details from the account table
|
||||
// No SQL injection (escaped user name)
|
||||
|
||||
result = LoginDatabase.PQuery("SELECT sha_pass_hash,id,locked,last_ip,gmlevel FROM account WHERE username = '%s'",_safelogin.c_str ());
|
||||
result = loginDatabase.PQuery("SELECT sha_pass_hash,id,locked,last_ip,gmlevel FROM account WHERE username = '%s'",_safelogin.c_str ());
|
||||
if( result )
|
||||
{
|
||||
///- If the IP is 'locked', check that the player comes indeed from the correct IP address
|
||||
@@ -432,9 +426,9 @@ bool AuthSocket::_HandleLogonChallenge()
|
||||
if (!locked)
|
||||
{
|
||||
//set expired bans to inactive
|
||||
LoginDatabase.Execute("UPDATE account_banned SET active = 0 WHERE unbandate<=UNIX_TIMESTAMP() AND unbandate<>bandate");
|
||||
loginDatabase.Execute("UPDATE account_banned SET active = 0 WHERE unbandate<=UNIX_TIMESTAMP() AND unbandate<>bandate");
|
||||
///- If the account is banned, reject the logon attempt
|
||||
QueryResult *banresult = LoginDatabase.PQuery("SELECT bandate,unbandate FROM account_banned WHERE id = %u AND active = 1", (*result)[1].GetUInt32());
|
||||
QueryResult *banresult = loginDatabase.PQuery("SELECT bandate,unbandate FROM account_banned WHERE id = %u AND active = 1", (*result)[1].GetUInt32());
|
||||
if(banresult)
|
||||
{
|
||||
if((*banresult)[0].GetUInt64() == (*banresult)[1].GetUInt64())
|
||||
@@ -457,35 +451,56 @@ bool AuthSocket::_HandleLogonChallenge()
|
||||
_SetVSFields(rI);
|
||||
|
||||
b.SetRand(19 * 8);
|
||||
BigNumber gmod=g.ModExp(b, N);
|
||||
BigNumber gmod = g.ModExp(b, N);
|
||||
B = ((v * 3) + gmod) % N;
|
||||
|
||||
ASSERT(gmod.GetNumBytes() <= 32);
|
||||
|
||||
BigNumber unk3;
|
||||
unk3.SetRand(16*8);
|
||||
unk3.SetRand(16 * 8);
|
||||
|
||||
///- Fill the response packet with the result
|
||||
pkt << (uint8)REALM_AUTH_SUCCESS;
|
||||
pkt << uint8(REALM_AUTH_SUCCESS);
|
||||
|
||||
// B may be calculated < 32B so we force minnimal length to 32B
|
||||
pkt.append(B.AsByteArray(32), 32); // 32 bytes
|
||||
pkt << (uint8)1;
|
||||
// B may be calculated < 32B so we force minimal length to 32B
|
||||
pkt.append(B.AsByteArray(32), 32); // 32 bytes
|
||||
pkt << uint8(1);
|
||||
pkt.append(g.AsByteArray(), 1);
|
||||
pkt << (uint8)32;
|
||||
pkt << uint8(32);
|
||||
pkt.append(N.AsByteArray(), 32);
|
||||
pkt.append(s.AsByteArray(), s.GetNumBytes()); // 32 bytes
|
||||
pkt.append(unk3.AsByteArray(), 16);
|
||||
pkt << (uint8)0; // Added in 1.12.x client branch
|
||||
uint8 securityFlags = 0;
|
||||
pkt << uint8(securityFlags); // security flags (0x0...0x04)
|
||||
|
||||
if(securityFlags & 0x01) // PIN input
|
||||
{
|
||||
pkt << uint32(0);
|
||||
pkt << uint64(0) << uint64(0); // 16 bytes hash?
|
||||
}
|
||||
|
||||
if(securityFlags & 0x02) // Matrix input
|
||||
{
|
||||
pkt << uint8(0);
|
||||
pkt << uint8(0);
|
||||
pkt << uint8(0);
|
||||
pkt << uint8(0);
|
||||
pkt << uint64(0);
|
||||
}
|
||||
|
||||
if(securityFlags & 0x04) // Security token input
|
||||
{
|
||||
pkt << uint8(1);
|
||||
}
|
||||
|
||||
uint8 secLevel = (*result)[4].GetUInt8();
|
||||
_accountSecurityLevel = secLevel <= SEC_ADMINISTRATOR ? AccountTypes(secLevel) : SEC_ADMINISTRATOR;
|
||||
|
||||
_localizationName.resize(4);
|
||||
for(int i = 0; i <4; ++i)
|
||||
for(int i = 0; i < 4; ++i)
|
||||
_localizationName[i] = ch->country[4-i-1];
|
||||
|
||||
sLog.outBasic("[AuthChallenge] account %s is using '%c%c%c%c' locale (%u)", _login.c_str (), ch->country[3],ch->country[2],ch->country[1],ch->country[0], GetLocaleByName(_localizationName));
|
||||
sLog.outBasic("[AuthChallenge] account %s is using '%c%c%c%c' locale (%u)", _login.c_str (), ch->country[3], ch->country[2], ch->country[1], ch->country[0], GetLocaleByName(_localizationName));
|
||||
}
|
||||
}
|
||||
delete result;
|
||||
@@ -510,13 +525,13 @@ bool AuthSocket::_HandleLogonProof()
|
||||
ibuf.Read((char *)&lp, sizeof(sAuthLogonProof_C));
|
||||
|
||||
///- Check if the client has one of the expected version numbers
|
||||
bool valid_version=false;
|
||||
int accepted_versions[]=EXPECTED_TRINITY_CLIENT_BUILD;
|
||||
for(int i=0;accepted_versions[i];i++)
|
||||
bool valid_version = false;
|
||||
int accepted_versions[] = EXPECTED_MANGOS_CLIENT_BUILD;
|
||||
for(int i = 0; accepted_versions[i]; ++i)
|
||||
{
|
||||
if(_build==accepted_versions[i])
|
||||
if(_build == accepted_versions[i])
|
||||
{
|
||||
valid_version=true;
|
||||
valid_version = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -529,9 +544,9 @@ bool AuthSocket::_HandleLogonProof()
|
||||
// 24 = len("./patches/65535enGB.mpq")+1
|
||||
char tmp[24];
|
||||
// No buffer overflow (fixed length of arguments)
|
||||
sprintf(tmp,"./patches/%d%s.mpq",_build, _localizationName.c_str());
|
||||
// This will be closed at the destruction of the AuthSocket (client deconnection)
|
||||
FILE *pFile=fopen(tmp,"rb");
|
||||
sprintf(tmp, "./patches/%d%s.mpq", _build, _localizationName.c_str());
|
||||
// This will be closed at the destruction of the AuthSocket (client disconnection)
|
||||
FILE *pFile = fopen(tmp, "rb");
|
||||
|
||||
if(!pFile)
|
||||
{
|
||||
@@ -540,37 +555,37 @@ bool AuthSocket::_HandleLogonProof()
|
||||
pkt << (uint8) 0x00;
|
||||
pkt << (uint8) REALM_AUTH_WRONG_BUILD_NUMBER;
|
||||
DEBUG_LOG("[AuthChallenge] %u is not a valid client version!", _build);
|
||||
DEBUG_LOG("[AuthChallenge] Patch %s not found",tmp);
|
||||
DEBUG_LOG("[AuthChallenge] Patch %s not found", tmp);
|
||||
SendBuf((char const*)pkt.contents(), pkt.size());
|
||||
return true;
|
||||
}
|
||||
else // have patch
|
||||
{
|
||||
pPatch=pFile;
|
||||
pPatch = pFile;
|
||||
XFER_INIT xferh;
|
||||
|
||||
///- Get the MD5 hash of the patch file (get it from preloaded Patcher cache or calculate it)
|
||||
if(PatchesCache.GetHash(tmp,(uint8*)&xferh.md5))
|
||||
if(PatchesCache.GetHash(tmp, (uint8*)&xferh.md5))
|
||||
{
|
||||
DEBUG_LOG("\n[AuthChallenge] Found precached patch info for patch %s",tmp);
|
||||
DEBUG_LOG("\n[AuthChallenge] Found precached patch info for patch %s", tmp);
|
||||
}
|
||||
else
|
||||
{ //calculate patch md5
|
||||
printf("\n[AuthChallenge] Patch info for %s was not cached.",tmp);
|
||||
{ // calculate patch md5
|
||||
printf("\n[AuthChallenge] Patch info for %s was not cached.", tmp);
|
||||
PatchesCache.LoadPatchMD5(tmp);
|
||||
PatchesCache.GetHash(tmp,(uint8*)&xferh.md5);
|
||||
PatchesCache.GetHash(tmp, (uint8*)&xferh.md5);
|
||||
}
|
||||
|
||||
///- Send a packet to the client with the file length and MD5 hash
|
||||
uint8 data[2]={AUTH_LOGON_PROOF,REALM_AUTH_UPDATE_CLIENT};
|
||||
SendBuf((const char*)data,sizeof(data));
|
||||
uint8 data[2] = { AUTH_LOGON_PROOF, REALM_AUTH_UPDATE_CLIENT };
|
||||
SendBuf((const char*)data, sizeof(data));
|
||||
|
||||
memcpy(&xferh,"0\x05Patch",7);
|
||||
xferh.cmd=XFER_INITIATE;
|
||||
fseek(pPatch,0,SEEK_END);
|
||||
xferh.file_size=ftell(pPatch);
|
||||
memcpy(&xferh, "0\x05Patch", 7);
|
||||
xferh.cmd = XFER_INITIATE;
|
||||
fseek(pPatch, 0, SEEK_END);
|
||||
xferh.file_size = ftell(pPatch);
|
||||
|
||||
SendBuf((const char*)&xferh,sizeof(xferh));
|
||||
SendBuf((const char*)&xferh, sizeof(xferh));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -591,27 +606,27 @@ bool AuthSocket::_HandleLogonProof()
|
||||
uint8 t1[16];
|
||||
uint8 vK[40];
|
||||
memcpy(t, S.AsByteArray(), 32);
|
||||
for (int i = 0; i < 16; i++)
|
||||
for (int i = 0; i < 16; ++i)
|
||||
{
|
||||
t1[i] = t[i*2];
|
||||
t1[i] = t[i * 2];
|
||||
}
|
||||
sha.Initialize();
|
||||
sha.UpdateData(t1, 16);
|
||||
sha.Finalize();
|
||||
for (int i = 0; i < 20; i++)
|
||||
for (int i = 0; i < 20; ++i)
|
||||
{
|
||||
vK[i*2] = sha.GetDigest()[i];
|
||||
vK[i * 2] = sha.GetDigest()[i];
|
||||
}
|
||||
for (int i = 0; i < 16; i++)
|
||||
for (int i = 0; i < 16; ++i)
|
||||
{
|
||||
t1[i] = t[i*2+1];
|
||||
t1[i] = t[i * 2 + 1];
|
||||
}
|
||||
sha.Initialize();
|
||||
sha.UpdateData(t1, 16);
|
||||
sha.Finalize();
|
||||
for (int i = 0; i < 20; i++)
|
||||
for (int i = 0; i < 20; ++i)
|
||||
{
|
||||
vK[i*2+1] = sha.GetDigest()[i];
|
||||
vK[i * 2 + 1] = sha.GetDigest()[i];
|
||||
}
|
||||
K.SetBinary(vK, 40);
|
||||
|
||||
@@ -624,7 +639,7 @@ bool AuthSocket::_HandleLogonProof()
|
||||
sha.Initialize();
|
||||
sha.UpdateBigNumbers(&g, NULL);
|
||||
sha.Finalize();
|
||||
for (int i = 0; i < 20; i++)
|
||||
for (int i = 0; i < 20; ++i)
|
||||
{
|
||||
hash[i] ^= sha.GetDigest()[i];
|
||||
}
|
||||
@@ -653,7 +668,7 @@ bool AuthSocket::_HandleLogonProof()
|
||||
///- Update the sessionkey, last_ip, last login time and reset number of failed logins in the account table for this account
|
||||
// No SQL injection (escaped user name) and IP address as received by socket
|
||||
const char* K_hex = K.AsHexStr();
|
||||
LoginDatabase.PExecute("UPDATE account SET sessionkey = '%s', last_ip = '%s', last_login = NOW(), locale = '%u', failed_logins = 0 WHERE username = '%s'", K_hex, GetRemoteAddress().c_str(), GetLocaleByName(_localizationName), _safelogin.c_str() );
|
||||
loginDatabase.PExecute("UPDATE account SET sessionkey = '%s', last_ip = '%s', last_login = NOW(), locale = '%u', failed_logins = 0 WHERE username = '%s'", K_hex, GetRemoteAddress().c_str(), GetLocaleByName(_localizationName), _safelogin.c_str() );
|
||||
OPENSSL_free((void*)K_hex);
|
||||
|
||||
///- Finish SRP6 and send the final result to the client
|
||||
@@ -676,17 +691,17 @@ bool AuthSocket::_HandleLogonProof()
|
||||
}
|
||||
else
|
||||
{
|
||||
char data[4]={AUTH_LOGON_PROOF,REALM_AUTH_NO_MATCH,3,0};
|
||||
SendBuf(data,sizeof(data));
|
||||
char data[4]= { AUTH_LOGON_PROOF, REALM_AUTH_NO_MATCH, 3, 0};
|
||||
SendBuf(data, sizeof(data));
|
||||
sLog.outBasic("[AuthChallenge] account %s tried to login with wrong password!",_login.c_str ());
|
||||
|
||||
uint32 MaxWrongPassCount = sConfig.GetIntDefault("WrongPass.MaxCount", 0);
|
||||
if(MaxWrongPassCount > 0)
|
||||
{
|
||||
//Increment number of failed logins by one and if it reaches the limit temporarily ban that account or IP
|
||||
LoginDatabase.PExecute("UPDATE account SET failed_logins = failed_logins + 1 WHERE username = '%s'",_safelogin.c_str());
|
||||
loginDatabase.PExecute("UPDATE account SET failed_logins = failed_logins + 1 WHERE username = '%s'",_safelogin.c_str());
|
||||
|
||||
if(QueryResult *loginfail = LoginDatabase.PQuery("SELECT id, failed_logins FROM account WHERE username = '%s'", _safelogin.c_str()))
|
||||
if(QueryResult *loginfail = loginDatabase.PQuery("SELECT id, failed_logins FROM account WHERE username = '%s'", _safelogin.c_str()))
|
||||
{
|
||||
Field* fields = loginfail->Fetch();
|
||||
uint32 failed_logins = fields[1].GetUInt32();
|
||||
@@ -699,7 +714,7 @@ bool AuthSocket::_HandleLogonProof()
|
||||
if(WrongPassBanType)
|
||||
{
|
||||
uint32 acc_id = fields[0].GetUInt32();
|
||||
LoginDatabase.PExecute("INSERT INTO account_banned VALUES ('%u',UNIX_TIMESTAMP(),UNIX_TIMESTAMP()+'%u','Trinity realmd','Failed login autoban',1)",
|
||||
loginDatabase.PExecute("INSERT INTO account_banned VALUES ('%u',UNIX_TIMESTAMP(),UNIX_TIMESTAMP()+'%u','Trinity realmd','Failed login autoban',1)",
|
||||
acc_id, WrongPassBanTime);
|
||||
sLog.outBasic("[AuthChallenge] account %s got banned for '%u' seconds because it failed to authenticate '%u' times",
|
||||
_login.c_str(), WrongPassBanTime, failed_logins);
|
||||
@@ -707,8 +722,8 @@ bool AuthSocket::_HandleLogonProof()
|
||||
else
|
||||
{
|
||||
std::string current_ip = GetRemoteAddress();
|
||||
LoginDatabase.escape_string(current_ip);
|
||||
LoginDatabase.PExecute("INSERT INTO ip_banned VALUES ('%s',UNIX_TIMESTAMP(),UNIX_TIMESTAMP()+'%u','Trinity realmd','Failed login autoban')",
|
||||
loginDatabase.escape_string(current_ip);
|
||||
loginDatabase.PExecute("INSERT INTO ip_banned VALUES ('%s',UNIX_TIMESTAMP(),UNIX_TIMESTAMP()+'%u','Trinity realmd','Failed login autoban')",
|
||||
current_ip.c_str(), WrongPassBanTime);
|
||||
sLog.outBasic("[AuthChallenge] IP %s got banned for '%u' seconds because account %s failed to authenticate '%u' times",
|
||||
current_ip.c_str(), WrongPassBanTime, _login.c_str(), failed_logins);
|
||||
@@ -754,7 +769,7 @@ bool AuthSocket::_HandleReconnectChallenge()
|
||||
_login = (const char*)ch->I;
|
||||
_safelogin = _login;
|
||||
|
||||
QueryResult *result = LoginDatabase.PQuery ("SELECT sessionkey FROM account WHERE username = '%s'", _safelogin.c_str ());
|
||||
QueryResult *result = loginDatabase.PQuery ("SELECT sessionkey FROM account WHERE username = '%s'", _safelogin.c_str ());
|
||||
|
||||
// Stop if the account is not found
|
||||
if (!result)
|
||||
@@ -772,7 +787,7 @@ bool AuthSocket::_HandleReconnectChallenge()
|
||||
ByteBuffer pkt;
|
||||
pkt << (uint8) AUTH_RECONNECT_CHALLENGE;
|
||||
pkt << (uint8) 0x00;
|
||||
_reconnectProof.SetRand(16*8);
|
||||
_reconnectProof.SetRand(16 * 8);
|
||||
pkt.append(_reconnectProof.AsByteBuffer()); // 16 bytes random
|
||||
pkt << (uint64) 0x00 << (uint64) 0x00; // 16 bytes zeros
|
||||
SendBuf((char const*)pkt.contents(), pkt.size());
|
||||
@@ -834,7 +849,7 @@ bool AuthSocket::_HandleRealmList()
|
||||
///- Get the user id (else close the connection)
|
||||
// No SQL injection (escaped user name)
|
||||
|
||||
QueryResult *result = LoginDatabase.PQuery("SELECT id,sha_pass_hash FROM account WHERE username = '%s'",_safelogin.c_str());
|
||||
QueryResult *result = loginDatabase.PQuery("SELECT id,sha_pass_hash FROM account WHERE username = '%s'",_safelogin.c_str());
|
||||
if(!result)
|
||||
{
|
||||
sLog.outError("[ERROR] user %s tried to login and we cannot find him in the database.",_login.c_str());
|
||||
@@ -854,12 +869,12 @@ bool AuthSocket::_HandleRealmList()
|
||||
pkt << (uint32) 0;
|
||||
pkt << (uint16) m_realmList.size();
|
||||
RealmList::RealmMap::const_iterator i;
|
||||
for( i = m_realmList.begin(); i != m_realmList.end(); i++ )
|
||||
for( i = m_realmList.begin(); i != m_realmList.end(); ++i )
|
||||
{
|
||||
uint8 AmountOfCharacters;
|
||||
|
||||
// No SQL injection. id of realm is controlled by the database.
|
||||
result = LoginDatabase.PQuery( "SELECT numchars FROM realmcharacters WHERE realmid = '%d' AND acctid='%u'",i->second.m_ID,id);
|
||||
result = loginDatabase.PQuery( "SELECT numchars FROM realmcharacters WHERE realmid = '%d' AND acctid='%u'",i->second.m_ID,id);
|
||||
if( result )
|
||||
{
|
||||
Field *fields = result->Fetch();
|
||||
@@ -901,7 +916,7 @@ bool AuthSocket::_HandleXferResume()
|
||||
{
|
||||
DEBUG_LOG("Entering _HandleXferResume");
|
||||
///- Check packet length and patch existence
|
||||
if (ibuf.GetLength()<9 || !pPatch)
|
||||
if (ibuf.GetLength() < 9 || !pPatch)
|
||||
{
|
||||
sLog.outError("Error while resuming patch transfer (wrong packet)");
|
||||
return false;
|
||||
@@ -911,7 +926,7 @@ bool AuthSocket::_HandleXferResume()
|
||||
uint64 start;
|
||||
ibuf.Remove(1);
|
||||
ibuf.Read((char*)&start,sizeof(start));
|
||||
fseek(pPatch,start,0);
|
||||
fseek(pPatch, start, 0);
|
||||
|
||||
ACE_Based::Thread u(*new PatcherRunnable(this));
|
||||
return true;
|
||||
@@ -942,9 +957,9 @@ bool AuthSocket::_HandleXferAccept()
|
||||
return false;
|
||||
}
|
||||
|
||||
///- Launch a PatcherRunnable thread, starting at the begining of the patch file
|
||||
ibuf.Remove(1); //clear input buffer
|
||||
fseek(pPatch,0,0);
|
||||
///- Launch a PatcherRunnable thread, starting at the beginning of the patch file
|
||||
ibuf.Remove(1); // clear input buffer
|
||||
fseek(pPatch, 0, 0);
|
||||
|
||||
ACE_Based::Thread u(*new PatcherRunnable(this));
|
||||
return true;
|
||||
@@ -953,12 +968,12 @@ bool AuthSocket::_HandleXferAccept()
|
||||
/// Check if there is lag on the connection to the client
|
||||
bool AuthSocket::IsLag()
|
||||
{
|
||||
return (TCP_BUFSIZE_READ-GetOutputLength()< 2*ChunkSize);
|
||||
return (TCP_BUFSIZE_READ-GetOutputLength() < 2 * ChunkSize);
|
||||
}
|
||||
|
||||
PatcherRunnable::PatcherRunnable(class AuthSocket * as)
|
||||
{
|
||||
mySocket=as;
|
||||
mySocket = as;
|
||||
}
|
||||
|
||||
/// Send content of patch file to the client
|
||||
@@ -977,8 +992,8 @@ void PatcherRunnable::run()
|
||||
ACE_Based::Thread::Sleep(1);
|
||||
}
|
||||
///- And send content of the patch file to the client
|
||||
xfdata.data_size=fread(&xfdata.data,1,ChunkSize,mySocket->pPatch);
|
||||
mySocket->SendBuf((const char*)&xfdata,xfdata.data_size +(sizeof(XFER_DATA_STRUCT)-ChunkSize));
|
||||
xfdata.data_size = fread(&xfdata.data, 1, ChunkSize, mySocket->pPatch);
|
||||
mySocket->SendBuf((const char*)&xfdata, xfdata.data_size + (sizeof(XFER_DATA_STRUCT) - ChunkSize));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -999,8 +1014,9 @@ void Patcher::LoadPatchesInfo()
|
||||
errno = 0;
|
||||
if ((dp = readdir(dirp)) != NULL)
|
||||
{
|
||||
int l=strlen(dp->d_name);
|
||||
if(l<8)continue;
|
||||
int l = strlen(dp->d_name);
|
||||
if(l < 8)
|
||||
continue;
|
||||
if(!memcmp(&dp->d_name[l-4],".mpq",4))
|
||||
LoadPatchMD5(dp->d_name);
|
||||
}
|
||||
@@ -1023,15 +1039,15 @@ void Patcher::LoadPatchesInfo()
|
||||
void Patcher::LoadPatchesInfo()
|
||||
{
|
||||
WIN32_FIND_DATA fil;
|
||||
HANDLE hFil=FindFirstFile("./patches/*.mpq",&fil);
|
||||
if(hFil==INVALID_HANDLE_VALUE)
|
||||
return; //no patches were found
|
||||
HANDLE hFil=FindFirstFile("./patches/*.mpq", &fil);
|
||||
if(hFil == INVALID_HANDLE_VALUE)
|
||||
return; // no patches were found
|
||||
|
||||
do
|
||||
{
|
||||
LoadPatchMD5(fil.cFileName);
|
||||
}
|
||||
while(FindNextFile(hFil,&fil));
|
||||
while(FindNextFile(hFil, &fil));
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -1041,11 +1057,11 @@ void Patcher::LoadPatchMD5(char * szFileName)
|
||||
///- Try to open the patch file
|
||||
std::string path = "./patches/";
|
||||
path += szFileName;
|
||||
FILE * pPatch=fopen(path.c_str(),"rb");
|
||||
sLog.outDebug("Loading patch info from %s\n",path.c_str());
|
||||
FILE *pPatch = fopen(path.c_str(), "rb");
|
||||
sLog.outDebug("Loading patch info from %s\n", path.c_str());
|
||||
if(!pPatch)
|
||||
{
|
||||
sLog.outError("Error loading patch %s\n",path.c_str());
|
||||
sLog.outError("Error loading patch %s\n", path.c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1064,16 +1080,16 @@ void Patcher::LoadPatchMD5(char * szFileName)
|
||||
|
||||
///- Store the result in the internal patch hash map
|
||||
_patches[path] = new PATCH_INFO;
|
||||
MD5_Final((uint8 *)&_patches[path]->md5 , &ctx);
|
||||
MD5_Final((uint8 *)&_patches[path]->md5, &ctx);
|
||||
}
|
||||
|
||||
/// Get cached MD5 hash for a given patch file
|
||||
bool Patcher::GetHash(char * pat,uint8 mymd5[16])
|
||||
bool Patcher::GetHash(char * pat, uint8 mymd5[16])
|
||||
{
|
||||
for( Patches::iterator i = _patches.begin(); i != _patches.end(); i++ )
|
||||
if(!stricmp(pat,i->first.c_str () ))
|
||||
for( Patches::iterator i = _patches.begin(); i != _patches.end(); ++i )
|
||||
if(!stricmp(pat, i->first.c_str()))
|
||||
{
|
||||
memcpy(mymd5,i->second->md5,16);
|
||||
memcpy(mymd5, i->second->md5, 16);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1089,6 +1105,6 @@ Patcher::Patcher()
|
||||
/// Empty and delete the patch map on termination
|
||||
Patcher::~Patcher()
|
||||
{
|
||||
for(Patches::iterator i = _patches.begin(); i != _patches.end(); i++ )
|
||||
for(Patches::iterator i = _patches.begin(); i != _patches.end(); ++i )
|
||||
delete i->second;
|
||||
}
|
||||
|
||||
@@ -66,7 +66,7 @@ void HookSignals();
|
||||
bool stopEvent = false; ///< Setting it to true stops the server
|
||||
RealmList m_realmList; ///< Holds the list of realms for this server
|
||||
|
||||
DatabaseType LoginDatabase; ///< Accessor to the realm server database
|
||||
DatabaseType loginDatabase; ///< Accessor to the realm server database
|
||||
|
||||
/// Print out the usage string for this program on the console.
|
||||
void usage(const char *prog)
|
||||
@@ -304,7 +304,7 @@ extern int main(int argc, char **argv)
|
||||
{
|
||||
loopCounter = 0;
|
||||
sLog.outDetail("Ping MySQL to keep connection alive");
|
||||
delete LoginDatabase.Query("SELECT 1 FROM realmlist LIMIT 1");
|
||||
delete loginDatabase.Query("SELECT 1 FROM realmlist LIMIT 1");
|
||||
}
|
||||
#ifdef WIN32
|
||||
if (m_ServiceStatus == 0) stopEvent = true;
|
||||
@@ -313,8 +313,8 @@ extern int main(int argc, char **argv)
|
||||
}
|
||||
|
||||
///- Wait for the delay thread to exit
|
||||
LoginDatabase.ThreadEnd();
|
||||
LoginDatabase.HaltDelayThread();
|
||||
loginDatabase.ThreadEnd();
|
||||
loginDatabase.HaltDelayThread();
|
||||
|
||||
///- Remove signal handling before leaving
|
||||
UnhookSignals();
|
||||
@@ -346,19 +346,19 @@ void OnSignal(int s)
|
||||
/// Initialize connection to the database
|
||||
bool StartDB()
|
||||
{
|
||||
std::string dbstring = sConfig.GetStringDefault("LoginDatabaseInfo", "");
|
||||
std::string dbstring = sConfig.GetStringDefault("loginDatabaseInfo", "");
|
||||
if(dbstring.empty())
|
||||
{
|
||||
sLog.outError("Database not specified");
|
||||
return false;
|
||||
}
|
||||
|
||||
if(!LoginDatabase.Initialize(dbstring.c_str()))
|
||||
if(!loginDatabase.Initialize(dbstring.c_str()))
|
||||
{
|
||||
sLog.outError("Cannot connect to database");
|
||||
return false;
|
||||
}
|
||||
LoginDatabase.ThreadStart();
|
||||
loginDatabase.ThreadStart();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
|
||||
INSTANTIATE_SINGLETON_1( RealmList );
|
||||
|
||||
extern DatabaseType LoginDatabase;
|
||||
extern DatabaseType loginDatabase;
|
||||
|
||||
RealmList::RealmList( ) : m_UpdateInterval(0), m_NextUpdateTime(time(NULL))
|
||||
{
|
||||
@@ -82,7 +82,7 @@ void RealmList::UpdateRealms(bool init)
|
||||
{
|
||||
sLog.outDetail("Updating Realm List...");
|
||||
|
||||
QueryResult *result = LoginDatabase.Query( "SELECT id, name, address, port, icon, color, timezone, allowedSecurityLevel, population FROM realmlist WHERE color <> 3 ORDER BY name" );
|
||||
QueryResult *result = loginDatabase.Query( "SELECT id, name, address, port, icon, color, timezone, allowedSecurityLevel, population FROM realmlist WHERE color <> 3 ORDER BY name" );
|
||||
|
||||
///- Circle through results and add them to the realm map
|
||||
if(result)
|
||||
|
||||
@@ -370,6 +370,7 @@
|
||||
<ClCompile Include="..\..\src\game\CalendarHandler.cpp" />
|
||||
<ClCompile Include="..\..\src\game\Channel.cpp" />
|
||||
<ClCompile Include="..\..\src\game\ChannelHandler.cpp" />
|
||||
<ClCompile Include="..\..\src\game\ChannelMgr.cpp" />
|
||||
<ClCompile Include="..\..\src\game\CharacterHandler.cpp" />
|
||||
<ClCompile Include="..\..\src\game\Chat.cpp" />
|
||||
<ClCompile Include="..\..\src\game\ChatHandler.cpp" />
|
||||
|
||||
@@ -673,6 +673,10 @@
|
||||
RelativePath="..\..\src\game\ChannelHandler.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\src\game\ChannelMgr.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\src\game\ChannelMgr.h"
|
||||
>
|
||||
|
||||
@@ -674,6 +674,10 @@
|
||||
RelativePath="..\..\src\game\ChannelHandler.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\src\game\ChannelMgr.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\src\game\ChannelMgr.h"
|
||||
>
|
||||
|
||||
Reference in New Issue
Block a user