Merge branch 'master' into 310

Conflicts:
	src/game/GameObject.cpp
This commit is contained in:
tomrus88 2009-03-18 07:45:29 +03:00
commit 9d2acc22b4
47 changed files with 1772 additions and 1246 deletions

View file

@ -153,7 +153,12 @@ uint32 ReadMapDBC()
{ {
printf("Read Map.dbc file... "); printf("Read Map.dbc file... ");
DBCFile dbc("DBFilesClient\\Map.dbc"); DBCFile dbc("DBFilesClient\\Map.dbc");
dbc.open();
if(!dbc.open())
{
printf("Fatal error: Invalid Map.dbc file format!\n");
exit(1);
}
size_t map_count = dbc.getRecordCount(); size_t map_count = dbc.getRecordCount();
map_ids = new map_id[map_count]; map_ids = new map_id[map_count];
@ -170,7 +175,12 @@ void ReadAreaTableDBC()
{ {
printf("Read AreaTable.dbc file..."); printf("Read AreaTable.dbc file...");
DBCFile dbc("DBFilesClient\\AreaTable.dbc"); DBCFile dbc("DBFilesClient\\AreaTable.dbc");
dbc.open();
if(!dbc.open())
{
printf("Fatal error: Invalid AreaTable.dbc file format!\n");
exit(1);
}
size_t area_count = dbc.getRecordCount(); size_t area_count = dbc.getRecordCount();
size_t maxid = dbc.getMaxId(); size_t maxid = dbc.getMaxId();
@ -189,7 +199,12 @@ void ReadLiquidTypeTableDBC()
{ {
printf("Read LiquidType.dbc file..."); printf("Read LiquidType.dbc file...");
DBCFile dbc("DBFilesClient\\LiquidType.dbc"); DBCFile dbc("DBFilesClient\\LiquidType.dbc");
dbc.open(); if(!dbc.open())
{
printf("Fatal error: Invalid LiquidType.dbc file format!\n");
exit(1);
}
size_t LiqType_count = dbc.getRecordCount(); size_t LiqType_count = dbc.getRecordCount();
size_t LiqType_maxid = dbc.getMaxId(); size_t LiqType_maxid = dbc.getMaxId();
LiqType = new uint16[LiqType_maxid + 1]; LiqType = new uint16[LiqType_maxid + 1];

Binary file not shown.

View file

@ -9,29 +9,42 @@ DBCFile::DBCFile(const std::string &filename):
{ {
} }
void DBCFile::open() bool DBCFile::open()
{ {
MPQFile f(filename.c_str()); MPQFile f(filename.c_str());
char header[4]; char header[4];
unsigned int na,nb,es,ss; unsigned int na,nb,es,ss;
f.read(header,4); // Number of records if(f.read(header,4)!=4) // Number of records
assert(header[0]=='W' && header[1]=='D' && header[2]=='B' && header[3] == 'C'); return false;
f.read(&na,4); // Number of records
f.read(&nb,4); // Number of fields if(header[0]!='W' || header[1]!='D' || header[2]!='B' || header[3]!='C')
f.read(&es,4); // Size of a record return false;
f.read(&ss,4); // String size
if(f.read(&na,4)!=4) // Number of records
return false;
if(f.read(&nb,4)!=4) // Number of fields
return false;
if(f.read(&es,4)!=4) // Size of a record
return false;
if(f.read(&ss,4)!=4) // String size
return false;
recordSize = es; recordSize = es;
recordCount = na; recordCount = na;
fieldCount = nb; fieldCount = nb;
stringSize = ss; stringSize = ss;
assert(fieldCount*4 == recordSize); if(fieldCount*4 != recordSize)
return false;
data = new unsigned char[recordSize*recordCount+stringSize]; data = new unsigned char[recordSize*recordCount+stringSize];
stringTable = data + recordSize*recordCount; stringTable = data + recordSize*recordCount;
f.read(data,recordSize*recordCount+stringSize);
size_t data_size = recordSize*recordCount+stringSize;
if(f.read(data,data_size)!=data_size)
return false;
f.close(); f.close();
return true;
} }
DBCFile::~DBCFile() DBCFile::~DBCFile()
{ {

View file

@ -10,7 +10,7 @@ public:
~DBCFile(); ~DBCFile();
// Open database. It must be openened before it can be used. // Open database. It must be openened before it can be used.
void open(); bool open();
// Database exceptions // Database exceptions
class Exception class Exception

View file

@ -22,7 +22,7 @@
DROP TABLE IF EXISTS `db_version`; DROP TABLE IF EXISTS `db_version`;
CREATE TABLE `db_version` ( CREATE TABLE `db_version` (
`version` varchar(120) default NULL, `version` varchar(120) default NULL,
`required_7439_01_mangos_mangos_string` bit(1) default NULL `required_7472_01_mangos_mangos_string` bit(1) default NULL
) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=FIXED COMMENT='Used DB version notes'; ) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=FIXED COMMENT='Used DB version notes';
-- --
@ -639,6 +639,8 @@ CREATE TABLE `creature_model_info` (
LOCK TABLES `creature_model_info` WRITE; LOCK TABLES `creature_model_info` WRITE;
/*!40000 ALTER TABLE `creature_model_info` DISABLE KEYS */; /*!40000 ALTER TABLE `creature_model_info` DISABLE KEYS */;
INSERT INTO `creature_model_info` VALUES
(10045, 1, 1.5, 2, 0);
/*!40000 ALTER TABLE `creature_model_info` ENABLE KEYS */; /*!40000 ALTER TABLE `creature_model_info` ENABLE KEYS */;
UNLOCK TABLES; UNLOCK TABLES;
@ -830,7 +832,7 @@ CREATE TABLE `creature_template` (
LOCK TABLES `creature_template` WRITE; LOCK TABLES `creature_template` WRITE;
/*!40000 ALTER TABLE `creature_template` DISABLE KEYS */; /*!40000 ALTER TABLE `creature_template` DISABLE KEYS */;
INSERT INTO `creature_template` VALUES INSERT INTO `creature_template` VALUES
(1,1,10045,0,10045,0,'Waypoint(Only GM can see it)','Visual',NULL,1,1,64,64,0,0,0,35,35,0,0.91,1,0,14,15,0,100,2000,2200,4096,0,0,0,0,0,0,1.76,2.42,100,8,5242886,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,3,1.0,1.0,0,1,0,0,0x82,''); (1,0,10045,0,10045,0,'Waypoint(Only GM can see it)','Visual',NULL,1,1,64,64,0,0,0,35,35,0,0.91,1,0,14,15,0,100,2000,2200,4096,0,0,0,0,0,0,1.76,2.42,100,8,5242886,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,3,1.0,1.0,0,1,0,0,0x82,'');
/*!40000 ALTER TABLE `creature_template` ENABLE KEYS */; /*!40000 ALTER TABLE `creature_template` ENABLE KEYS */;
UNLOCK TABLES; UNLOCK TABLES;
@ -1706,7 +1708,7 @@ INSERT INTO `item_template` VALUES
(56,4,1,-1,'Apprentice\'s Robe',12647,0,0,1,5,1,20,2047,255,1,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3,0,0,0,0,0,0,1000,0,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,0,0,0,0,7,0,0,0,0,0,35,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,'internalItemHandler',0,0,0,0,0), (56,4,1,-1,'Apprentice\'s Robe',12647,0,0,1,5,1,20,2047,255,1,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3,0,0,0,0,0,0,1000,0,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,0,0,0,0,7,0,0,0,0,0,35,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,'internalItemHandler',0,0,0,0,0),
(57,4,1,-1,'Acolyte\'s Robe',12645,0,0,1,5,1,20,2047,255,1,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3,0,0,0,0,0,0,1000,0,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,0,0,0,0,7,0,0,0,0,0,35,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,'internalItemHandler',0,0,0,0,0), (57,4,1,-1,'Acolyte\'s Robe',12645,0,0,1,5,1,20,2047,255,1,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3,0,0,0,0,0,0,1000,0,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,0,0,0,0,7,0,0,0,0,0,35,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,'internalItemHandler',0,0,0,0,0),
(59,4,0,-1,'Acolyte\'s Shoes',3261,1,0,1,5,1,8,2047,255,1,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1000,0,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,'internalItemHandler',0,0,0,0,0), (59,4,0,-1,'Acolyte\'s Shoes',3261,1,0,1,5,1,8,2047,255,1,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1000,0,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,'internalItemHandler',0,0,0,0,0),
(117,0,0,-1,'Tough Jerky',2473,1,0,6,25,1,0,2047,255,5,1,0,0,0,0,0,0,0,0,20,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1000,0,0,433,0,-1,0,-1,11,1000,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,'internalItemHandler',0,0,0,0,0), (117,0,0,-1,'Tough Jerky',2473,1,0,6,25,1,0,2047,255,5,1,0,0,0,0,0,0,0,0,20,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1000,0,0,433,0,-1,0,-1,11,1000,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,'internalItemHandler',0,0,0,0,0),
(120,4,1,-1,'Thug Pants',10006,0,0,1,4,1,7,2047,255,1,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,1000,0,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,0,0,0,0,7,0,0,0,0,0,25,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,'internalItemHandler',0,0,0,0,0), (120,4,1,-1,'Thug Pants',10006,0,0,1,4,1,7,2047,255,1,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,1000,0,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,0,0,0,0,7,0,0,0,0,0,25,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,'internalItemHandler',0,0,0,0,0),
(121,4,0,-1,'Thug Boots',10008,1,0,1,4,1,8,2047,255,1,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1000,0,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,'internalItemHandler',0,0,0,0,0), (121,4,0,-1,'Thug Boots',10008,1,0,1,4,1,8,2047,255,1,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1000,0,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,'internalItemHandler',0,0,0,0,0),
(127,4,0,-1,'Trapper\'s Shirt',9996,1,0,1,1,1,4,2047,255,1,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1000,0,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,'internalItemHandler',0,0,0,0,0), (127,4,0,-1,'Trapper\'s Shirt',9996,1,0,1,1,1,4,2047,255,1,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1000,0,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,'internalItemHandler',0,0,0,0,0),
@ -1716,13 +1718,13 @@ INSERT INTO `item_template` VALUES
(148,4,0,-1,'Rugged Trapper\'s Shirt',9976,1,0,1,1,1,4,2047,255,1,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1000,0,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,'internalItemHandler',0,0,0,0,0), (148,4,0,-1,'Rugged Trapper\'s Shirt',9976,1,0,1,1,1,4,2047,255,1,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1000,0,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,'internalItemHandler',0,0,0,0,0),
(153,4,2,-1,'Primitive Kilt',10050,0,0,1,5,1,7,2047,255,1,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,14,0,0,0,0,0,0,1000,0,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,0,0,0,0,8,0,0,0,0,0,30,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,'internalItemHandler',0,0,0,0,0), (153,4,2,-1,'Primitive Kilt',10050,0,0,1,5,1,7,2047,255,1,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,14,0,0,0,0,0,0,1000,0,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,0,0,0,0,8,0,0,0,0,0,30,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,'internalItemHandler',0,0,0,0,0),
(154,4,0,-1,'Primitive Mantle',10058,1,0,1,1,1,4,2047,255,1,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1000,0,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,'internalItemHandler',0,0,0,0,0), (154,4,0,-1,'Primitive Mantle',10058,1,0,1,1,1,4,2047,255,1,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1000,0,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,'internalItemHandler',0,0,0,0,0),
(159,0,0,-1,'Refreshing Spring Water',18084,1,0,6,25,1,0,2047,255,5,1,0,0,0,0,0,0,0,0,20,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1000,0,0,430,0,-1,0,-1,59,1000,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,'internalItemHandler',0,0,0,0,0), (159,0,0,-1,'Refreshing Spring Water',18084,1,0,6,25,1,0,2047,255,5,1,0,0,0,0,0,0,0,0,20,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1000,0,0,430,0,-1,0,-1,59,1000,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,'internalItemHandler',0,0,0,0,0),
(1395,4,1,-1,'Apprentice\'s Pants',9924,0,0,1,5,1,7,2047,255,1,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,1000,0,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,0,0,0,0,7,0,0,0,0,0,25,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,'internalItemHandler',0,0,0,0,0), (1395,4,1,-1,'Apprentice\'s Pants',9924,0,0,1,5,1,7,2047,255,1,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,1000,0,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,0,0,0,0,7,0,0,0,0,0,25,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,'internalItemHandler',0,0,0,0,0),
(1396,4,1,-1,'Acolyte\'s Pants',3260,0,0,1,4,1,7,2047,255,1,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,1000,0,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,0,0,0,0,7,0,0,0,0,0,25,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,'internalItemHandler',0,0,0,0,0), (1396,4,1,-1,'Acolyte\'s Pants',3260,0,0,1,4,1,7,2047,255,1,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,1000,0,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,0,0,0,0,7,0,0,0,0,0,25,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,'internalItemHandler',0,0,0,0,0),
(2070,0,0,-1,'Darnassian Bleu',6353,1,0,6,25,1,0,2047,255,5,1,0,0,0,0,0,0,0,0,20,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1000,0,0,433,0,-1,0,-1,11,1000,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,'internalItemHandler',0,0,0,0,0), (2070,0,0,-1,'Darnassian Bleu',6353,1,0,6,25,1,0,2047,255,5,1,0,0,0,0,0,0,0,0,20,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1000,0,0,433,0,-1,0,-1,11,1000,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,'internalItemHandler',0,0,0,0,0),
(2092,2,15,-1,'Worn Dagger',6442,1,0,1,35,7,13,2047,255,2,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1600,0,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,0,0,0,0,1,3,0,0,0,0,16,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,'internalItemHandler',0,0,0,0,0), (2092,2,15,-1,'Worn Dagger',6442,1,0,1,35,7,13,2047,255,2,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1600,0,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,0,0,0,0,1,3,0,0,0,0,16,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,'internalItemHandler',0,0,0,0,0),
(2101,1,2,-1,'Light Quiver',21328,1,0,1,4,1,18,2047,255,1,1,0,0,0,0,0,0,0,0,1,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1000,0,0,14824,1,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,'',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,'internalItemHandler',0,0,0,0,0), (2101,11,2,-1,'Light Quiver',21328,1,0,1,4,1,18,2047,255,1,1,0,0,0,0,0,0,0,0,1,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1000,0,0,14824,1,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,'',0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,'internalItemHandler',0,0,0,0,0),
(2102,1,3,-1,'Small Ammo Pouch',1816,1,0,1,4,1,18,2047,255,1,1,0,0,0,0,0,0,0,0,1,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1000,0,0,14824,1,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,'',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,'internalItemHandler',0,0,0,0,0), (2102,11,3,-1,'Small Ammo Pouch',1816,1,0,1,4,1,18,2047,255,1,1,0,0,0,0,0,0,0,0,1,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1000,0,0,14824,1,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,'',0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,'internalItemHandler',0,0,0,0,0),
(2105,4,0,-1,'Thug Shirt',10005,1,0,1,5,1,4,2047,255,1,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1000,0,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,'internalItemHandler',0,0,0,0,0), (2105,4,0,-1,'Thug Shirt',10005,1,0,1,5,1,4,2047,255,1,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1000,0,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,'internalItemHandler',0,0,0,0,0),
(2361,2,5,-1,'Battleworn Hammer',8690,1,0,1,45,9,17,2047,255,2,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2900,0,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,0,0,0,0,2,1,0,0,0,0,25,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,'internalItemHandler',0,0,0,0,0), (2361,2,5,-1,'Battleworn Hammer',8690,1,0,1,45,9,17,2047,255,2,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2900,0,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,0,0,0,0,2,1,0,0,0,0,25,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,'internalItemHandler',0,0,0,0,0),
(2362,4,6,-1,'Worn Wooden Shield',18730,0,0,1,7,1,14,32767,511,1,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,0,0,0,0,1,4,0,0,1,0,20,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,'internalItemHandler',0,0,0,0,0), (2362,4,6,-1,'Worn Wooden Shield',18730,0,0,1,7,1,14,32767,511,1,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,0,0,0,0,1,4,0,0,1,0,20,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,'internalItemHandler',0,0,0,0,0),
@ -1730,11 +1732,11 @@ INSERT INTO `item_template` VALUES
(2508,2,3,-1,'Old Blunderbuss',6606,1,0,1,27,5,26,2047,255,2,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2300,3,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,0,0,0,0,1,0,0,0,0,0,20,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,'internalItemHandler',0,0,0,0,0), (2508,2,3,-1,'Old Blunderbuss',6606,1,0,1,27,5,26,2047,255,2,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2300,3,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,0,0,0,0,1,0,0,0,0,0,20,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,'internalItemHandler',0,0,0,0,0),
(2512,6,2,-1,'Rough Arrow',5996,1,0,1,10,0,24,2047,255,5,1,0,0,0,0,0,0,0,0,200,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3000,0,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,0,0,0,0,2,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,-1,0,0,'internalItemHandler',0,0,0,0,0), (2512,6,2,-1,'Rough Arrow',5996,1,0,1,10,0,24,2047,255,5,1,0,0,0,0,0,0,0,0,200,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3000,0,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,0,0,0,0,2,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,-1,0,0,'internalItemHandler',0,0,0,0,0),
(2516,6,3,-1,'Light Shot',5998,1,0,1,10,0,24,2047,255,5,1,0,0,0,0,0,0,0,0,200,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3000,0,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,0,0,0,0,2,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,-1,0,0,'internalItemHandler',0,0,0,0,0), (2516,6,3,-1,'Light Shot',5998,1,0,1,10,0,24,2047,255,5,1,0,0,0,0,0,0,0,0,200,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3000,0,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,0,0,0,0,2,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,-1,0,0,'internalItemHandler',0,0,0,0,0),
(2947,2,16,-1,'Small Throwing Knife',16754,1,0,1,15,0,25,2047,255,3,1,0,0,0,0,0,0,0,0,200,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2000,4,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,'internalItemHandler',0,0,0,0,0), (2947,15,0,-1,'Small Throwing Knife',16754,1,0,1,15,0,0,2047,255,3,1,0,0,0,0,0,0,0,0,200,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2000,4,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,'internalItemHandler',0,0,0,0,0),
(3661,2,10,-1,'Handcrafted Staff',18530,1,0,1,45,9,17,2047,255,2,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2900,0,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,0,0,0,0,2,2,0,0,0,0,25,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,'internalItemHandler',0,0,0,0,0), (3661,2,10,-1,'Handcrafted Staff',18530,1,0,1,45,9,17,2047,255,2,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2900,0,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,0,0,0,0,2,2,0,0,0,0,25,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,'internalItemHandler',0,0,0,0,0),
(4536,0,0,-1,'Shiny Red Apple',6410,1,0,6,25,1,0,2047,255,5,1,0,0,0,0,0,0,0,0,20,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1000,0,0,433,0,-1,0,-1,11,100,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,'internalItemHandler',0,0,0,0,0), (4536,0,0,-1,'Shiny Red Apple',6410,1,0,6,25,1,0,2047,255,5,1,0,0,0,0,0,0,0,0,20,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1000,0,0,433,0,-1,0,-1,11,100,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,'internalItemHandler',0,0,0,0,0),
(4540,0,0,-1,'Tough Hunk of Bread',6399,1,0,6,25,1,0,2047,255,5,1,0,0,0,0,0,0,0,0,20,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1000,0,0,433,0,-1,0,-1,11,1000,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,'internalItemHandler',0,0,0,0,0), (4540,0,0,-1,'Tough Hunk of Bread',6399,1,0,6,25,1,0,2047,255,5,1,0,0,0,0,0,0,0,0,20,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1000,0,0,433,0,-1,0,-1,11,1000,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,'internalItemHandler',0,0,0,0,0),
(4604,0,0,-1,'Forest Mushroom Cap',15852,1,0,6,25,1,0,2047,255,5,1,0,0,0,0,0,0,0,0,20,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1000,0,0,433,0,-1,0,-1,11,1000,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,'internalItemHandler',0,0,0,0,0), (4604,0,0,-1,'Forest Mushroom Cap',15852,1,0,6,25,1,0,2047,255,5,1,0,0,0,0,0,0,0,0,20,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1000,0,0,433,0,-1,0,-1,11,1000,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,'internalItemHandler',0,0,0,0,0),
(6096,4,0,-1,'Apprentice\'s Shirt',2163,1,0,1,1,1,4,2047,255,1,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1000,0,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,'internalItemHandler',0,0,0,0,0), (6096,4,0,-1,'Apprentice\'s Shirt',2163,1,0,1,1,1,4,2047,255,1,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1000,0,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,'internalItemHandler',0,0,0,0,0),
(6097,4,0,-1,'Acolyte\'s Shirt',2470,1,0,1,1,1,4,2047,255,1,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1000,0,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,'internalItemHandler',0,0,0,0,0), (6097,4,0,-1,'Acolyte\'s Shirt',2470,1,0,1,1,1,4,2047,255,1,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1000,0,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,'internalItemHandler',0,0,0,0,0),
(6098,4,1,-1,'Neophyte\'s Robe',12679,0,0,1,4,1,20,2047,255,1,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3,0,0,0,0,0,0,1000,0,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,0,0,0,0,7,0,0,0,0,0,35,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,'internalItemHandler',0,0,0,0,0), (6098,4,1,-1,'Neophyte\'s Robe',12679,0,0,1,4,1,20,2047,255,1,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3,0,0,0,0,0,0,1000,0,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,0,0,0,0,7,0,0,0,0,0,35,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,'internalItemHandler',0,0,0,0,0),
@ -1750,14 +1752,14 @@ INSERT INTO `item_template` VALUES
(6139,4,1,-1,'Novice\'s Robe',12684,0,0,1,4,1,20,2047,255,1,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3,0,0,0,0,0,0,1000,0,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,0,0,0,0,7,0,0,0,0,0,35,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,'internalItemHandler',0,0,0,0,0), (6139,4,1,-1,'Novice\'s Robe',12684,0,0,1,4,1,20,2047,255,1,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3,0,0,0,0,0,0,1000,0,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,0,0,0,0,7,0,0,0,0,0,35,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,'internalItemHandler',0,0,0,0,0),
(6140,4,1,-1,'Apprentice\'s Robe',12649,0,0,1,4,1,20,2047,255,1,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3,0,0,0,0,0,0,1000,0,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,0,0,0,0,7,0,0,0,0,0,35,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,'internalItemHandler',0,0,0,0,0), (6140,4,1,-1,'Apprentice\'s Robe',12649,0,0,1,4,1,20,2047,255,1,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3,0,0,0,0,0,0,1000,0,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,0,0,0,0,7,0,0,0,0,0,35,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,'internalItemHandler',0,0,0,0,0),
(6144,4,1,-1,'Neophyte\'s Robe',12680,0,0,1,5,1,20,2047,255,1,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3,0,0,0,0,0,0,1000,0,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,0,0,0,0,7,0,0,0,0,0,35,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,'internalItemHandler',0,0,0,0,0), (6144,4,1,-1,'Neophyte\'s Robe',12680,0,0,1,5,1,20,2047,255,1,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3,0,0,0,0,0,0,1000,0,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,0,0,0,0,7,0,0,0,0,0,35,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,'internalItemHandler',0,0,0,0,0),
(6948,15,0,-1,'Hearthstone',6418,1,64,1,0,0,0,32767,511,1,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8690,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,'',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,'internalItemHandler',0,0,0,0,0), (6948,15,0,-1,'Hearthstone',6418,1,64,1,0,0,0,32767,511,1,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8690,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,'',0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,'internalItemHandler',0,0,0,0,0),
(12282,2,1,-1,'Worn Battleaxe',22291,1,0,1,43,8,17,2047,255,2,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2900,0,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,0,0,0,0,1,1,0,0,0,0,25,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,'internalItemHandler',0,0,0,0,0), (12282,2,1,-1,'Worn Battleaxe',22291,1,0,1,43,8,17,2047,255,2,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2900,0,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,0,0,0,0,1,1,0,0,0,0,25,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,'internalItemHandler',0,0,0,0,0),
(14646,12,0,-1,'Northshire Gift Voucher',18499,1,0,1,0,0,0,2047,255,1,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1000,0,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,'',0,0,0,5805,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,'internalItemHandler',0,0,0,0,0), (14646,12,0,-1,'Northshire Gift Voucher',18499,1,0,1,0,0,0,2047,255,1,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1000,0,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,'',0,0,0,5805,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,'internalItemHandler',0,0,0,0,0),
(14647,12,0,-1,'Coldridge Valley Gift Voucher',18499,1,0,1,0,0,0,2047,255,1,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1000,0,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,'',0,0,0,5841,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,'internalItemHandler',0,0,0,0,0), (14647,12,0,-1,'Coldridge Valley Gift Voucher',18499,1,0,1,0,0,0,2047,255,1,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1000,0,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,'',0,0,0,5841,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,'internalItemHandler',0,0,0,0,0),
(14648,12,0,-1,'Shadowglen Gift Voucher',18499,1,0,1,0,0,0,2047,255,1,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1000,0,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,'',0,0,0,5842,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,'internalItemHandler',0,0,0,0,0), (14648,12,0,-1,'Shadowglen Gift Voucher',18499,1,0,1,0,0,0,2047,255,1,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1000,0,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,'',0,0,0,5842,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,'internalItemHandler',0,0,0,0,0),
(14649,12,0,-1,'Valley of Trials Gift Voucher',18499,1,0,1,0,0,0,2047,255,1,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1000,0,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,'',0,0,0,5843,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,'internalItemHandler',0,0,0,0,0), (14649,12,0,-1,'Valley of Trials Gift Voucher',18499,1,0,1,0,0,0,2047,255,1,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1000,0,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,'',0,0,0,5843,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,'internalItemHandler',0,0,0,0,0),
(14650,12,0,-1,'Camp Narache Gift Voucher',18499,1,0,1,0,0,0,2047,255,1,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1000,0,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,'',0,0,0,5844,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,'internalItemHandler',0,0,0,0,0), (14650,12,0,-1,'Camp Narache Gift Voucher',18499,1,0,1,0,0,0,2047,255,1,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1000,0,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,'',0,0,0,5844,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,'internalItemHandler',0,0,0,0,0),
(14651,12,0,-1,'Deathknell Gift Voucher',18499,1,0,1,0,0,0,2047,255,1,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1000,0,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,'',0,0,0,5847,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,'internalItemHandler',0,0,0,0,0), (14651,12,0,-1,'Deathknell Gift Voucher',18499,1,0,1,0,0,0,2047,255,1,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1000,0,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,'',0,0,0,5847,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,'internalItemHandler',0,0,0,0,0),
(25861,2,16,-1,'Crude Throwing Axe',20777,1,0,1,15,0,25,2047,255,3,1,0,0,0,0,0,0,0,0,200,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2000,4,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,'internalItemHandler',0,0,0,0,0), (25861,2,16,-1,'Crude Throwing Axe',20777,1,0,1,15,0,25,2047,255,3,1,0,0,0,0,0,0,0,0,200,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2000,4,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,'internalItemHandler',0,0,0,0,0),
(34648,4,4,-1,'Acherus Knight\'s Greaves',51496,2,32768,1,51,10,8,-1,-1,60,55,0,0,0,0,0,0,0,0,1,0,3,4,10,7,12,3,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,392,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,-1,0,0,0,0,-1,0,-1,0,0,0,0,-1,0,-1,0,0,0,0,-1,0,-1,0,0,0,0,-1,0,-1,1,'',0,0,0,0,0,6,0,0,0,0,0,55,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,0,'',0,0,0,0), (34648,4,4,-1,'Acherus Knight\'s Greaves',51496,2,32768,1,51,10,8,-1,-1,60,55,0,0,0,0,0,0,0,0,1,0,3,4,10,7,12,3,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,392,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,-1,0,0,0,0,-1,0,-1,0,0,0,0,-1,0,-1,0,0,0,0,-1,0,-1,0,0,0,0,-1,0,-1,1,'',0,0,0,0,0,6,0,0,0,0,0,55,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,0,'',0,0,0,0),
(34649,4,4,-1,'Acherus Knight\'s Gauntlets',51498,2,32768,1,34,6,10,-1,-1,60,55,0,0,0,0,0,0,0,0,1,0,3,4,15,7,6,32,8,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,356,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,-1,0,0,0,0,-1,0,-1,0,0,0,0,-1,0,-1,0,0,0,0,-1,0,-1,0,0,0,0,-1,0,-1,1,'',0,0,0,0,0,6,0,0,0,0,0,40,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,0,'',0,0,0,0), (34649,4,4,-1,'Acherus Knight\'s Gauntlets',51498,2,32768,1,34,6,10,-1,-1,60,55,0,0,0,0,0,0,0,0,1,0,3,4,15,7,6,32,8,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,356,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,-1,0,0,0,0,-1,0,-1,0,0,0,0,-1,0,-1,0,0,0,0,-1,0,-1,0,0,0,0,-1,0,-1,1,'',0,0,0,0,0,6,0,0,0,0,0,40,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,0,'',0,0,0,0),
@ -2769,9 +2771,11 @@ INSERT INTO `mangos_string` VALUES
(611,'The Horde flag was picked up by $n!',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), (611,'The Horde flag was picked up by $n!',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL),
(612,'The Alliance Flag was picked up by $n!',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), (612,'The Alliance Flag was picked up by $n!',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL),
(613,'The flags are now placed at their bases.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), (613,'The flags are now placed at their bases.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL),
(636,'The Battle for Eye of the Storm begins in 1 minute.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), (614,'The Alliance flag is now placed at its base.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL),
(637,'The Battle for Eye of the Storm begins in 30 seconds.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), (615,'The Horde flag is now placed at its base.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL),
(638,'The Battle for Eye of the Storm has begun!',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), (636,'The battle begins in 1 minute.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL),
(637,'The battle begins in 30 seconds.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL),
(638,'The battle has begun!',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL),
(650,'Alliance',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), (650,'Alliance',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL),
(651,'Horde',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), (651,'Horde',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL),
(652,'stables',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), (652,'stables',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL),
@ -2783,12 +2787,33 @@ INSERT INTO `mangos_string` VALUES
(658,'$n has defended the %s',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), (658,'$n has defended the %s',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL),
(659,'$n has assaulted the %s',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), (659,'$n has assaulted the %s',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL),
(660,'$n claims the %s! If left unchallenged, the %s will control it in 1 minute!',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), (660,'$n claims the %s! If left unchallenged, the %s will control it in 1 minute!',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL),
(661,'The Battle for Arathi Basin begins in 1 minute.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), (661,'The battle for Arathi Basin begins in 1 minute.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL),
(662,'The Battle for Arathi Basin begins in 30 seconds. Prepare yourselves!',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), (662,'The battle for Arathi Basin begins in 30 seconds. Prepare yourselves!',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL),
(663,'The Battle for Arathi Basin has begun!',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), (663,'The battle for Arathi Basin has begun!',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL),
(664,'The Alliance has gathered $1776W resources, and is near victory!',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), (664,'The Alliance has gathered $1776W resources, and is near victory!',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL),
(665,'The Horde has gathered $1777W resources, and is near victory!',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), (665,'The Horde has gathered $1777W resources, and is near victory!',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL),
(666,'After your recent battle in %s our best attempts to award you a Mark of Honor failed. Enclosed you will find the Mark of Honor we were not able to deliver to you at the time. Thanks for fighting in %s!',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), (666,'After your recent battle in %s our best attempts to award you a Mark of Honor failed. Enclosed you will find the Mark of Honor we were not able to deliver to you at the time. Thanks for fighting in %s!',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL),
(667,'The Alliance has taken control of the Mage Tower!',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL),
(668,'The Horde has taken control of the Mage Tower!',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL),
(669,'The Alliance has taken control of the Draenei Ruins!',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL),
(670,'The Horde has taken control of the Draenei Ruins!',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL),
(671,'The Alliance has taken control of the Blood Elf Tower!',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL),
(672,'The Horde has taken control of the Blood Elf Tower!',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL),
(673,'The Alliance has taken control of the Fel Reaver Ruins!',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL),
(674,'The Horde has taken control of the Fel Reaver Ruins!',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL),
(675,'The Alliance has lost control of the Mage Tower!',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL),
(676,'The Horde has lost control of the Mage Tower!',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL),
(677,'The Alliance has lost control of the Draenei Ruins!',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL),
(678,'The Horde has lost control of the Draenei Ruins!',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL),
(679,'The Alliance has lost control of the Blood Elf Tower!',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL),
(680,'The Horde has lost control of the Blood Elf Tower!',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL),
(681,'The Alliance has lost control of the Fel Reaver Ruins!',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL),
(682,'The Horde has lost control of the Fel Reaver Ruins!',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL),
(683,'%s has taken the flag!',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL),
(684,'The Alliance have captured the flag!',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL),
(685,'The Horde have captured the flag!',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL),
(686,'The flag has been dropped.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL),
(687,'The flag has been reset.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL),
(700,'You must be level %u to form an arena team',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), (700,'You must be level %u to form an arena team',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL),
(701,'One minute until the Arena battle begins!',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), (701,'One minute until the Arena battle begins!',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL),
(702,'Thirty seconds until the Arena battle begins!',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), (702,'Thirty seconds until the Arena battle begins!',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL),
@ -2839,7 +2864,7 @@ INSERT INTO `mangos_string` VALUES
(751,'Not enough players. This game will close in %u seconds.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), (751,'Not enough players. This game will close in %u seconds.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL),
(753,'The battle for Warsong Gulch begins in 2 minutes.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), (753,'The battle for Warsong Gulch begins in 2 minutes.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL),
(754,'The battle for Arathi Basin begins in 2 minutes.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), (754,'The battle for Arathi Basin begins in 2 minutes.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL),
(755,'The battle for Eye of the Storm begins in 2 minutes.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), (755,'The battle begins in 2 minutes.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL),
(801,'You do not have enough gold',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), (801,'You do not have enough gold',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL),
(802,'You do not have enough free slots',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), (802,'You do not have enough free slots',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL),
(803,'Your partner does not have enough free bag slots',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), (803,'Your partner does not have enough free bag slots',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL),

View file

@ -0,0 +1,27 @@
ALTER TABLE db_version CHANGE COLUMN required_7439_01_mangos_mangos_string required_7472_01_mangos_mangos_string bit;
DELETE FROM mangos_string WHERE entry >= 667 and entry <= 687 or entry = 614 or entry = 615;
INSERT INTO mangos_string VALUES
(614,'The Alliance flag is now placed at its base.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL),
(615,'The Horde flag is now placed at its base.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL),
(667,'The Alliance has taken control of the Mage Tower!',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL),
(668,'The Horde has taken control of the Mage Tower!',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL),
(669,'The Alliance has taken control of the Draenei Ruins!',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL),
(670,'The Horde has taken control of the Draenei Ruins!',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL),
(671,'The Alliance has taken control of the Blood Elf Tower!',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL),
(672,'The Horde has taken control of the Blood Elf Tower!',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL),
(673,'The Alliance has taken control of the Fel Reaver Ruins!',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL),
(674,'The Horde has taken control of the Fel Reaver Ruins!',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL),
(675,'The Alliance has lost control of the Mage Tower!',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL),
(676,'The Horde has lost control of the Mage Tower!',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL),
(677,'The Alliance has lost control of the Draenei Ruins!',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL),
(678,'The Horde has lost control of the Draenei Ruins!',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL),
(679,'The Alliance has lost control of the Blood Elf Tower!',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL),
(680,'The Horde has lost control of the Blood Elf Tower!',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL),
(681,'The Alliance has lost control of the Fel Reaver Ruins!',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL),
(682,'The Horde has lost control of the Fel Reaver Ruins!',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL),
(683,'%s has taken the flag!',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL),
(684,'The Alliance have captured the flag!',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL),
(685,'The Horde have captured the flag!',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL),
(686,'The flag has been dropped.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL),
(687,'The flag has been reset.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL);

View file

@ -197,6 +197,7 @@ pkgdata_DATA = \
7399_01_mangos_mangos_string.sql \ 7399_01_mangos_mangos_string.sql \
7422_01_mangos_mangos_string.sql \ 7422_01_mangos_mangos_string.sql \
7439_01_mangos_mangos_string.sql \ 7439_01_mangos_mangos_string.sql \
7472_01_mangos_mangos_string.sql \
README README
## Additional files to include when running 'make dist' ## Additional files to include when running 'make dist'
@ -374,4 +375,5 @@ EXTRA_DIST = \
7399_01_mangos_mangos_string.sql \ 7399_01_mangos_mangos_string.sql \
7422_01_mangos_mangos_string.sql \ 7422_01_mangos_mangos_string.sql \
7439_01_mangos_mangos_string.sql \ 7439_01_mangos_mangos_string.sql \
7472_01_mangos_mangos_string.sql \
README README

View file

@ -274,6 +274,36 @@ InstanceData* CreateInstanceData(Map *map)
return tmpscript->GetInstanceData(map); return tmpscript->GetInstanceData(map);
} }
MANGOS_DLL_EXPORT
bool EffectDummyGameObj(Unit *caster, uint32 spellId, uint32 effIndex, GameObject *gameObjTarget )
{
Script *tmpscript = m_scripts[gameObjTarget->GetGOInfo()->ScriptId];
if (!tmpscript || !tmpscript->pEffectDummyGameObj) return false;
return tmpscript->pEffectDummyGameObj(caster, spellId,effIndex,gameObjTarget);
}
MANGOS_DLL_EXPORT
bool EffectDummyCreature(Unit *caster, uint32 spellId, uint32 effIndex, Creature *crTarget )
{
Script *tmpscript = m_scripts[crTarget->GetScriptId()];
if (!tmpscript || !tmpscript->pEffectDummyCreature) return false;
return tmpscript->pEffectDummyCreature(caster, spellId,effIndex,crTarget);
}
MANGOS_DLL_EXPORT
bool EffectDummyItem(Unit *caster, uint32 spellId, uint32 effIndex, Item *itemTarget )
{
Script *tmpscript = m_scripts[itemTarget->GetProto()->ScriptId];
if (!tmpscript || !tmpscript->pEffectDummyItem) return false;
return tmpscript->pEffectDummyItem(caster, spellId,effIndex,itemTarget);
}
void ScriptedAI::UpdateAI(const uint32) void ScriptedAI::UpdateAI(const uint32)
{ {
//Check if we have a current target //Check if we have a current target

View file

@ -41,7 +41,8 @@ struct Script
pGossipHello(NULL), pQuestAccept(NULL), pGossipSelect(NULL), pGossipSelectWithCode(NULL), pGossipHello(NULL), pQuestAccept(NULL), pGossipSelect(NULL), pGossipSelectWithCode(NULL),
pQuestSelect(NULL), pQuestComplete(NULL), pNPCDialogStatus(NULL), pGODialogStatus(NULL), pChooseReward(NULL), pQuestSelect(NULL), pQuestComplete(NULL), pNPCDialogStatus(NULL), pGODialogStatus(NULL), pChooseReward(NULL),
pItemHello(NULL), pGOHello(NULL), pAreaTrigger(NULL), pItemQuestAccept(NULL), pGOQuestAccept(NULL), pItemHello(NULL), pGOHello(NULL), pAreaTrigger(NULL), pItemQuestAccept(NULL), pGOQuestAccept(NULL),
pGOChooseReward(NULL), pReceiveEmote(NULL), pItemUse(NULL), GetAI(NULL) pGOChooseReward(NULL), pReceiveEmote(NULL), pItemUse(NULL), pEffectDummyGameObj(NULL), pEffectDummyCreature(NULL),
pEffectDummyItem(NULL), GetAI(NULL)
{} {}
std::string Name; std::string Name;
@ -64,6 +65,9 @@ struct Script
bool (*pGOChooseReward )(Player *player, GameObject *_GO, Quest const*_Quest, uint32 opt ); bool (*pGOChooseReward )(Player *player, GameObject *_GO, Quest const*_Quest, uint32 opt );
bool (*pReceiveEmote )(Player *player, Creature *_Creature, uint32 emote ); bool (*pReceiveEmote )(Player *player, Creature *_Creature, uint32 emote );
bool (*pItemUse )(Player *player, Item* _Item, SpellCastTargets const& targets); bool (*pItemUse )(Player *player, Item* _Item, SpellCastTargets const& targets);
bool (*pEffectDummyGameObj )(Unit*, uint32, uint32, GameObject* );
bool (*pEffectDummyCreature )(Unit*, uint32, uint32, Creature* );
bool (*pEffectDummyItem )(Unit*, uint32, uint32, Item* );
CreatureAI* (*GetAI)(Creature *_Creature); CreatureAI* (*GetAI)(Creature *_Creature);
InstanceData* (*GetInstanceData)(Map*); InstanceData* (*GetInstanceData)(Map*);

View file

@ -689,12 +689,15 @@ void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, ui
SetCriteriaProgress(achievementCriteria, 1, PROGRESS_ACCUMULATE); SetCriteriaProgress(achievementCriteria, 1, PROGRESS_ACCUMULATE);
break; break;
case ACHIEVEMENT_CRITERIA_TYPE_LEARN_SPELL: case ACHIEVEMENT_CRITERIA_TYPE_LEARN_SPELL:
if(GetPlayer()->HasSpell(achievementCriteria->learn_spell.spellID)) // spell always provide and at login spell learning.
if(miscvalue1 && miscvalue1!=achievementCriteria->learn_spell.spellID)
continue;
if(GetPlayer()->HasSpell(miscvalue1))
SetCriteriaProgress(achievementCriteria, 1); SetCriteriaProgress(achievementCriteria, 1);
break; break;
case ACHIEVEMENT_CRITERIA_TYPE_OWN_ITEM: case ACHIEVEMENT_CRITERIA_TYPE_OWN_ITEM:
// speedup for non-login case // speedup for non-login case
if(miscvalue1 && achievementCriteria->own_item.itemID!=miscvalue1) if(miscvalue1 && achievementCriteria->own_item.itemID != miscvalue1)
continue; continue;
SetCriteriaProgress(achievementCriteria, GetPlayer()->GetItemCount(achievementCriteria->own_item.itemID, true)); SetCriteriaProgress(achievementCriteria, GetPlayer()->GetItemCount(achievementCriteria->own_item.itemID, true));
break; break;
@ -736,6 +739,10 @@ void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, ui
break; break;
case ACHIEVEMENT_CRITERIA_TYPE_GAIN_REPUTATION: case ACHIEVEMENT_CRITERIA_TYPE_GAIN_REPUTATION:
{ {
// skip faction check only at loading
if (miscvalue1 && miscvalue1 != achievementCriteria->gain_reputation.factionID)
continue;
int32 reputation = GetPlayer()->GetReputation(achievementCriteria->gain_reputation.factionID); int32 reputation = GetPlayer()->GetReputation(achievementCriteria->gain_reputation.factionID);
if (reputation > 0) if (reputation > 0)
SetCriteriaProgress(achievementCriteria, reputation); SetCriteriaProgress(achievementCriteria, reputation);
@ -743,6 +750,10 @@ void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, ui
} }
case ACHIEVEMENT_CRITERIA_TYPE_GAIN_EXALTED_REPUTATION: case ACHIEVEMENT_CRITERIA_TYPE_GAIN_EXALTED_REPUTATION:
{ {
// skip faction check only at loading
if (miscvalue1 && GetPlayer()->GetReputationRank(miscvalue1) < REP_EXALTED)
continue;
uint32 counter = 0; uint32 counter = 0;
const FactionStateList factionStateList = GetPlayer()->GetFactionStateList(); const FactionStateList factionStateList = GetPlayer()->GetFactionStateList();
for (FactionStateList::const_iterator iter = factionStateList.begin(); iter!= factionStateList.end(); ++iter) for (FactionStateList::const_iterator iter = factionStateList.begin(); iter!= factionStateList.end(); ++iter)
@ -806,24 +817,43 @@ void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, ui
SetCriteriaProgress(achievementCriteria, 1, PROGRESS_ACCUMULATE); SetCriteriaProgress(achievementCriteria, 1, PROGRESS_ACCUMULATE);
break; break;
} }
case ACHIEVEMENT_CRITERIA_TYPE_EQUIP_ITEM:
// miscvalue1 = item_id
if(!miscvalue1)
continue;
if(miscvalue1 != achievementCriteria->equip_item.itemID)
continue;
SetCriteriaProgress(achievementCriteria, 1, PROGRESS_ACCUMULATE);
break;
case ACHIEVEMENT_CRITERIA_TYPE_LEARN_SKILLLINE_SPELLS: case ACHIEVEMENT_CRITERIA_TYPE_LEARN_SKILLLINE_SPELLS:
{
// spell always provide and at login spell learning.
if(!miscvalue1)
continue;
// rescan only when change possible
SkillLineAbilityMap::const_iterator skillIter0 = spellmgr.GetBeginSkillLineAbilityMap(miscvalue1);
if(skillIter0 == spellmgr.GetEndSkillLineAbilityMap(miscvalue1))
continue;
if(skillIter0->second->skillId != achievementCriteria->learn_skilline_spell.skillLine)
continue;
uint32 spellCount = 0;
for (PlayerSpellMap::const_iterator spellIter = GetPlayer()->GetSpellMap().begin();
spellIter != GetPlayer()->GetSpellMap().end();
++spellIter)
{ {
uint32 spellCount = 0; for(SkillLineAbilityMap::const_iterator skillIter = spellmgr.GetBeginSkillLineAbilityMap(spellIter->first);
for (PlayerSpellMap::const_iterator spellIter = GetPlayer()->GetSpellMap().begin(); skillIter != spellmgr.GetEndSkillLineAbilityMap(spellIter->first);
spellIter != GetPlayer()->GetSpellMap().end(); ++skillIter)
++spellIter)
{ {
for(SkillLineAbilityMap::const_iterator skillIter = spellmgr.GetBeginSkillLineAbilityMap(spellIter->first); if(skillIter->second->skillId == achievementCriteria->learn_skilline_spell.skillLine)
skillIter != spellmgr.GetEndSkillLineAbilityMap(spellIter->first); spellCount++;
++skillIter)
{
if(skillIter->second->skillId == achievementCriteria->learn_skilline_spell.skillLine)
spellCount++;
}
} }
SetCriteriaProgress(achievementCriteria, spellCount);
break;
} }
SetCriteriaProgress(achievementCriteria, spellCount);
break;
}
case ACHIEVEMENT_CRITERIA_TYPE_CAST_SPELL2: case ACHIEVEMENT_CRITERIA_TYPE_CAST_SPELL2:
{ {
if (!miscvalue1 || miscvalue1 != achievementCriteria->cast_spell.spellID) if (!miscvalue1 || miscvalue1 != achievementCriteria->cast_spell.spellID)
@ -876,7 +906,6 @@ void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, ui
case ACHIEVEMENT_CRITERIA_TYPE_HK_RACE: case ACHIEVEMENT_CRITERIA_TYPE_HK_RACE:
case ACHIEVEMENT_CRITERIA_TYPE_HEALING_DONE: case ACHIEVEMENT_CRITERIA_TYPE_HEALING_DONE:
case ACHIEVEMENT_CRITERIA_TYPE_GET_KILLING_BLOWS: case ACHIEVEMENT_CRITERIA_TYPE_GET_KILLING_BLOWS:
case ACHIEVEMENT_CRITERIA_TYPE_EQUIP_ITEM:
case ACHIEVEMENT_CRITERIA_TYPE_MONEY_FROM_VENDORS: case ACHIEVEMENT_CRITERIA_TYPE_MONEY_FROM_VENDORS:
case ACHIEVEMENT_CRITERIA_TYPE_NUMBER_OF_TALENT_RESETS: case ACHIEVEMENT_CRITERIA_TYPE_NUMBER_OF_TALENT_RESETS:
case ACHIEVEMENT_CRITERIA_TYPE_USE_GAMEOBJECT: case ACHIEVEMENT_CRITERIA_TYPE_USE_GAMEOBJECT:
@ -1004,6 +1033,8 @@ bool AchievementMgr::IsCompletedCriteria(AchievementCriteriaEntry const* achieve
return progress->counter >= achievementCriteria->roll_greed_on_loot.count; return progress->counter >= achievementCriteria->roll_greed_on_loot.count;
case ACHIEVEMENT_CRITERIA_TYPE_DO_EMOTE: case ACHIEVEMENT_CRITERIA_TYPE_DO_EMOTE:
return progress->counter >= achievementCriteria->do_emote.count; return progress->counter >= achievementCriteria->do_emote.count;
case ACHIEVEMENT_CRITERIA_TYPE_EQUIP_ITEM:
return progress->counter >= achievementCriteria->equip_item.count;
case ACHIEVEMENT_CRITERIA_TYPE_MONEY_FROM_QUEST_REWARD: case ACHIEVEMENT_CRITERIA_TYPE_MONEY_FROM_QUEST_REWARD:
return progress->counter >= achievementCriteria->quest_reward_money.goldInCopper; return progress->counter >= achievementCriteria->quest_reward_money.goldInCopper;
case ACHIEVEMENT_CRITERIA_TYPE_LOOT_MONEY: case ACHIEVEMENT_CRITERIA_TYPE_LOOT_MONEY:

View file

@ -428,9 +428,10 @@ void BattleGround::Update(uint32 diff)
if(GetStatus() == STATUS_WAIT_LEAVE) if(GetStatus() == STATUS_WAIT_LEAVE)
{ {
// remove all players from battleground after 2 minutes // remove all players from battleground after 2 minutes
m_EndTime += diff; m_EndTime -= diff;
if(m_EndTime >= TIME_TO_AUTOREMOVE) // 2 minutes if( m_EndTime <= 0)
{ {
m_EndTime = 0;
BattleGroundPlayerMap::iterator itr, next; BattleGroundPlayerMap::iterator itr, next;
for(itr = m_Players.begin(); itr != m_Players.end(); itr = next) for(itr = m_Players.begin(); itr != m_Players.end(); itr = next)
{ {
@ -443,6 +444,8 @@ void BattleGround::Update(uint32 diff)
} }
} }
//update start time
m_StartTime += diff;
} }
void BattleGround::SetTeamStartLoc(uint32 TeamID, float X, float Y, float Z, float O) void BattleGround::SetTeamStartLoc(uint32 TeamID, float X, float Y, float Z, float O)
@ -633,7 +636,8 @@ void BattleGround::EndBattleGround(uint32 winner)
} }
SetStatus(STATUS_WAIT_LEAVE); SetStatus(STATUS_WAIT_LEAVE);
m_EndTime = 0; //we must set it this way, because end time is sent in packet!
m_EndTime = TIME_TO_AUTOREMOVE;
// arena rating calculation // arena rating calculation
if(isArena() && isRated()) if(isArena() && isRated())
@ -716,7 +720,7 @@ void BattleGround::EndBattleGround(uint32 winner)
plr->GetSession()->SendPacket(&data); plr->GetSession()->SendPacket(&data);
BattleGroundQueueTypeId bgQueueTypeId = BattleGroundMgr::BGQueueTypeId(GetTypeID(), GetArenaType()); BattleGroundQueueTypeId bgQueueTypeId = BattleGroundMgr::BGQueueTypeId(GetTypeID(), GetArenaType());
sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, this, plr->GetBattleGroundQueueIndex(bgQueueTypeId), STATUS_IN_PROGRESS, TIME_TO_AUTOREMOVE, GetStartTime()); sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, this, plr->GetBattleGroundQueueIndex(bgQueueTypeId), STATUS_IN_PROGRESS, TIME_TO_AUTOREMOVE, GetStartTime(), GetArenaType());
plr->GetSession()->SendPacket(&data); plr->GetSession()->SendPacket(&data);
plr->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_BATTLEGROUND, 1); plr->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_BATTLEGROUND, 1);
} }
@ -964,7 +968,7 @@ void BattleGround::RemovePlayerAtLeave(uint64 guid, bool Transport, bool SendPac
if(SendPacket) if(SendPacket)
{ {
WorldPacket data; WorldPacket data;
sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, this, plr->GetBattleGroundQueueIndex(bgQueueTypeId), STATUS_NONE, 0, 0); sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, this, plr->GetBattleGroundQueueIndex(bgQueueTypeId), STATUS_NONE, 0, 0, 0);
plr->GetSession()->SendPacket(&data); plr->GetSession()->SendPacket(&data);
} }
@ -1155,10 +1159,15 @@ void BattleGround::AddOrSetPlayerToCorrectBgGroup(Player *plr, uint64 plr_guid,
if(group->IsMember(plr_guid)) if(group->IsMember(plr_guid))
{ {
uint8 subgroup = group->GetMemberGroup(plr_guid); uint8 subgroup = group->GetMemberGroup(plr_guid);
plr->SetGroup(group, subgroup); plr->SetBattleGroundRaid(group, subgroup);
} }
else else
GetBgRaid(team)->AddMember(plr_guid, plr->GetName()); {
group->AddMember(plr_guid, plr->GetName());
if( Group* originalGroup = plr->GetOriginalGroup() )
if( originalGroup->IsLeader(plr_guid) )
group->ChangeLeader(plr_guid);
}
} }
} }
@ -1191,7 +1200,11 @@ void BattleGround::EventPlayerLoggedOut(Player* player)
if( isBattleGround() ) if( isBattleGround() )
EventPlayerDroppedFlag(player); EventPlayerDroppedFlag(player);
else else
CheckArenaWinConditions(); {
//1 player is logging out, if it is the last, then end arena!
if( GetAlivePlayersCountByTeam(player->GetTeam()) <= 1 && GetPlayersCountByTeam(GetOtherTeam(player->GetTeam())) )
EndBattleGround(GetOtherTeam(player->GetTeam()));
}
} }
} }
@ -1589,7 +1602,7 @@ void BattleGround::EndNow()
{ {
RemoveFromBGFreeSlotQueue(); RemoveFromBGFreeSlotQueue();
SetStatus(STATUS_WAIT_LEAVE); SetStatus(STATUS_WAIT_LEAVE);
SetEndTime(TIME_TO_AUTOREMOVE); SetEndTime(0);
// inform invited players about the removal // inform invited players about the removal
sBattleGroundMgr.m_BattleGroundQueues[BattleGroundMgr::BGQueueTypeId(GetTypeID(), GetArenaType())].BGEndedRemoveInvites(this); sBattleGroundMgr.m_BattleGroundQueues[BattleGroundMgr::BGQueueTypeId(GetTypeID(), GetArenaType())].BGEndedRemoveInvites(this);
} }
@ -1659,8 +1672,9 @@ void BattleGround::HandleKillPlayer( Player *player, Player *killer )
} }
} }
// to be able to remove insignia // to be able to remove insignia -- ONLY IN BattleGrounds
player->SetFlag( UNIT_FIELD_FLAGS, UNIT_FLAG_SKINNABLE ); if( !isArena() )
player->SetFlag( UNIT_FIELD_FLAGS, UNIT_FLAG_SKINNABLE );
} }
// return the player's team based on battlegroundplayer info // return the player's team based on battlegroundplayer info
@ -1699,7 +1713,7 @@ void BattleGround::PlayerAddedToBGCheckIfBGIsRunning(Player* plr)
sBattleGroundMgr.BuildPvpLogDataPacket(&data, this); sBattleGroundMgr.BuildPvpLogDataPacket(&data, this);
plr->GetSession()->SendPacket(&data); plr->GetSession()->SendPacket(&data);
sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, this, plr->GetBattleGroundQueueIndex(bgQueueTypeId), STATUS_IN_PROGRESS, TIME_TO_AUTOREMOVE, GetStartTime()); sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, this, plr->GetBattleGroundQueueIndex(bgQueueTypeId), STATUS_IN_PROGRESS, GetEndTime(), GetStartTime(), GetArenaType());
plr->GetSession()->SendPacket(&data); plr->GetSession()->SendPacket(&data);
} }

View file

@ -530,7 +530,7 @@ class BattleGround
BattleGroundStatus m_Status; BattleGroundStatus m_Status;
uint32 m_ClientInstanceID; //the instance-id which is sent to the client and without any other internal use uint32 m_ClientInstanceID; //the instance-id which is sent to the client and without any other internal use
uint32 m_StartTime; uint32 m_StartTime;
uint32 m_EndTime; int32 m_EndTime; // it is set to 120000 when bg is ending and it decreases itself
uint32 m_LastResurrectTime; uint32 m_LastResurrectTime;
BGQueueIdBasedOnLevel m_QueueId; BGQueueIdBasedOnLevel m_QueueId;
uint8 m_ArenaType; // 2=2v2, 3=3v3, 5=5v5 uint8 m_ArenaType; // 2=2v2, 3=3v3, 5=5v5

View file

@ -48,7 +48,7 @@ void BattleGroundAB::Update(uint32 diff)
if( GetStatus() == STATUS_IN_PROGRESS ) if( GetStatus() == STATUS_IN_PROGRESS )
{ {
int team_points[2] = { 0, 0 }; int team_points[BG_TEAMS_COUNT] = { 0, 0 };
for (int node = 0; node < BG_AB_DYNAMIC_NODES_COUNT; ++node) for (int node = 0; node < BG_AB_DYNAMIC_NODES_COUNT; ++node)
{ {
@ -88,24 +88,24 @@ void BattleGroundAB::Update(uint32 diff)
{ {
// FIXME: team and node names not localized // FIXME: team and node names not localized
SendMessage2ToAll(LANG_BG_AB_NODE_TAKEN,CHAT_MSG_BG_SYSTEM_ALLIANCE,NULL,LANG_BG_AB_ALLY,_GetNodeNameId(node)); SendMessage2ToAll(LANG_BG_AB_NODE_TAKEN,CHAT_MSG_BG_SYSTEM_ALLIANCE,NULL,LANG_BG_AB_ALLY,_GetNodeNameId(node));
PlaySoundToAll(SOUND_NODE_CAPTURED_ALLIANCE); PlaySoundToAll(BG_AB_SOUND_NODE_CAPTURED_ALLIANCE);
} }
else else
{ {
// FIXME: team and node names not localized // FIXME: team and node names not localized
SendMessage2ToAll(LANG_BG_AB_NODE_TAKEN,CHAT_MSG_BG_SYSTEM_HORDE,NULL,LANG_BG_AB_HORDE,_GetNodeNameId(node)); SendMessage2ToAll(LANG_BG_AB_NODE_TAKEN,CHAT_MSG_BG_SYSTEM_HORDE,NULL,LANG_BG_AB_HORDE,_GetNodeNameId(node));
PlaySoundToAll(SOUND_NODE_CAPTURED_HORDE); PlaySoundToAll(BG_AB_SOUND_NODE_CAPTURED_HORDE);
} }
} }
} }
for (int team = 0; team < 2; ++team) for (int team = 0; team < BG_TEAMS_COUNT; ++team)
if( m_Nodes[node] == team + BG_AB_NODE_TYPE_OCCUPIED ) if( m_Nodes[node] == team + BG_AB_NODE_TYPE_OCCUPIED )
++team_points[team]; ++team_points[team];
} }
// Accumulate points // Accumulate points
for (int team = 0; team < 2; ++team) for (int team = 0; team < BG_TEAMS_COUNT; ++team)
{ {
int points = team_points[team]; int points = team_points[team];
if( !points ) if( !points )
@ -127,18 +127,18 @@ void BattleGroundAB::Update(uint32 diff)
RewardHonorToTeam(GetBonusHonorFromKill(1), (team == BG_TEAM_ALLIANCE) ? ALLIANCE : HORDE); RewardHonorToTeam(GetBonusHonorFromKill(1), (team == BG_TEAM_ALLIANCE) ? ALLIANCE : HORDE);
m_HonorScoreTics[team] -= m_HonorTics; m_HonorScoreTics[team] -= m_HonorTics;
} }
if( !m_IsInformedNearVictory && m_TeamScores[team] > 1800 ) if( !m_IsInformedNearVictory && m_TeamScores[team] > BG_AB_WARNING_NEAR_VICTORY_SCORE )
{ {
if( team == BG_TEAM_ALLIANCE ) if( team == BG_TEAM_ALLIANCE )
SendMessageToAll(LANG_BG_AB_A_NEAR_VICTORY, CHAT_MSG_BG_SYSTEM_NEUTRAL); SendMessageToAll(LANG_BG_AB_A_NEAR_VICTORY, CHAT_MSG_BG_SYSTEM_NEUTRAL);
else else
SendMessageToAll(LANG_BG_AB_H_NEAR_VICTORY, CHAT_MSG_BG_SYSTEM_NEUTRAL); SendMessageToAll(LANG_BG_AB_H_NEAR_VICTORY, CHAT_MSG_BG_SYSTEM_NEUTRAL);
PlaySoundToAll(SOUND_NEAR_VICTORY); PlaySoundToAll(BG_AB_SOUND_NEAR_VICTORY);
m_IsInformedNearVictory = true; m_IsInformedNearVictory = true;
} }
if( m_TeamScores[team] > 2000 ) if( m_TeamScores[team] > BG_AB_MAX_TEAM_SCORE )
m_TeamScores[team] = 2000; m_TeamScores[team] = BG_AB_MAX_TEAM_SCORE;
if( team == BG_TEAM_ALLIANCE ) if( team == BG_TEAM_ALLIANCE )
UpdateWorldState(BG_AB_OP_RESOURCES_ALLY, m_TeamScores[team]); UpdateWorldState(BG_AB_OP_RESOURCES_ALLY, m_TeamScores[team]);
if( team == BG_TEAM_HORDE ) if( team == BG_TEAM_HORDE )
@ -147,9 +147,9 @@ void BattleGroundAB::Update(uint32 diff)
} }
// Test win condition // Test win condition
if( m_TeamScores[BG_TEAM_ALLIANCE] >= 2000 ) if( m_TeamScores[BG_TEAM_ALLIANCE] >= BG_AB_MAX_TEAM_SCORE )
EndBattleGround(ALLIANCE); EndBattleGround(ALLIANCE);
if( m_TeamScores[BG_TEAM_HORDE] >= 2000 ) if( m_TeamScores[BG_TEAM_HORDE] >= BG_AB_MAX_TEAM_SCORE )
EndBattleGround(HORDE); EndBattleGround(HORDE);
} }
} }
@ -313,7 +313,7 @@ void BattleGroundAB::FillInitialWorldStates(WorldPacket& data)
// Team scores // Team scores
data << uint32(BG_AB_OP_RESOURCES_MAX) << uint32(BG_AB_MAX_TEAM_SCORE); data << uint32(BG_AB_OP_RESOURCES_MAX) << uint32(BG_AB_MAX_TEAM_SCORE);
data << uint32(BG_AB_OP_RESOURCES_WARNING) << uint32(BG_AB_WARNING_SCORE); data << uint32(BG_AB_OP_RESOURCES_WARNING) << uint32(BG_AB_WARNING_NEAR_VICTORY_SCORE);
data << uint32(BG_AB_OP_RESOURCES_ALLY) << uint32(m_TeamScores[BG_TEAM_ALLIANCE]); data << uint32(BG_AB_OP_RESOURCES_ALLY) << uint32(m_TeamScores[BG_TEAM_ALLIANCE]);
data << uint32(BG_AB_OP_RESOURCES_HORDE) << uint32(m_TeamScores[BG_TEAM_HORDE]); data << uint32(BG_AB_OP_RESOURCES_HORDE) << uint32(m_TeamScores[BG_TEAM_HORDE]);
@ -440,7 +440,7 @@ void BattleGroundAB::EventPlayerClickedOnFlag(Player *source, GameObject* /*targ
else else
SendMessage2ToAll(LANG_BG_AB_NODE_CLAIMED,CHAT_MSG_BG_SYSTEM_HORDE, source, _GetNodeNameId(node), LANG_BG_AB_HORDE); SendMessage2ToAll(LANG_BG_AB_NODE_CLAIMED,CHAT_MSG_BG_SYSTEM_HORDE, source, _GetNodeNameId(node), LANG_BG_AB_HORDE);
sound = SOUND_NODE_CLAIMED; sound = BG_AB_SOUND_NODE_CLAIMED;
} }
// If node is contested // If node is contested
else if( (m_Nodes[node] == BG_AB_NODE_STATUS_ALLY_CONTESTED) || (m_Nodes[node] == BG_AB_NODE_STATUS_HORDE_CONTESTED) ) else if( (m_Nodes[node] == BG_AB_NODE_STATUS_ALLY_CONTESTED) || (m_Nodes[node] == BG_AB_NODE_STATUS_HORDE_CONTESTED) )
@ -484,7 +484,7 @@ void BattleGroundAB::EventPlayerClickedOnFlag(Player *source, GameObject* /*targ
else else
SendMessage2ToAll(LANG_BG_AB_NODE_DEFENDED,CHAT_MSG_BG_SYSTEM_HORDE, source, _GetNodeNameId(node)); SendMessage2ToAll(LANG_BG_AB_NODE_DEFENDED,CHAT_MSG_BG_SYSTEM_HORDE, source, _GetNodeNameId(node));
} }
sound = (teamIndex == 0) ? SOUND_NODE_ASSAULTED_ALLIANCE : SOUND_NODE_ASSAULTED_HORDE; sound = (teamIndex == 0) ? BG_AB_SOUND_NODE_ASSAULTED_ALLIANCE : BG_AB_SOUND_NODE_ASSAULTED_HORDE;
} }
// If node is occupied, change to enemy-contested // If node is occupied, change to enemy-contested
else else
@ -506,7 +506,7 @@ void BattleGroundAB::EventPlayerClickedOnFlag(Player *source, GameObject* /*targ
else else
SendMessage2ToAll(LANG_BG_AB_NODE_ASSAULTED,CHAT_MSG_BG_SYSTEM_HORDE, source, _GetNodeNameId(node)); SendMessage2ToAll(LANG_BG_AB_NODE_ASSAULTED,CHAT_MSG_BG_SYSTEM_HORDE, source, _GetNodeNameId(node));
sound = (teamIndex == 0) ? SOUND_NODE_ASSAULTED_ALLIANCE : SOUND_NODE_ASSAULTED_HORDE; sound = (teamIndex == 0) ? 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 node is occupied again, send "X has taken the Y" msg.

View file

@ -75,17 +75,17 @@ enum BG_AB_NodeObjectId
enum BG_AB_ObjectType enum BG_AB_ObjectType
{ {
// for all 5 node points 8*5=40 objects // for all 5 node points 8*5=40 objects
BG_AB_OBJECT_BANNER_NEUTRAL = 0, BG_AB_OBJECT_BANNER_NEUTRAL = 0,
BG_AB_OBJECT_BANNER_CONT_A = 1, BG_AB_OBJECT_BANNER_CONT_A = 1,
BG_AB_OBJECT_BANNER_CONT_H = 2, BG_AB_OBJECT_BANNER_CONT_H = 2,
BG_AB_OBJECT_BANNER_ALLY = 3, BG_AB_OBJECT_BANNER_ALLY = 3,
BG_AB_OBJECT_BANNER_HORDE = 4, BG_AB_OBJECT_BANNER_HORDE = 4,
BG_AB_OBJECT_AURA_ALLY = 5, BG_AB_OBJECT_AURA_ALLY = 5,
BG_AB_OBJECT_AURA_HORDE = 6, BG_AB_OBJECT_AURA_HORDE = 6,
BG_AB_OBJECT_AURA_CONTESTED = 7, BG_AB_OBJECT_AURA_CONTESTED = 7,
//gates //gates
BG_AB_OBJECT_GATE_A = 40, BG_AB_OBJECT_GATE_A = 40,
BG_AB_OBJECT_GATE_H = 41, BG_AB_OBJECT_GATE_H = 41,
//buffs //buffs
BG_AB_OBJECT_SPEEDBUFF_STABLES = 42, BG_AB_OBJECT_SPEEDBUFF_STABLES = 42,
BG_AB_OBJECT_REGENBUFF_STABLES = 43, BG_AB_OBJECT_REGENBUFF_STABLES = 43,
@ -128,8 +128,8 @@ enum BG_AB_Timers
enum BG_AB_Score enum BG_AB_Score
{ {
BG_AB_MAX_TEAM_SCORE = 2000, BG_AB_WARNING_NEAR_VICTORY_SCORE = 1800,
BG_AB_WARNING_SCORE = 1800 BG_AB_MAX_TEAM_SCORE = 2000
}; };
/* do NOT change the order, else wrong behaviour */ /* do NOT change the order, else wrong behaviour */
@ -162,18 +162,18 @@ enum BG_AB_NodeStatus
enum BG_AB_Sounds enum BG_AB_Sounds
{ {
SOUND_NODE_CLAIMED = 8192, BG_AB_SOUND_NODE_CLAIMED = 8192,
SOUND_NODE_CAPTURED_ALLIANCE = 8173, BG_AB_SOUND_NODE_CAPTURED_ALLIANCE = 8173,
SOUND_NODE_CAPTURED_HORDE = 8213, BG_AB_SOUND_NODE_CAPTURED_HORDE = 8213,
SOUND_NODE_ASSAULTED_ALLIANCE = 8174, BG_AB_SOUND_NODE_ASSAULTED_ALLIANCE = 8174,
SOUND_NODE_ASSAULTED_HORDE = 8212, BG_AB_SOUND_NODE_ASSAULTED_HORDE = 8212,
SOUND_NEAR_VICTORY = 8456 BG_AB_SOUND_NEAR_VICTORY = 8456
}; };
#define BG_AB_NotABBGWeekendHonorTicks 330 #define BG_AB_NotABBGWeekendHonorTicks 330
#define BG_AB_ABBGWeekendHonorTicks 200 #define BG_AB_ABBGWeekendHonorTicks 200
#define BG_AB_NotABBGWeekendReputationTicks 200 #define BG_AB_NotABBGWeekendReputationTicks 200
#define BG_AB_ABBGWeekendReputationTicks 150 #define BG_AB_ABBGWeekendReputationTicks 150
// x, y, z, o // x, y, z, o
const float BG_AB_NodePositions[BG_AB_DYNAMIC_NODES_COUNT][4] = { const float BG_AB_NodePositions[BG_AB_DYNAMIC_NODES_COUNT][4] = {
@ -283,10 +283,10 @@ class BattleGroundAB : public BattleGround
uint8 m_prevNodes[BG_AB_DYNAMIC_NODES_COUNT]; uint8 m_prevNodes[BG_AB_DYNAMIC_NODES_COUNT];
BG_AB_BannerTimer m_BannerTimers[BG_AB_DYNAMIC_NODES_COUNT]; BG_AB_BannerTimer m_BannerTimers[BG_AB_DYNAMIC_NODES_COUNT];
int32 m_NodeTimers[BG_AB_DYNAMIC_NODES_COUNT]; int32 m_NodeTimers[BG_AB_DYNAMIC_NODES_COUNT];
uint32 m_TeamScores[2]; uint32 m_TeamScores[BG_TEAMS_COUNT];
uint32 m_lastTick[2]; uint32 m_lastTick[BG_TEAMS_COUNT];
uint32 m_HonorScoreTics[2]; uint32 m_HonorScoreTics[BG_TEAMS_COUNT];
uint32 m_ReputationScoreTics[2]; uint32 m_ReputationScoreTics[BG_TEAMS_COUNT];
bool m_IsInformedNearVictory; bool m_IsInformedNearVictory;
uint32 m_HonorTics; uint32 m_HonorTics;
uint32 m_ReputationTics; uint32 m_ReputationTics;

View file

@ -258,9 +258,20 @@ void BattleGroundEY::UpdatePointStatuses()
void BattleGroundEY::UpdateTeamScore(uint32 Team) void BattleGroundEY::UpdateTeamScore(uint32 Team)
{ {
uint32 score = GetTeamScore(Team); uint32 score = GetTeamScore(Team);
if(score >= EY_MAX_TEAM_SCORE) //TODO there should be some sound played when one team is near victory!! - and define variables
/*if( !m_IsInformedNearVictory && score >= BG_EY_WARNING_NEAR_VICTORY_SCORE )
{ {
score = EY_MAX_TEAM_SCORE; if( Team == ALLIANCE )
SendMessageToAll(LANG_BG_EY_A_NEAR_VICTORY, CHAT_MSG_BG_SYSTEM_NEUTRAL);
else
SendMessageToAll(LANG_BG_EY_H_NEAR_VICTORY, CHAT_MSG_BG_SYSTEM_NEUTRAL);
PlaySoundToAll(BG_EY_SOUND_NEAR_VICTORY);
m_IsInformedNearVictory = true;
}*/
if( score >= BG_EY_MAX_TEAM_SCORE )
{
score = BG_EY_MAX_TEAM_SCORE;
EndBattleGround(Team); EndBattleGround(Team);
} }
@ -509,7 +520,7 @@ void BattleGroundEY::Reset()
m_PointAddingTimer = 0; m_PointAddingTimer = 0;
m_TowerCapCheckTimer = 0; m_TowerCapCheckTimer = 0;
bool isBGWeekend = false; //TODO FIXME - call sBattleGroundMgr.IsBGWeekend(m_TypeID); - you must also implement that call! bool isBGWeekend = false; //TODO FIXME - call sBattleGroundMgr.IsBGWeekend(m_TypeID); - you must also implement that call!
uint32 m_HonorTics = (isBGWeekend) ? BG_EY_EYWeekendHonorTicks : BG_EY_NotEYWeekendHonorTicks; m_HonorTics = (isBGWeekend) ? BG_EY_EYWeekendHonorTicks : BG_EY_NotEYWeekendHonorTicks;
for(uint8 i = 0; i < EY_POINTS_MAX; ++i) for(uint8 i = 0; i < EY_POINTS_MAX; ++i)
{ {
@ -594,9 +605,9 @@ void BattleGroundEY::EventPlayerDroppedFlag(Player *Source)
UpdateWorldState(NETHERSTORM_FLAG_STATE_ALLIANCE, BG_EY_FLAG_STATE_WAIT_RESPAWN); UpdateWorldState(NETHERSTORM_FLAG_STATE_ALLIANCE, BG_EY_FLAG_STATE_WAIT_RESPAWN);
if(Source->GetTeam() == ALLIANCE) if(Source->GetTeam() == ALLIANCE)
SendMessageToAll(LANG_BG_EY_DROPPED_FLAG,CHAT_MSG_BG_SYSTEM_ALLIANCE, Source); SendMessageToAll(LANG_BG_EY_DROPPED_FLAG, CHAT_MSG_BG_SYSTEM_ALLIANCE, NULL);
else else
SendMessageToAll(LANG_BG_EY_DROPPED_FLAG,CHAT_MSG_BG_SYSTEM_HORDE, Source); SendMessageToAll(LANG_BG_EY_DROPPED_FLAG, CHAT_MSG_BG_SYSTEM_HORDE, NULL);
} }
void BattleGroundEY::EventPlayerClickedOnFlag(Player *Source, GameObject* target_obj) void BattleGroundEY::EventPlayerClickedOnFlag(Player *Source, GameObject* target_obj)
@ -626,9 +637,9 @@ void BattleGroundEY::EventPlayerClickedOnFlag(Player *Source, GameObject* target
Source->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_ENTER_PVP_COMBAT); Source->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_ENTER_PVP_COMBAT);
if(Source->GetTeam() == ALLIANCE) if(Source->GetTeam() == ALLIANCE)
SendMessageToAll(LANG_BG_EY_HAS_TAKEN_FLAG,CHAT_MSG_BG_SYSTEM_ALLIANCE, Source); PSendMessageToAll(LANG_BG_EY_HAS_TAKEN_FLAG, CHAT_MSG_BG_SYSTEM_ALLIANCE, NULL, Source->GetName());
else else
SendMessageToAll(LANG_BG_EY_HAS_TAKEN_FLAG,CHAT_MSG_BG_SYSTEM_HORDE, Source); PSendMessageToAll(LANG_BG_EY_HAS_TAKEN_FLAG, CHAT_MSG_BG_SYSTEM_HORDE, NULL, Source->GetName());
} }
void BattleGroundEY::EventTeamLostPoint(Player *Source, uint32 Point) void BattleGroundEY::EventTeamLostPoint(Player *Source, uint32 Point)

View file

@ -23,9 +23,8 @@
class BattleGround; class BattleGround;
#define EY_MAX_TEAM_SCORE 2000 #define BG_EY_FLAG_RESPAWN_TIME (10*IN_MILISECONDS) //10 seconds
#define BG_EY_FLAG_RESPAWN_TIME (10*IN_MILISECONDS) //10 seconds #define BG_EY_FPOINTS_TICK_TIME (2*IN_MILISECONDS) //2 seconds
#define BG_EY_FPOINTS_TICK_TIME (2*IN_MILISECONDS) //2 seconds
enum BG_EY_WorldStates enum BG_EY_WorldStates
{ {
@ -71,11 +70,11 @@ enum BG_EY_ProgressBarConsts
enum BG_EY_Sounds enum BG_EY_Sounds
{ {
//strange ids, but sure about them //strange ids, but sure about them
BG_EY_SOUND_FLAG_PICKED_UP_ALLIANCE = 8212, BG_EY_SOUND_FLAG_PICKED_UP_ALLIANCE = 8212,
BG_EY_SOUND_FLAG_CAPTURED_HORDE = 8213, BG_EY_SOUND_FLAG_CAPTURED_HORDE = 8213,
BG_EY_SOUND_FLAG_PICKED_UP_HORDE = 8174, BG_EY_SOUND_FLAG_PICKED_UP_HORDE = 8174,
BG_EY_SOUND_FLAG_CAPTURED_ALLIANCE = 8173, BG_EY_SOUND_FLAG_CAPTURED_ALLIANCE = 8173,
BG_EY_SOUND_FLAG_RESET = 8192 BG_EY_SOUND_FLAG_RESET = 8192
}; };
enum BG_EY_Spells enum BG_EY_Spells
@ -86,18 +85,18 @@ enum BG_EY_Spells
enum EYBattleGroundObjectEntry enum EYBattleGroundObjectEntry
{ {
BG_OBJECT_A_DOOR_EY_ENTRY = 184719, //Alliance door BG_OBJECT_A_DOOR_EY_ENTRY = 184719, //Alliance door
BG_OBJECT_H_DOOR_EY_ENTRY = 184720, //Horde door BG_OBJECT_H_DOOR_EY_ENTRY = 184720, //Horde door
BG_OBJECT_FLAG1_EY_ENTRY = 184493, //Netherstorm flag (generic) BG_OBJECT_FLAG1_EY_ENTRY = 184493, //Netherstorm flag (generic)
BG_OBJECT_FLAG2_EY_ENTRY = 184141, //Netherstorm flag (flagstand) BG_OBJECT_FLAG2_EY_ENTRY = 184141, //Netherstorm flag (flagstand)
BG_OBJECT_FLAG3_EY_ENTRY = 184142, //Netherstorm flag (flagdrop) BG_OBJECT_FLAG3_EY_ENTRY = 184142, //Netherstorm flag (flagdrop)
BG_OBJECT_A_BANNER_EY_ENTRY = 184381, //Visual Banner (Alliance) BG_OBJECT_A_BANNER_EY_ENTRY = 184381, //Visual Banner (Alliance)
BG_OBJECT_H_BANNER_EY_ENTRY = 184380, //Visual Banner (Horde) BG_OBJECT_H_BANNER_EY_ENTRY = 184380, //Visual Banner (Horde)
BG_OBJECT_N_BANNER_EY_ENTRY = 184382, //Visual Banner (Neutral) BG_OBJECT_N_BANNER_EY_ENTRY = 184382, //Visual Banner (Neutral)
BG_OBJECT_BE_TOWER_CAP_EY_ENTRY = 184080, //BE Tower Cap Pt BG_OBJECT_BE_TOWER_CAP_EY_ENTRY = 184080, //BE Tower Cap Pt
BG_OBJECT_FR_TOWER_CAP_EY_ENTRY = 184081, //Fel Reaver Cap Pt BG_OBJECT_FR_TOWER_CAP_EY_ENTRY = 184081, //Fel Reaver Cap Pt
BG_OBJECT_HU_TOWER_CAP_EY_ENTRY = 184082, //Human Tower Cap Pt BG_OBJECT_HU_TOWER_CAP_EY_ENTRY = 184082, //Human Tower Cap Pt
BG_OBJECT_DR_TOWER_CAP_EY_ENTRY = 184083 //Draenei Tower Cap Pt BG_OBJECT_DR_TOWER_CAP_EY_ENTRY = 184083 //Draenei Tower Cap Pt
}; };
enum EYBattleGroundPointsTrigger enum EYBattleGroundPointsTrigger
@ -129,7 +128,7 @@ enum EYBattleGroundPoints
DRAENEI_RUINS = 2, DRAENEI_RUINS = 2,
MAGE_TOWER = 3, MAGE_TOWER = 3,
EY_PLAYERS_OUT_OF_POINTS = 4, EY_PLAYERS_OUT_OF_POINTS = 4,
EY_POINTS_MAX = 4 EY_POINTS_MAX = 4
}; };
@ -210,8 +209,14 @@ enum EYBattleGroundObjectTypes
BG_EY_OBJECT_MAX = 59 BG_EY_OBJECT_MAX = 59
}; };
#define BG_EY_NotEYWeekendHonorTicks 330 #define BG_EY_NotEYWeekendHonorTicks 330
#define BG_EY_EYWeekendHonorTicks 200 #define BG_EY_EYWeekendHonorTicks 200
enum BG_EY_Score
{
BG_EY_WARNING_NEAR_VICTORY_SCORE = 1800,
BG_EY_MAX_TEAM_SCORE = 2000
};
enum BG_EY_FlagState enum BG_EY_FlagState
{ {

View file

@ -127,7 +127,7 @@ void WorldSession::HandleBattleGroundJoinOpcode( WorldPacket & recv_data )
if( !_player->CanJoinToBattleground() ) if( !_player->CanJoinToBattleground() )
{ {
WorldPacket data(SMSG_GROUP_JOINED_BATTLEGROUND, 4); WorldPacket data(SMSG_GROUP_JOINED_BATTLEGROUND, 4);
data << (uint32) 0xFFFFFFFE; data << uint32(0xFFFFFFFE);
_player->GetSession()->SendPacket(&data); _player->GetSession()->SendPacket(&data);
return; return;
} }
@ -173,7 +173,7 @@ void WorldSession::HandleBattleGroundJoinOpcode( WorldPacket & recv_data )
WorldPacket data; WorldPacket data;
// send status packet (in queue) // send status packet (in queue)
sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, queueSlot, STATUS_WAIT_QUEUE, avgTime, 0); sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, queueSlot, STATUS_WAIT_QUEUE, avgTime, 0, ginfo->ArenaType);
member->GetSession()->SendPacket(&data); member->GetSession()->SendPacket(&data);
sBattleGroundMgr.BuildGroupJoinedBattlegroundPacket(&data, bgTypeId); sBattleGroundMgr.BuildGroupJoinedBattlegroundPacket(&data, bgTypeId);
member->GetSession()->SendPacket(&data); member->GetSession()->SendPacket(&data);
@ -191,7 +191,7 @@ void WorldSession::HandleBattleGroundJoinOpcode( WorldPacket & recv_data )
WorldPacket data; WorldPacket data;
// send status packet (in queue) // send status packet (in queue)
sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, queueSlot, STATUS_WAIT_QUEUE, avgTime, 0); sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, queueSlot, STATUS_WAIT_QUEUE, avgTime, 0, ginfo->ArenaType);
SendPacket(&data); SendPacket(&data);
sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].AddPlayer(_player, ginfo); sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].AddPlayer(_player, ginfo);
@ -302,25 +302,25 @@ void WorldSession::HandleBattleGroundPlayerPortOpcode( WorldPacket &recv_data )
recv_data >> type >> unk2 >> bgTypeId_ >> unk >> action; recv_data >> type >> unk2 >> bgTypeId_ >> unk >> action;
if(!sBattlemasterListStore.LookupEntry(bgTypeId_)) if( !sBattlemasterListStore.LookupEntry(bgTypeId_) )
{ {
sLog.outError("Battleground: invalid bgtype (%u) received.",bgTypeId_); sLog.outError("Battleground: invalid bgtype (%u) received.", bgTypeId_);
// update battleground slots for the player to fix his UI and sent data. // update battleground slots for the player to fix his UI and sent data.
// this is a HACK, I don't know why the client starts sending invalid packets in the first place. // this is a HACK, I don't know why the client starts sending invalid packets in the first place.
// it usually happens with extremely high latency (if debugging / stepping in the code for example) // it usually happens with extremely high latency (if debugging / stepping in the code for example)
if(_player->InBattleGroundQueue()) if( _player->InBattleGroundQueue() )
{ {
// update all queues, send invitation info if player is invited, queue info if queued // update all queues, send invitation info if player is invited, queue info if queued
for (uint32 i = 0; i < PLAYER_MAX_BATTLEGROUND_QUEUES; i++) for (uint32 i = 0; i < PLAYER_MAX_BATTLEGROUND_QUEUES; i++)
{ {
BattleGroundQueueTypeId bgQueueTypeId = _player->GetBattleGroundQueueTypeId(i); BattleGroundQueueTypeId bgQueueTypeId = _player->GetBattleGroundQueueTypeId(i);
if(!bgQueueTypeId) if( !bgQueueTypeId )
continue; continue;
BattleGroundTypeId bgTypeId = BattleGroundMgr::BGTemplateId(bgQueueTypeId); BattleGroundTypeId bgTypeId = BattleGroundMgr::BGTemplateId(bgQueueTypeId);
BattleGroundQueue::QueuedPlayersMap& qpMap = sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].m_QueuedPlayers; BattleGroundQueue::QueuedPlayersMap& qpMap = sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].m_QueuedPlayers;
BattleGroundQueue::QueuedPlayersMap::iterator itrPlayerStatus = qpMap.find(_player->GetGUID()); BattleGroundQueue::QueuedPlayersMap::iterator itrPlayerStatus = qpMap.find(_player->GetGUID());
// if the player is not in queue, continue or no group information - this should never happen // if the player is not in queue, continue or no group information - this should never happen
if(itrPlayerStatus == qpMap.end() || !itrPlayerStatus->second.GroupInfo) if( itrPlayerStatus == qpMap.end() || !itrPlayerStatus->second.GroupInfo )
continue; continue;
BattleGround * bg = NULL; BattleGround * bg = NULL;
@ -329,7 +329,7 @@ void WorldSession::HandleBattleGroundPlayerPortOpcode( WorldPacket &recv_data )
uint8 israted = itrPlayerStatus->second.GroupInfo->IsRated; uint8 israted = itrPlayerStatus->second.GroupInfo->IsRated;
uint8 status = 0; uint8 status = 0;
if(!itrPlayerStatus->second.GroupInfo->IsInvitedToBGInstanceGUID) if( !itrPlayerStatus->second.GroupInfo->IsInvitedToBGInstanceGUID )
{ {
// not invited to bg, get template // not invited to bg, get template
bg = sBattleGroundMgr.GetBattleGroundTemplate(bgTypeId); bg = sBattleGroundMgr.GetBattleGroundTemplate(bgTypeId);
@ -342,12 +342,8 @@ void WorldSession::HandleBattleGroundPlayerPortOpcode( WorldPacket &recv_data )
status = STATUS_WAIT_JOIN; status = STATUS_WAIT_JOIN;
} }
// if bg not found, then continue // if bg not found, then continue, don't invite if already in the instance
if(!bg) if( !bg || (_player->InBattleGround() && _player->GetBattleGround() && _player->GetBattleGround()->GetInstanceID() == bg->GetInstanceID()) )
continue;
// don't invite if already in the instance
if(_player->InBattleGround() && _player->GetBattleGround() && _player->GetBattleGround()->GetInstanceID() == bg->GetInstanceID())
continue; continue;
// re - invite player with proper data // re - invite player with proper data
@ -359,22 +355,20 @@ void WorldSession::HandleBattleGroundPlayerPortOpcode( WorldPacket &recv_data )
return; return;
} }
//get GroupQueueInfo from BattleGroundQueue
BattleGroundTypeId bgTypeId = BattleGroundTypeId(bgTypeId_); BattleGroundTypeId bgTypeId = BattleGroundTypeId(bgTypeId_);
BattleGroundQueueTypeId bgQueueTypeId = BattleGroundMgr::BGQueueTypeId(bgTypeId, type);
BattleGroundQueueTypeId bgQueueTypeId = BATTLEGROUND_QUEUE_NONE;
// get the bg what we were invited to
bgQueueTypeId = BattleGroundMgr::BGQueueTypeId(bgTypeId, type);
BattleGroundQueue::QueuedPlayersMap& qpMap = sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].m_QueuedPlayers; BattleGroundQueue::QueuedPlayersMap& qpMap = sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].m_QueuedPlayers;
BattleGroundQueue::QueuedPlayersMap::iterator itrPlayerStatus = qpMap.find(_player->GetGUID()); BattleGroundQueue::QueuedPlayersMap::iterator itrPlayerStatus = qpMap.find(_player->GetGUID());
if(itrPlayerStatus == qpMap.end()) if( itrPlayerStatus == qpMap.end() )
{ {
sLog.outError("Battleground: itrplayerstatus not found."); sLog.outError("Battleground: itrplayerstatus not found.");
return; return;
} }
instanceId = itrPlayerStatus->second.GroupInfo->IsInvitedToBGInstanceGUID;
// if action == 1, then instanceId is _required_ instanceId = itrPlayerStatus->second.GroupInfo->IsInvitedToBGInstanceGUID;
if(!instanceId && action == 1) // if action == 1, then instanceId is required
if( !instanceId && action == 1 )
{ {
sLog.outError("Battleground: instance not found."); sLog.outError("Battleground: instance not found.");
return; return;
@ -383,56 +377,52 @@ void WorldSession::HandleBattleGroundPlayerPortOpcode( WorldPacket &recv_data )
BattleGround *bg = sBattleGroundMgr.GetBattleGround(instanceId, bgTypeId); BattleGround *bg = sBattleGroundMgr.GetBattleGround(instanceId, bgTypeId);
// bg template might and must be used in case of leaving queue, when instance is not created yet // bg template might and must be used in case of leaving queue, when instance is not created yet
if(!bg && action == 0) if( !bg && action == 0 )
bg = sBattleGroundMgr.GetBattleGroundTemplate(bgTypeId); bg = sBattleGroundMgr.GetBattleGroundTemplate(bgTypeId);
if( !bg )
if(!bg)
{ {
sLog.outError("Battleground: bg not found for type id %u.",bgTypeId); sLog.outError("Battleground: bg_template not found for type id %u.", bgTypeId);
return; return;
} }
bgTypeId = bg->GetTypeID(); if( _player->InBattleGroundQueue() )
if(_player->InBattleGroundQueue())
{ {
uint32 queueSlot = 0; //we must use temporary variables, because GroupQueueInfo pointer can be deleted in BattleGroundQueue::RemovePlayer() function!
uint32 team = 0; uint32 team = itrPlayerStatus->second.GroupInfo->Team;
uint32 arenatype = 0; uint32 arenaType = itrPlayerStatus->second.GroupInfo->ArenaType;
uint32 israted = 0; uint32 isRated = itrPlayerStatus->second.GroupInfo->IsRated;
uint32 rating = 0; uint32 rating = itrPlayerStatus->second.GroupInfo->ArenaTeamRating;
uint32 opponentsRating = 0; uint32 opponentsRating = itrPlayerStatus->second.GroupInfo->OpponentsTeamRating;
// get the team info from the queue
BattleGroundQueue::QueuedPlayersMap& qpMap2 = sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].m_QueuedPlayers; //some checks if player isn't cheating - it is not exactly cheating, but we cannot allow it
BattleGroundQueue::QueuedPlayersMap::iterator pitr = qpMap2.find(_player->GetGUID()); if( action == 1 && arenaType == 0)
if (pitr !=qpMap2.end() && pitr->second.GroupInfo)
{ {
team = pitr->second.GroupInfo->Team; //if player is trying to enter battleground (not arena!) and he has deserter debuff, we must just remove him from queue
arenatype = pitr->second.GroupInfo->ArenaType; if( !_player->CanJoinToBattleground() )
israted = pitr->second.GroupInfo->IsRated; {
rating = pitr->second.GroupInfo->ArenaTeamRating; //send bg command result to show nice message
opponentsRating = pitr->second.GroupInfo->OpponentsTeamRating; WorldPacket data2(SMSG_GROUP_JOINED_BATTLEGROUND, 4);
} data2 << uint32(0xFFFFFFFE);
else _player->GetSession()->SendPacket(&data2);
{ action = 0;
sLog.outError("Battleground: Invalid player queue info!"); sLog.outDebug("Battleground: player %s (%u) has a deserter debuff, do not port him to battleground!", _player->GetName(), _player->GetGUIDLow());
return; }
} //if player don't match battleground max level, then do not allow him to enter! (this might happen when player leveled up during his waiting in queue
//if player is trying to enter battleground (not arena!) and he has deserter debuff, we must just remove him from queue if( _player->getLevel() > bg->GetMaxLevel() )
if( arenatype == 0 && !_player->CanJoinToBattleground() ) {
{ sLog.outError("Battleground: Player %s (%u) has level higher than maxlevel of battleground! Do not port him to battleground!", _player->GetName(), _player->GetGUIDLow());
sLog.outDebug("Battleground: player %s (%u) has a deserter debuff, do not port him to battleground!", _player->GetName(), _player->GetGUIDLow()); action = 0;
action = 0; }
} }
uint32 queueSlot = _player->GetBattleGroundQueueIndex(bgQueueTypeId);
WorldPacket data; WorldPacket data;
switch(action) switch( action )
{ {
case 1: // port to battleground case 1: // port to battleground
if(!_player->IsInvitedForBattleGroundQueueType(bgQueueTypeId)) if( !_player->IsInvitedForBattleGroundQueueType(bgQueueTypeId) )
return; // cheating? return; // cheating?
// resurrect the player // resurrect the player
if(!_player->isAlive()) if( !_player->isAlive() )
{ {
_player->ResurrectPlayer(1.0f); _player->ResurrectPlayer(1.0f);
_player->SpawnCorpseBones(); _player->SpawnCorpseBones();
@ -443,14 +433,13 @@ void WorldSession::HandleBattleGroundPlayerPortOpcode( WorldPacket &recv_data )
_player->GetMotionMaster()->MovementExpired(); _player->GetMotionMaster()->MovementExpired();
_player->m_taxi.ClearTaxiDestinations(); _player->m_taxi.ClearTaxiDestinations();
} }
_player->RemoveFromGroup();
queueSlot = _player->GetBattleGroundQueueIndex(bgQueueTypeId); sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, queueSlot, STATUS_IN_PROGRESS, 0, bg->GetStartTime(), bg->GetArenaType());
sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, queueSlot, STATUS_IN_PROGRESS, 0, bg->GetStartTime());
_player->GetSession()->SendPacket(&data); _player->GetSession()->SendPacket(&data);
// remove battleground queue status from BGmgr // remove battleground queue status from BGmgr
sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].RemovePlayer(_player->GetGUID(), false); sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].RemovePlayer(_player->GetGUID(), false);
// this is still needed here if battleground "jumping" shouldn't add deserter debuff // this is still needed here if battleground "jumping" shouldn't add deserter debuff
// also this required to prevent stuck at old battleground after SetBattleGroundId set to new // also this is required to prevent stuck at old battleground after SetBattleGroundId set to new
if( BattleGround *currentBg = _player->GetBattleGround() ) if( BattleGround *currentBg = _player->GetBattleGround() )
currentBg->RemovePlayerAtLeave(_player->GetGUID(), false, true); currentBg->RemovePlayerAtLeave(_player->GetGUID(), false, true);
@ -462,30 +451,28 @@ void WorldSession::HandleBattleGroundPlayerPortOpcode( WorldPacket &recv_data )
sBattleGroundMgr.SendToBattleGround(_player, instanceId, bgTypeId); sBattleGroundMgr.SendToBattleGround(_player, instanceId, bgTypeId);
// add only in HandleMoveWorldPortAck() // add only in HandleMoveWorldPortAck()
// bg->AddPlayer(_player,team); // bg->AddPlayer(_player,team);
sLog.outDebug("Battleground: player %s (%u) joined battle for bg %u, bgtype %u, queue type %u.",_player->GetName(),_player->GetGUIDLow(),bg->GetInstanceID(),bg->GetTypeID(),bgQueueTypeId); sLog.outDebug("Battleground: player %s (%u) joined battle for bg %u, bgtype %u, queue type %u.", _player->GetName(), _player->GetGUIDLow(), bg->GetInstanceID(), bg->GetTypeID(), bgQueueTypeId);
break; break;
case 0: // leave queue case 0: // leave queue
queueSlot = _player->GetBattleGroundQueueIndex(bgQueueTypeId); // if player leaves rated arena match before match start, it is counted as he played but he lost
/* if( isRated )
if player leaves rated arena match before match start, it is counted as he played but he lost
*/
if (israted)
{ {
ArenaTeam * at = objmgr.GetArenaTeamById(team); ArenaTeam * at = objmgr.GetArenaTeamById(team);
if (at) if( at )
{ {
sLog.outDebug("UPDATING memberLost's personal arena rating for %u by opponents rating: %u, because he has left queue!", GUID_LOPART(_player->GetGUID()), opponentsRating); sLog.outDebug("UPDATING memberLost's personal arena rating for %u by opponents rating: %u, because he has left queue!", GUID_LOPART(_player->GetGUID()), opponentsRating);
at->MemberLost(_player, opponentsRating); at->MemberLost(_player, opponentsRating);
at->SaveToDB(); at->SaveToDB();
} }
} }
_player->RemoveBattleGroundQueueId(bgQueueTypeId); // must be called this way, because if you move this call to queue->removeplayer, it causes bugs _player->RemoveBattleGroundQueueId(bgQueueTypeId); // must be called this way, because if you move this call to queue->removeplayer, it causes bugs
sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, queueSlot, STATUS_NONE, 0, 0); sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, queueSlot, STATUS_NONE, 0, 0, 0);
sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].RemovePlayer(_player->GetGUID(), true); sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].RemovePlayer(_player->GetGUID(), true);
// player left queue, we should update it, maybe now his group fits in // player left queue, we should update it - do not update Arena Queue
sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].Update(bgTypeId,_player->GetBattleGroundQueueIdFromLevel(bgTypeId),arenatype,israted,rating); if( !arenaType )
sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].Update(bgTypeId, _player->GetBattleGroundQueueIdFromLevel(bgTypeId), arenaType, isRated, rating);
SendPacket(&data); SendPacket(&data);
sLog.outDebug("Battleground: player %s (%u) left queue for bgtype %u, queue type %u.",_player->GetName(),_player->GetGUIDLow(),bg->GetTypeID(),bgQueueTypeId); sLog.outDebug("Battleground: player %s (%u) left queue for bgtype %u, queue type %u.", _player->GetName(), _player->GetGUIDLow(), bg->GetTypeID(), bgQueueTypeId);
break; break;
default: default:
sLog.outError("Battleground port: unknown action %u", action); sLog.outError("Battleground port: unknown action %u", action);
@ -524,40 +511,55 @@ void WorldSession::HandleBattlefieldStatusOpcode( WorldPacket & /*recv_data*/ )
sLog.outDebug( "WORLD: Battleground status" ); sLog.outDebug( "WORLD: Battleground status" );
WorldPacket data; WorldPacket data;
uint32 queueSlot = PLAYER_MAX_BATTLEGROUND_QUEUES; // we must update all queues here
BattleGround *bg = NULL;
if(_player->InBattleGround()) for (uint8 i = 0; i < PLAYER_MAX_BATTLEGROUND_QUEUES; i++)
{
BattleGround *bg = _player->GetBattleGround();
if(!bg)
return;
BattleGroundQueueTypeId bgQueueTypeId_tmp = BattleGroundMgr::BGQueueTypeId(bg->GetTypeID(), bg->GetArenaType());
queueSlot = _player->GetBattleGroundQueueIndex(bgQueueTypeId_tmp);
if((bg->GetStatus() <= STATUS_IN_PROGRESS))
{
sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, queueSlot, STATUS_IN_PROGRESS, 0, bg->GetStartTime());
SendPacket(&data);
}
}
// we should update all queues? .. i'm not sure if this code is correct
for (uint32 i = 0; i < PLAYER_MAX_BATTLEGROUND_QUEUES; i++)
{ {
BattleGroundQueueTypeId bgQueueTypeId = _player->GetBattleGroundQueueTypeId(i); BattleGroundQueueTypeId bgQueueTypeId = _player->GetBattleGroundQueueTypeId(i);
if(!bgQueueTypeId || i == queueSlot) //queueslot check in case we already send it in the above code if( !bgQueueTypeId )
continue; continue;
BattleGroundTypeId bgTypeId = BattleGroundMgr::BGTemplateId(bgQueueTypeId); BattleGroundTypeId bgTypeId = BattleGroundMgr::BGTemplateId(bgQueueTypeId);
uint8 arenatype = BattleGroundMgr::BGArenaType(bgQueueTypeId); uint8 arenaType = BattleGroundMgr::BGArenaType(bgQueueTypeId);
BattleGround *bg = sBattleGroundMgr.GetBattleGroundTemplate(bgTypeId); if( bgTypeId == _player->GetBattleGroundTypeId() )
if(!bg) {
continue; bg = _player->GetBattleGround();
//i cannot check any variable from player class because player class doesn't know if player is in 2v2 / 3v3 or 5v5 arena
//so i must use bg pointer to get that information
if( bg && bg->GetArenaType() == arenaType )
{
// this line is checked, i only don't know if GetStartTime is changing itself after bg end!
// send status in BattleGround
sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, i, STATUS_IN_PROGRESS, bg->GetEndTime(), bg->GetStartTime(), arenaType);
SendPacket(&data);
continue;
}
}
//we are sending update to player about queue - he can be invited there!
//get GroupQueueInfo for queue status
BattleGroundQueue::QueuedPlayersMap& qpMap = sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].m_QueuedPlayers; BattleGroundQueue::QueuedPlayersMap& qpMap = sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].m_QueuedPlayers;
BattleGroundQueue::QueuedPlayersMap::iterator itrPlayerStatus = qpMap.find(_player->GetGUID()); BattleGroundQueue::QueuedPlayersMap::iterator itrPlayerStatus = qpMap.find(_player->GetGUID());
if(itrPlayerStatus == qpMap.end() || !itrPlayerStatus->second.GroupInfo) if( itrPlayerStatus == qpMap.end() )
continue; continue;
arenatype = itrPlayerStatus->second.GroupInfo->ArenaType; if( itrPlayerStatus->second.GroupInfo->IsInvitedToBGInstanceGUID )
uint32 avgTime = sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].GetAverageQueueWaitTime(itrPlayerStatus->second.GroupInfo, _player->GetBattleGroundQueueIdFromLevel(bgTypeId)); {
sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, i, STATUS_WAIT_QUEUE, avgTime, getMSTime()-itrPlayerStatus->second.GroupInfo->JoinTime, arenatype); bg = sBattleGroundMgr.GetBattleGround(itrPlayerStatus->second.GroupInfo->IsInvitedToBGInstanceGUID, bgTypeId);
SendPacket(&data); if( !bg )
continue;
uint32 remainingTime = getMSTimeDiff(getMSTime(), itrPlayerStatus->second.GroupInfo->RemoveInviteTime);
// send status invited to BattleGround
sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, i, STATUS_WAIT_JOIN, remainingTime, 0, arenaType);
SendPacket(&data);
}
else
{
BattleGround *bg = sBattleGroundMgr.GetBattleGroundTemplate(bgTypeId);
if( !bg )
continue;
uint32 avgTime = sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].GetAverageQueueWaitTime(itrPlayerStatus->second.GroupInfo, _player->GetBattleGroundQueueIdFromLevel(bgTypeId));
// send status in BattleGround Queue
sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, i, STATUS_WAIT_QUEUE, avgTime, getMSTimeDiff(itrPlayerStatus->second.GroupInfo->JoinTime, getMSTime()), arenaType);
SendPacket(&data);
}
} }
} }

View file

@ -159,7 +159,8 @@ GroupQueueInfo * BattleGroundQueue::AddGroup(Player *leader, BattleGroundTypeId
ginfo->ArenaTeamId = arenateamid; ginfo->ArenaTeamId = arenateamid;
ginfo->IsRated = isRated; ginfo->IsRated = isRated;
ginfo->IsInvitedToBGInstanceGUID = 0; ginfo->IsInvitedToBGInstanceGUID = 0;
ginfo->JoinTime = sWorld.GetGameTime() * IN_MILISECONDS; ginfo->JoinTime = getMSTime();
ginfo->RemoveInviteTime = 0;
ginfo->Team = leader->GetTeam(); ginfo->Team = leader->GetTeam();
ginfo->ArenaTeamRating = arenaRating; ginfo->ArenaTeamRating = arenaRating;
ginfo->OpponentsTeamRating = 0; ginfo->OpponentsTeamRating = 0;
@ -194,7 +195,7 @@ void BattleGroundQueue::AddPlayer(Player *plr, GroupQueueInfo *ginfo)
void BattleGroundQueue::PlayerInvitedToBGUpdateAverageWaitTime(GroupQueueInfo* ginfo, BGQueueIdBasedOnLevel queue_id) void BattleGroundQueue::PlayerInvitedToBGUpdateAverageWaitTime(GroupQueueInfo* ginfo, BGQueueIdBasedOnLevel queue_id)
{ {
uint32 timeInQueue = (sWorld.GetGameTime() * IN_MILISECONDS) - ginfo->JoinTime; uint32 timeInQueue = getMSTimeDiff(ginfo->JoinTime, getMSTime());
uint8 team_index = BG_TEAM_ALLIANCE; //default set to BG_TEAM_ALLIANCE - or non rated arenas! uint8 team_index = BG_TEAM_ALLIANCE; //default set to BG_TEAM_ALLIANCE - or non rated arenas!
if( !ginfo->ArenaType ) if( !ginfo->ArenaType )
{ {
@ -353,7 +354,7 @@ void BattleGroundQueue::RemovePlayer(const uint64& guid, bool decreaseInvitedCou
plr2->RemoveBattleGroundQueueId(bgQueueTypeId); // must be called this way, because if you move this call to plr2->RemoveBattleGroundQueueId(bgQueueTypeId); // must be called this way, because if you move this call to
// queue->removeplayer, it causes bugs // queue->removeplayer, it causes bugs
WorldPacket data; WorldPacket data;
sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, queueSlot, STATUS_NONE, 0, 0); sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, queueSlot, STATUS_NONE, 0, 0, 0);
plr2->GetSession()->SendPacket(&data); plr2->GetSession()->SendPacket(&data);
} }
// then actually delete, this may delete the group as well! // then actually delete, this may delete the group as well!
@ -442,6 +443,7 @@ bool BattleGroundQueue::InviteGroupToBG(GroupQueueInfo * ginfo, BattleGround * b
// invite the player // invite the player
PlayerInvitedToBGUpdateAverageWaitTime(ginfo, queue_id); PlayerInvitedToBGUpdateAverageWaitTime(ginfo, queue_id);
ginfo->RemoveInviteTime = getMSTime() + INVITE_ACCEPT_WAIT_TIME;
sBattleGroundMgr.InvitePlayer(plr, bg->GetInstanceID(), bg->GetTypeID(), ginfo->Team); sBattleGroundMgr.InvitePlayer(plr, bg->GetInstanceID(), bg->GetTypeID(), ginfo->Team);
WorldPacket data; WorldPacket data;
@ -451,7 +453,7 @@ bool BattleGroundQueue::InviteGroupToBG(GroupQueueInfo * ginfo, BattleGround * b
sLog.outDebug("Battleground: invited plr %s (%u) to BG instance %u queueindex %u bgtype %u, I can't help it if they don't press the enter battle button.",plr->GetName(),plr->GetGUIDLow(),bg->GetInstanceID(),queueSlot,bg->GetTypeID()); sLog.outDebug("Battleground: invited plr %s (%u) to BG instance %u queueindex %u bgtype %u, I can't help it if they don't press the enter battle button.",plr->GetName(),plr->GetGUIDLow(),bg->GetInstanceID(),queueSlot,bg->GetTypeID());
// send status packet // send status packet
sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, queueSlot, STATUS_WAIT_JOIN, INVITE_ACCEPT_WAIT_TIME, 0); sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, queueSlot, STATUS_WAIT_JOIN, INVITE_ACCEPT_WAIT_TIME, 0, ginfo->ArenaType);
plr->GetSession()->SendPacket(&data); plr->GetSession()->SendPacket(&data);
} }
return true; return true;
@ -508,7 +510,7 @@ void BattleGroundQueue::BGEndedRemoveInvites(BattleGround *bg)
// remove player from queue, this might delete the ginfo as well! don't use that pointer after this! // remove player from queue, this might delete the ginfo as well! don't use that pointer after this!
RemovePlayer(itr2->first, true); RemovePlayer(itr2->first, true);
WorldPacket data; WorldPacket data;
sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, queueSlot, STATUS_NONE, 0, 0); sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, queueSlot, STATUS_NONE, 0, 0, 0);
plr->GetSession()->SendPacket(&data); plr->GetSession()->SendPacket(&data);
} }
} }
@ -1067,7 +1069,8 @@ bool BGQueueInviteEvent::Execute(uint64 /*e_time*/, uint32 /*p_time*/)
if (qItr != qpMap.end() && qItr->second.GroupInfo->IsInvitedToBGInstanceGUID == m_BgInstanceGUID) if (qItr != qpMap.end() && qItr->second.GroupInfo->IsInvitedToBGInstanceGUID == m_BgInstanceGUID)
{ {
WorldPacket data; WorldPacket data;
sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, queueSlot, STATUS_WAIT_JOIN, INVITATION_REMIND_TIME, 0); //here must be remaining time
sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, queueSlot, STATUS_WAIT_JOIN, INVITE_ACCEPT_WAIT_TIME - INVITATION_REMIND_TIME, 0, qItr->second.GroupInfo->ArenaType);
plr->GetSession()->SendPacket(&data); plr->GetSession()->SendPacket(&data);
} }
} }
@ -1106,7 +1109,7 @@ bool BGQueueRemoveEvent::Execute(uint64 /*e_time*/, uint32 /*p_time*/)
sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].RemovePlayer(m_PlayerGuid, true); sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].RemovePlayer(m_PlayerGuid, true);
sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].Update(bg->GetTypeID(), bg->GetQueueId()); sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].Update(bg->GetTypeID(), bg->GetQueueId());
WorldPacket data; WorldPacket data;
sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, queueSlot, STATUS_NONE, 0, 0); sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, queueSlot, STATUS_NONE, 0, 0, 0);
plr->GetSession()->SendPacket(&data); plr->GetSession()->SendPacket(&data);
} }
} }
@ -1226,7 +1229,7 @@ void BattleGroundMgr::Update(uint32 diff)
} }
} }
void BattleGroundMgr::BuildBattleGroundStatusPacket(WorldPacket *data, BattleGround *bg, uint8 QueueSlot, uint8 StatusID, uint32 Time1, uint32 Time2, uint32 arenatype) void BattleGroundMgr::BuildBattleGroundStatusPacket(WorldPacket *data, BattleGround *bg, uint8 QueueSlot, uint8 StatusID, uint32 Time1, uint32 Time2, uint8 arenatype)
{ {
// we can be in 3 queues in same time... // we can be in 3 queues in same time...
if(StatusID == 0) if(StatusID == 0)
@ -1240,11 +1243,11 @@ void BattleGroundMgr::BuildBattleGroundStatusPacket(WorldPacket *data, BattleGro
data->Initialize(SMSG_BATTLEFIELD_STATUS, (4+1+1+4+2+4+1+4+4+4)); data->Initialize(SMSG_BATTLEFIELD_STATUS, (4+1+1+4+2+4+1+4+4+4));
*data << uint32(QueueSlot); // queue id (0...2) - player can be in 3 queues in time *data << uint32(QueueSlot); // queue id (0...2) - player can be in 3 queues in time
// uint64 in client // uint64 in client
*data << uint64( uint64(arenatype ? arenatype : bg->GetArenaType()) | (uint64(0x0D) << 8) | (uint64(bg->GetTypeID()) << 16) | (uint64(0x1F90) << 48) ); *data << uint64( uint64(arenatype) | (uint64(0x0D) << 8) | (uint64(bg->GetTypeID()) << 16) | (uint64(0x1F90) << 48) );
*data << uint32(bg->GetClientInstanceID()); *data << uint32(bg->GetClientInstanceID());
// alliance/horde for BG and skirmish/rated for Arenas // alliance/horde for BG and skirmish/rated for Arenas
// following displays the minimap-icon 0 = faction icon 1 = arenaicon // following displays the minimap-icon 0 = faction icon 1 = arenaicon
*data << uint8(bg->isArena()); *data << uint8(bg->isRated());
/* *data << uint8(arenatype ? arenatype : bg->GetArenaType()); // team type (0=BG, 2=2x2, 3=3x3, 5=5x5), for arenas // NOT PROPER VALUE IF ARENA ISN'T RUNNING YET!!!! /* *data << uint8(arenatype ? arenatype : bg->GetArenaType()); // team type (0=BG, 2=2x2, 3=3x3, 5=5x5), for arenas // NOT PROPER VALUE IF ARENA ISN'T RUNNING YET!!!!
switch(bg->GetTypeID()) // value depends on bg id switch(bg->GetTypeID()) // value depends on bg id
{ {
@ -1301,7 +1304,7 @@ void BattleGroundMgr::BuildBattleGroundStatusPacket(WorldPacket *data, BattleGro
{ {
case STATUS_WAIT_QUEUE: // status_in_queue case STATUS_WAIT_QUEUE: // status_in_queue
*data << uint32(Time1); // average wait time, milliseconds *data << uint32(Time1); // average wait time, milliseconds
*data << uint32(Time2); // time in queue, updated every minute? *data << uint32(Time2); // time in queue, updated every minute!, milliseconds
break; break;
case STATUS_WAIT_JOIN: // status_invite case STATUS_WAIT_JOIN: // status_invite
*data << uint32(bg->GetMapId()); // map id *data << uint32(bg->GetMapId()); // map id
@ -1309,7 +1312,7 @@ void BattleGroundMgr::BuildBattleGroundStatusPacket(WorldPacket *data, BattleGro
break; break;
case STATUS_IN_PROGRESS: // status_in_progress case STATUS_IN_PROGRESS: // status_in_progress
*data << uint32(bg->GetMapId()); // map id *data << uint32(bg->GetMapId()); // map id
*data << uint32(Time1); // 0 at bg start, 120000 after bg end, time to bg auto leave, milliseconds *data << uint32(Time1); // time to bg auto leave, 0 at bg start, 120000 after bg end, milliseconds
*data << uint32(Time2); // time from bg start, milliseconds *data << uint32(Time2); // time from bg start, milliseconds
*data << uint8(0x1); // unk sometimes 0x0! *data << uint8(0x1); // unk sometimes 0x0!
break; break;

View file

@ -48,6 +48,7 @@ struct GroupQueueInfo // stores informatio
uint8 ArenaType; // 2v2, 3v3, 5v5 or 0 when BG uint8 ArenaType; // 2v2, 3v3, 5v5 or 0 when BG
uint32 ArenaTeamId; // team id if rated match uint32 ArenaTeamId; // team id if rated match
uint32 JoinTime; // time when group was added uint32 JoinTime; // time when group was added
uint32 RemoveInviteTime; // time when we will remove invite for players in group
uint32 IsInvitedToBGInstanceGUID; // was invited to certain BG uint32 IsInvitedToBGInstanceGUID; // was invited to certain BG
uint32 ArenaTeamRating; // if rated match, inited to the rating of the team uint32 ArenaTeamRating; // if rated match, inited to the rating of the team
uint32 OpponentsTeamRating; // for rated arena matches uint32 OpponentsTeamRating; // for rated arena matches
@ -184,7 +185,7 @@ class BattleGroundMgr
void BuildGroupJoinedBattlegroundPacket(WorldPacket *data, BattleGroundTypeId bgTypeId); void BuildGroupJoinedBattlegroundPacket(WorldPacket *data, BattleGroundTypeId bgTypeId);
void BuildUpdateWorldStatePacket(WorldPacket *data, uint32 field, uint32 value); void BuildUpdateWorldStatePacket(WorldPacket *data, uint32 field, uint32 value);
void BuildPvpLogDataPacket(WorldPacket *data, BattleGround *bg); void BuildPvpLogDataPacket(WorldPacket *data, BattleGround *bg);
void BuildBattleGroundStatusPacket(WorldPacket *data, BattleGround *bg, uint8 QueueSlot, uint8 StatusID, uint32 Time1, uint32 Time2, uint32 arenatype = 0); void BuildBattleGroundStatusPacket(WorldPacket *data, BattleGround *bg, uint8 QueueSlot, uint8 StatusID, uint32 Time1, uint32 Time2, uint8 arenatype);
void BuildPlaySoundPacket(WorldPacket *data, uint32 soundid); void BuildPlaySoundPacket(WorldPacket *data, uint32 soundid);
void SendAreaSpiritHealerQueryOpcode(Player *pl, BattleGround *bg, const uint64& guid); void SendAreaSpiritHealerQueryOpcode(Player *pl, BattleGround *bg, const uint64& guid);

View file

@ -34,6 +34,8 @@
#include "SpellAuras.h" #include "SpellAuras.h"
#include "Language.h" #include "Language.h"
#include "Util.h" #include "Util.h"
#include "GridNotifiersImpl.h"
#include "CellImpl.h"
void WorldSession::HandleMessagechatOpcode( WorldPacket & recv_data ) void WorldSession::HandleMessagechatOpcode( WorldPacket & recv_data )
{ {
@ -232,13 +234,15 @@ void WorldSession::HandleMessagechatOpcode( WorldPacket & recv_data )
if(msg.empty()) if(msg.empty())
break; break;
Group *group = GetPlayer()->GetGroup(); // if player is in battleground, he cannot say to battleground members by /p
if(!group) Group *group = GetPlayer()->GetOriginalGroup();
// so if player hasn't OriginalGroup and his player->GetGroup() is BG raid, then return
if( !group && (!(group = GetPlayer()->GetGroup()) || group->isBGGroup()) )
return; return;
WorldPacket data; WorldPacket data;
ChatHandler::FillMessageData(&data, this, CHAT_MSG_PARTY, lang, NULL, 0, msg.c_str(),NULL); ChatHandler::FillMessageData(&data, this, CHAT_MSG_PARTY, lang, NULL, 0, msg.c_str(),NULL);
group->BroadcastPacket(&data, group->GetMemberGroup(GetPlayer()->GetGUID())); group->BroadcastPacket(&data, false, group->GetMemberGroup(GetPlayer()->GetGUID()));
} }
break; break;
case CHAT_MSG_GUILD: case CHAT_MSG_GUILD:
@ -312,13 +316,15 @@ void WorldSession::HandleMessagechatOpcode( WorldPacket & recv_data )
if(msg.empty()) if(msg.empty())
break; break;
Group *group = GetPlayer()->GetGroup(); // if player is in battleground, he cannot say to battleground members by /ra
if(!group || !group->isRaidGroup()) Group *group = GetPlayer()->GetOriginalGroup();
// so if player hasn't OriginalGroup and his player->GetGroup() is BG raid or his group isn't raid, then return
if( !group && !(group = GetPlayer()->GetGroup()) || group->isBGGroup() || !group->isRaidGroup() )
return; return;
WorldPacket data; WorldPacket data;
ChatHandler::FillMessageData(&data, this, CHAT_MSG_RAID, lang, "", 0, msg.c_str(),NULL); ChatHandler::FillMessageData(&data, this, CHAT_MSG_RAID, lang, "", 0, msg.c_str(),NULL);
group->BroadcastPacket(&data); group->BroadcastPacket(&data, false);
} break; } break;
case CHAT_MSG_RAID_LEADER: case CHAT_MSG_RAID_LEADER:
{ {
@ -338,13 +344,14 @@ void WorldSession::HandleMessagechatOpcode( WorldPacket & recv_data )
if(msg.empty()) if(msg.empty())
break; break;
Group *group = GetPlayer()->GetGroup(); // if player is in battleground, he cannot say to battleground members by /ra
if(!group || !group->isRaidGroup() || !group->IsLeader(GetPlayer()->GetGUID())) Group *group = GetPlayer()->GetOriginalGroup();
if( !group && !(group = GetPlayer()->GetGroup()) || group->isBGGroup() || !group->isRaidGroup() )
return; return;
WorldPacket data; WorldPacket data;
ChatHandler::FillMessageData(&data, this, CHAT_MSG_RAID_LEADER, lang, "", 0, msg.c_str(),NULL); ChatHandler::FillMessageData(&data, this, CHAT_MSG_RAID_LEADER, lang, "", 0, msg.c_str(),NULL);
group->BroadcastPacket(&data); group->BroadcastPacket(&data, false);
} break; } break;
case CHAT_MSG_RAID_WARNING: case CHAT_MSG_RAID_WARNING:
{ {
@ -363,8 +370,9 @@ void WorldSession::HandleMessagechatOpcode( WorldPacket & recv_data )
return; return;
WorldPacket data; WorldPacket data;
//in battleground, raid warning is sent only to players in battleground - code is ok
ChatHandler::FillMessageData(&data, this, CHAT_MSG_RAID_WARNING, lang, "", 0, msg.c_str(),NULL); ChatHandler::FillMessageData(&data, this, CHAT_MSG_RAID_WARNING, lang, "", 0, msg.c_str(),NULL);
group->BroadcastPacket(&data); group->BroadcastPacket(&data, false);
} break; } break;
case CHAT_MSG_BATTLEGROUND: case CHAT_MSG_BATTLEGROUND:
@ -379,13 +387,14 @@ void WorldSession::HandleMessagechatOpcode( WorldPacket & recv_data )
if(msg.empty()) if(msg.empty())
break; break;
//battleground raid is always in Player->GetGroup(), never in GetOriginalGroup()
Group *group = GetPlayer()->GetGroup(); Group *group = GetPlayer()->GetGroup();
if(!group || !group->isRaidGroup()) if(!group || !group->isBGGroup())
return; return;
WorldPacket data; WorldPacket data;
ChatHandler::FillMessageData(&data, this, CHAT_MSG_BATTLEGROUND, lang, "", 0, msg.c_str(),NULL); ChatHandler::FillMessageData(&data, this, CHAT_MSG_BATTLEGROUND, lang, "", 0, msg.c_str(),NULL);
group->BroadcastPacket(&data); group->BroadcastPacket(&data, false);
} break; } break;
case CHAT_MSG_BATTLEGROUND_LEADER: case CHAT_MSG_BATTLEGROUND_LEADER:
@ -400,13 +409,14 @@ void WorldSession::HandleMessagechatOpcode( WorldPacket & recv_data )
if(msg.empty()) if(msg.empty())
break; break;
//battleground raid is always in Player->GetGroup(), never in GetOriginalGroup()
Group *group = GetPlayer()->GetGroup(); Group *group = GetPlayer()->GetGroup();
if(!group || !group->isRaidGroup() || !group->IsLeader(GetPlayer()->GetGUID())) if(!group || !group->isBGGroup() || !group->IsLeader(GetPlayer()->GetGUID()))
return; return;
WorldPacket data; WorldPacket data;
ChatHandler::FillMessageData(&data, this, CHAT_MSG_BATTLEGROUND_LEADER, lang, "", 0, msg.c_str(),NULL); ChatHandler::FillMessageData(&data, this, CHAT_MSG_BATTLEGROUND_LEADER, lang, "", 0, msg.c_str(),NULL);
group->BroadcastPacket(&data); group->BroadcastPacket(&data, false);
} break; } break;
case CHAT_MSG_CHANNEL: case CHAT_MSG_CHANNEL:
@ -488,6 +498,38 @@ void WorldSession::HandleEmoteOpcode( WorldPacket & recv_data )
GetPlayer()->HandleEmoteCommand(emote); GetPlayer()->HandleEmoteCommand(emote);
} }
namespace MaNGOS
{
class EmoteChatBuilder
{
public:
EmoteChatBuilder(Player const& pl, uint32 text_emote, uint32 emote_num, Unit const* target)
: i_player(pl), i_text_emote(text_emote), i_emote_num(emote_num), i_target(target) {}
void operator()(WorldPacket& data, int32 loc_idx)
{
char const* nam = i_target ? i_target->GetNameForLocaleIdx(loc_idx) : NULL;
uint32 namlen = (nam ? strlen(nam) : 0) + 1;
data.Initialize(SMSG_TEXT_EMOTE, (20+namlen));
data << i_player.GetGUID();
data << (uint32)i_text_emote;
data << i_emote_num;
data << (uint32)namlen;
if( namlen > 1 )
data.append(nam, namlen);
else
data << (uint8)0x00;
}
private:
Player const& i_player;
uint32 i_text_emote;
uint32 i_emote_num;
Unit const* i_target;
};
} // namespace MaNGOS
void WorldSession::HandleTextEmoteOpcode( WorldPacket & recv_data ) void WorldSession::HandleTextEmoteOpcode( WorldPacket & recv_data )
{ {
if(!GetPlayer()->isAlive()) if(!GetPlayer()->isAlive())
@ -509,27 +551,12 @@ void WorldSession::HandleTextEmoteOpcode( WorldPacket & recv_data )
recv_data >> emoteNum; recv_data >> emoteNum;
recv_data >> guid; recv_data >> guid;
const char *nam = 0;
uint32 namlen = 1;
Unit* unit = ObjectAccessor::GetUnit(*_player, guid);
Creature *pCreature = dynamic_cast<Creature *>(unit);
if(unit)
{
nam = unit->GetName();
namlen = (nam ? strlen(nam) : 0) + 1;
}
EmotesTextEntry const *em = sEmotesTextStore.LookupEntry(text_emote); EmotesTextEntry const *em = sEmotesTextStore.LookupEntry(text_emote);
if (!em) if (!em)
return; return;
GetPlayer()->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_DO_EMOTE, text_emote, 0, unit);
uint32 emote_anim = em->textid; uint32 emote_anim = em->textid;
WorldPacket data;
switch(emote_anim) switch(emote_anim)
{ {
case EMOTE_STATE_SLEEP: case EMOTE_STATE_SLEEP:
@ -542,21 +569,26 @@ void WorldSession::HandleTextEmoteOpcode( WorldPacket & recv_data )
break; break;
} }
data.Initialize(SMSG_TEXT_EMOTE, (20+namlen)); Unit* unit = ObjectAccessor::GetUnit(*_player, guid);
data << GetPlayer()->GetGUID();
data << (uint32)text_emote;
data << emoteNum;
data << (uint32)namlen;
if( namlen > 1 )
data.append(nam, namlen);
else
data << (uint8)0x00;
GetPlayer()->SendMessageToSetInRange(&data,sWorld.getConfig(CONFIG_LISTEN_RANGE_TEXTEMOTE),true); CellPair p = MaNGOS::ComputeCellPair(GetPlayer()->GetPositionX(), GetPlayer()->GetPositionY());
Cell cell(p);
cell.data.Part.reserved = ALL_DISTRICT;
cell.SetNoCreate();
MaNGOS::EmoteChatBuilder emote_builder(*GetPlayer(), text_emote, emoteNum, unit);
MaNGOS::LocalizedPacketDo<MaNGOS::EmoteChatBuilder > emote_do(emote_builder);
MaNGOS::PlayerDistWorker<MaNGOS::LocalizedPacketDo<MaNGOS::EmoteChatBuilder > > emote_worker(GetPlayer(),sWorld.getConfig(CONFIG_LISTEN_RANGE_TEXTEMOTE),emote_do);
TypeContainerVisitor<MaNGOS::PlayerDistWorker<MaNGOS::LocalizedPacketDo<MaNGOS::EmoteChatBuilder > >, WorldTypeMapContainer > message(emote_worker);
CellLock<GridReadGuard> cell_lock(cell, p);
cell_lock->Visit(cell_lock, message, *GetPlayer()->GetMap());
GetPlayer()->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_DO_EMOTE, text_emote, 0, unit);
//Send scripted event call //Send scripted event call
if (pCreature && Script) if (unit && unit->GetTypeId()==TYPEID_UNIT && Script)
Script->ReceiveEmote(GetPlayer(),pCreature,text_emote); Script->ReceiveEmote(GetPlayer(),(Creature*)unit,text_emote);
} }
void WorldSession::HandleChatIgnoredOpcode(WorldPacket& recv_data ) void WorldSession::HandleChatIgnoredOpcode(WorldPacket& recv_data )

View file

@ -201,7 +201,8 @@ void Group::ConvertToRaid()
_initRaidSubGroupsCounter(); _initRaidSubGroupsCounter();
if(!isBGGroup()) CharacterDatabase.PExecute("UPDATE groups SET isRaid = 1 WHERE leaderGuid='%u'", GUID_LOPART(m_leaderGuid)); if(!isBGGroup())
CharacterDatabase.PExecute("UPDATE groups SET isRaid = 1 WHERE leaderGuid='%u'", GUID_LOPART(m_leaderGuid));
SendUpdate(); SendUpdate();
// update quest related GO states (quest activity dependent from raid membership) // update quest related GO states (quest activity dependent from raid membership)
@ -212,7 +213,12 @@ void Group::ConvertToRaid()
bool Group::AddInvite(Player *player) bool Group::AddInvite(Player *player)
{ {
if(!player || player->GetGroupInvite() || player->GetGroup()) if( !player || player->GetGroupInvite() )
return false;
Group* group = player->GetGroup();
if( group && group->isBGGroup() )
group = player->GetOriginalGroup();
if( group )
return false; return false;
RemoveInvite(player); RemoveInvite(player);
@ -323,9 +329,17 @@ uint32 Group::RemoveMember(const uint64 &guid, const uint8 &method)
player->GetSession()->SendPacket( &data ); player->GetSession()->SendPacket( &data );
} }
data.Initialize(SMSG_GROUP_LIST, 24); //we already removed player from group and in player->GetGroup() is his original group!
data << uint64(0) << uint64(0) << uint64(0); if( Group* group = player->GetGroup() )
player->GetSession()->SendPacket(&data); {
group->SendUpdate();
}
else
{
data.Initialize(SMSG_GROUP_LIST, 24);
data << uint64(0) << uint64(0) << uint64(0);
player->GetSession()->SendPacket(&data);
}
_homebindIfInstance(player); _homebindIfInstance(player);
} }
@ -334,7 +348,7 @@ uint32 Group::RemoveMember(const uint64 &guid, const uint8 &method)
{ {
WorldPacket data(SMSG_GROUP_SET_LEADER, (m_memberSlots.front().name.size()+1)); WorldPacket data(SMSG_GROUP_SET_LEADER, (m_memberSlots.front().name.size()+1));
data << m_memberSlots.front().name; data << m_memberSlots.front().name;
BroadcastPacket(&data); BroadcastPacket(&data, true);
} }
SendUpdate(); SendUpdate();
@ -357,7 +371,7 @@ void Group::ChangeLeader(const uint64 &guid)
WorldPacket data(SMSG_GROUP_SET_LEADER, slot->name.size()+1); WorldPacket data(SMSG_GROUP_SET_LEADER, slot->name.size()+1);
data << slot->name; data << slot->name;
BroadcastPacket(&data); BroadcastPacket(&data, true);
SendUpdate(); SendUpdate();
} }
@ -371,13 +385,23 @@ void Group::Disband(bool hideDestroy)
if(!player) if(!player)
continue; continue;
player->SetGroup(NULL); //we cannot call _removeMember because it would invalidate member iterator
//if we are removing player from battleground raid
if( isBGGroup() )
player->RemoveFromBattleGroundRaid();
else
{
//we can remove player who is in battleground from his original group
if( player->GetOriginalGroup() == this )
player->SetOriginalGroup(NULL);
else
player->SetGroup(NULL);
}
// quest related GO state dependent from raid membership // quest related GO state dependent from raid membership
if(isRaidGroup()) if(isRaidGroup())
player->UpdateForQuestsGO(); player->UpdateForQuestsGO();
if(!player->GetSession()) if(!player->GetSession())
continue; continue;
@ -388,9 +412,17 @@ void Group::Disband(bool hideDestroy)
player->GetSession()->SendPacket(&data); player->GetSession()->SendPacket(&data);
} }
data.Initialize(SMSG_GROUP_LIST, 24); //we already removed player from group and in player->GetGroup() is his original group, send update
data << uint64(0) << uint64(0) << uint64(0); if( Group* group = player->GetGroup() )
player->GetSession()->SendPacket(&data); {
group->SendUpdate();
}
else
{
data.Initialize(SMSG_GROUP_LIST, 24);
data << uint64(0) << uint64(0) << uint64(0);
player->GetSession()->SendPacket(&data);
}
_homebindIfInstance(player); _homebindIfInstance(player);
} }
@ -838,7 +870,7 @@ void Group::SetTargetIcon(uint8 id, uint64 guid)
data << (uint8)0; data << (uint8)0;
data << id; data << id;
data << guid; data << guid;
BroadcastPacket(&data); BroadcastPacket(&data, true);
} }
void Group::GetDataForXPAtKill(Unit const* victim, uint32& count,uint32& sum_level, Player* & member_with_max_level, Player* & not_gray_member_with_max_level) void Group::GetDataForXPAtKill(Unit const* victim, uint32& count,uint32& sum_level, Player* & member_with_max_level, Player* & not_gray_member_with_max_level)
@ -891,7 +923,7 @@ void Group::SendUpdate()
for(member_citerator citr = m_memberSlots.begin(); citr != m_memberSlots.end(); ++citr) for(member_citerator citr = m_memberSlots.begin(); citr != m_memberSlots.end(); ++citr)
{ {
player = objmgr.GetPlayer(citr->guid); player = objmgr.GetPlayer(citr->guid);
if(!player || !player->GetSession()) if(!player || !player->GetSession() || player->GetGroup() != this )
continue; continue;
// guess size // guess size
WorldPacket data(SMSG_GROUP_LIST, (1+1+1+1+8+4+GetMembersCount()*20)); WorldPacket data(SMSG_GROUP_LIST, (1+1+1+1+8+4+GetMembersCount()*20));
@ -905,11 +937,14 @@ void Group::SendUpdate()
{ {
if(citr->guid == citr2->guid) if(citr->guid == citr2->guid)
continue; continue;
Player* member = objmgr.GetPlayer(citr2->guid);
uint8 onlineState = (member) ? MEMBER_STATUS_ONLINE : MEMBER_STATUS_OFFLINE;
onlineState = onlineState | ((isBGGroup()) ? MEMBER_STATUS_PVP : 0);
data << citr2->name; data << citr2->name;
data << (uint64)citr2->guid; data << (uint64)citr2->guid;
// online-state // online-state
data << (uint8)(objmgr.GetPlayer(citr2->guid) ? 1 : 0); data << (uint8)(onlineState);
data << (uint8)(citr2->group); // groupid data << (uint8)(citr2->group); // groupid
data << (uint8)(citr2->assistant?0x01:0); // 0x2 main assist, 0x4 main tank data << (uint8)(citr2->assistant?0x01:0); // 0x2 main assist, 0x4 main tank
} }
@ -943,12 +978,12 @@ void Group::UpdatePlayerOutOfRange(Player* pPlayer)
} }
} }
void Group::BroadcastPacket(WorldPacket *packet, int group, uint64 ignore) void Group::BroadcastPacket(WorldPacket *packet, bool ignorePlayersInBGRaid, int group, uint64 ignore)
{ {
for(GroupReference *itr = GetFirstMember(); itr != NULL; itr = itr->next()) for(GroupReference *itr = GetFirstMember(); itr != NULL; itr = itr->next())
{ {
Player *pl = itr->getSource(); Player *pl = itr->getSource();
if(!pl || (ignore != 0 && pl->GetGUID() == ignore)) if(!pl || (ignore != 0 && pl->GetGUID() == ignore) || (ignorePlayersInBGRaid && pl->GetGroup() != this) )
continue; continue;
if (pl->GetSession() && (group==-1 || itr->getSubGroup()==group)) if (pl->GetSession() && (group==-1 || itr->getSubGroup()==group))
@ -1027,7 +1062,15 @@ bool Group::_addMember(const uint64 &guid, const char* name, bool isAssistant, u
if(player) if(player)
{ {
player->SetGroupInvite(NULL); player->SetGroupInvite(NULL);
player->SetGroup(this, group); //if player is in group and he is being added to BG raid group, then call SetBattleGroundRaid()
if( player->GetGroup() && isBGGroup() )
player->SetBattleGroundRaid(this, group);
//if player is in bg raid and we are adding him to normal group, then call SetOriginalGroup()
else if ( player->GetGroup() )
player->SetOriginalGroup(this, group);
//if player is not in group, then call set group
else
player->SetGroup(this, group);
// if the same group invites the player back, cancel the homebind timer // if the same group invites the player back, cancel the homebind timer
InstanceGroupBind *bind = GetBoundInstance(player->GetMapId(), player->GetDifficulty()); InstanceGroupBind *bind = GetBoundInstance(player->GetMapId(), player->GetDifficulty());
if(bind && bind->save->GetInstanceId() == player->GetInstanceId()) if(bind && bind->save->GetInstanceId() == player->GetInstanceId())
@ -1054,7 +1097,17 @@ bool Group::_removeMember(const uint64 &guid)
Player *player = objmgr.GetPlayer(guid); Player *player = objmgr.GetPlayer(guid);
if (player) if (player)
{ {
player->SetGroup(NULL); //if we are removing player from battleground raid
if( isBGGroup() )
player->RemoveFromBattleGroundRaid();
else
{
//we can remove player who is in battleground from his original group
if( player->GetOriginalGroup() == this )
player->SetOriginalGroup(NULL);
else
player->SetGroup(NULL);
}
} }
_removeRolls(guid); _removeRolls(guid);
@ -1246,12 +1299,17 @@ void Group::ChangeMembersGroup(Player *player, const uint8 &group)
return; return;
if(_setMembersGroup(player->GetGUID(), group)) if(_setMembersGroup(player->GetGUID(), group))
{ {
uint8 prevSubGroup; uint8 prevSubGroup = player->GetSubGroup();
prevSubGroup = player->GetSubGroup(); if( player->GetGroup() == this )
player->GetGroupRef().setSubGroup(group);
//if player is in BG raid, it is possible that he is also in normal raid - and that normal raid is stored in m_originalGroup reference
else
{
prevSubGroup = player->GetOriginalSubGroup();
player->GetOriginalGroupRef().setSubGroup(group);
}
SubGroupCounterDecrease(prevSubGroup); SubGroupCounterDecrease(prevSubGroup);
player->GetGroupRef().setSubGroup(group);
SendUpdate(); SendUpdate();
} }
} }

View file

@ -291,7 +291,7 @@ class MANGOS_DLL_SPEC Group
void SendUpdate(); void SendUpdate();
void UpdatePlayerOutOfRange(Player* pPlayer); void UpdatePlayerOutOfRange(Player* pPlayer);
// ignore: GUID of player that will be ignored // ignore: GUID of player that will be ignored
void BroadcastPacket(WorldPacket *packet, int group=-1, uint64 ignore=0); void BroadcastPacket(WorldPacket *packet, bool ignorePlayersInBGRaid, int group=-1, uint64 ignore=0);
void BroadcastReadyCheck(WorldPacket *packet); void BroadcastReadyCheck(WorldPacket *packet);
void OfflineReadyCheck(); void OfflineReadyCheck();

View file

@ -55,12 +55,6 @@ void WorldSession::HandleGroupInviteOpcode( WorldPacket & recv_data )
std::string membername; std::string membername;
recv_data >> membername; recv_data >> membername;
if(_player->InBattleGround())
{
SendPartyResult(PARTY_OP_INVITE, membername, PARTY_RESULT_INVITE_RESTRICTED);
return;
}
// attempt add selected player // attempt add selected player
// cheating // cheating
@ -97,15 +91,20 @@ void WorldSession::HandleGroupInviteOpcode( WorldPacket & recv_data )
return; return;
} }
Group *group = GetPlayer()->GetGroup();
if( group && group->isBGGroup() )
group = GetPlayer()->GetOriginalGroup();
Group *group2 = player->GetGroup();
if( group2 && group2->isBGGroup() )
group2 = player->GetOriginalGroup();
// player already in another group or invited // player already in another group or invited
if(player->GetGroup() || player->GetGroupInvite() ) if( group2 || player->GetGroupInvite() )
{ {
SendPartyResult(PARTY_OP_INVITE, membername, PARTY_RESULT_ALREADY_IN_GROUP); SendPartyResult(PARTY_OP_INVITE, membername, PARTY_RESULT_ALREADY_IN_GROUP);
return; return;
} }
Group *group = GetPlayer()->GetGroup();
if(group) if(group)
{ {
// not have permissions for invite // not have permissions for invite
@ -114,7 +113,6 @@ void WorldSession::HandleGroupInviteOpcode( WorldPacket & recv_data )
SendPartyResult(PARTY_OP_INVITE, "", PARTY_RESULT_YOU_NOT_LEADER); SendPartyResult(PARTY_OP_INVITE, "", PARTY_RESULT_YOU_NOT_LEADER);
return; return;
} }
// not have place // not have place
if(group->IsFull()) if(group->IsFull())
{ {
@ -185,27 +183,20 @@ void WorldSession::HandleGroupAcceptOpcode( WorldPacket & /*recv_data*/ )
Player* leader = objmgr.GetPlayer(group->GetLeaderGUID()); Player* leader = objmgr.GetPlayer(group->GetLeaderGUID());
if(leader && leader->InBattleGround())
{
SendPartyResult(PARTY_OP_INVITE, "", PARTY_RESULT_INVITE_RESTRICTED);
return;
}
// forming a new group, create it // forming a new group, create it
if(!group->IsCreated()) if(!group->IsCreated())
{ {
if(leader) group->RemoveInvite(leader); if( leader )
group->RemoveInvite(leader);
group->Create(group->GetLeaderGUID(), group->GetLeaderName()); group->Create(group->GetLeaderGUID(), group->GetLeaderName());
objmgr.AddGroup(group); objmgr.AddGroup(group);
} }
// everything's fine, do it // everything's fine, do it, PLAYER'S GROUP IS SET IN ADDMEMBER!!!
if(!group->AddMember(GetPlayer()->GetGUID(), GetPlayer()->GetName())) if(!group->AddMember(GetPlayer()->GetGUID(), GetPlayer()->GetName()))
return; return;
uint8 subgroup = group->GetMemberGroup(GetPlayer()->GetGUID()); uint8 subgroup = group->GetMemberGroup(GetPlayer()->GetGUID());
GetPlayer()->SetGroup(group, subgroup);
} }
void WorldSession::HandleGroupDeclineOpcode( WorldPacket & /*recv_data*/ ) void WorldSession::HandleGroupDeclineOpcode( WorldPacket & /*recv_data*/ )
@ -424,7 +415,7 @@ void WorldSession::HandleMinimapPingOpcode(WorldPacket& recv_data)
data << GetPlayer()->GetGUID(); data << GetPlayer()->GetGUID();
data << x; data << x;
data << y; data << y;
GetPlayer()->GetGroup()->BroadcastPacket(&data, -1, GetPlayer()->GetGUID()); GetPlayer()->GetGroup()->BroadcastPacket(&data, true, -1, GetPlayer()->GetGUID());
} }
void WorldSession::HandleRandomRollOpcode(WorldPacket& recv_data) void WorldSession::HandleRandomRollOpcode(WorldPacket& recv_data)
@ -451,7 +442,7 @@ void WorldSession::HandleRandomRollOpcode(WorldPacket& recv_data)
data << roll; data << roll;
data << GetPlayer()->GetGUID(); data << GetPlayer()->GetGUID();
if(GetPlayer()->GetGroup()) if(GetPlayer()->GetGroup())
GetPlayer()->GetGroup()->BroadcastPacket(&data); GetPlayer()->GetGroup()->BroadcastPacket(&data, false);
else else
SendPacket(&data); SendPacket(&data);
} }
@ -512,6 +503,7 @@ void WorldSession::HandleGroupChangeSubGroupOpcode( WorldPacket & recv_data )
{ {
CHECK_PACKET_SIZE(recv_data,1+1); CHECK_PACKET_SIZE(recv_data,1+1);
// we will get correct pointer for group here, so we don't have to check if group is BG raid
Group *group = GetPlayer()->GetGroup(); Group *group = GetPlayer()->GetGroup();
if(!group) if(!group)
return; return;
@ -604,7 +596,7 @@ void WorldSession::HandleRaidReadyCheckOpcode( WorldPacket & recv_data )
// everything's fine, do it // everything's fine, do it
WorldPacket data(MSG_RAID_READY_CHECK, 8); WorldPacket data(MSG_RAID_READY_CHECK, 8);
data << GetPlayer()->GetGUID(); data << GetPlayer()->GetGUID();
group->BroadcastPacket(&data, -1); group->BroadcastPacket(&data, false, -1);
group->OfflineReadyCheck(); group->OfflineReadyCheck();
} }

View file

@ -285,13 +285,10 @@ class MANGOS_DLL_SPEC Item : public Object
uState = state; uState = state;
} }
bool hasQuest(uint32 quest_id) const bool hasQuest(uint32 quest_id) const { return GetProto()->StartQuest == quest_id; }
{
ItemPrototype const *itemProto = GetProto();
return itemProto && itemProto->StartQuest == quest_id;
}
bool hasInvolvedQuest(uint32 /*quest_id*/) const { return false; } bool hasInvolvedQuest(uint32 /*quest_id*/) const { return false; }
bool IsPotion() const { return GetProto()->IsPotion(); }
bool IsConjuredConsumable() const { return GetProto()->IsConjuredConsumable(); }
private: private:
uint8 m_slot; uint8 m_slot;
Bag *m_container; Bag *m_container;

View file

@ -656,6 +656,9 @@ struct ItemPrototype
} }
return 0; return 0;
} }
bool IsPotion() const { return Class==ITEM_CLASS_CONSUMABLE && SubClass==ITEM_SUBCLASS_POTION; }
bool IsConjuredConsumable() const { return Class == ITEM_CLASS_CONSUMABLE && (Flags & ITEM_FLAGS_CONJURED); }
}; };
struct ItemLocale struct ItemLocale

View file

@ -692,9 +692,9 @@ enum MangosStrings
LANG_BATTLEGROUND_PREMATURE_FINISH_WARNING = 750, // "Not enough players. This game will close in %u mins." LANG_BATTLEGROUND_PREMATURE_FINISH_WARNING = 750, // "Not enough players. This game will close in %u mins."
LANG_BATTLEGROUND_PREMATURE_FINISH_WARNING_SECS = 751, // "Not enough players. This game will close in %u seconds." LANG_BATTLEGROUND_PREMATURE_FINISH_WARNING_SECS = 751, // "Not enough players. This game will close in %u seconds."
// = 752, not used // = 752, not used
// LANG_BG_WS_START_TWO_MINUTES = 753, // LANG_BG_WS_START_TWO_MINUTES = 753, - defined above
// LANG_BG_AB_START_TWO_MINUTES = 754, // LANG_BG_AB_START_TWO_MINUTES = 754, - defined above
// LANG_BG_EY_START_TWO_MINUTES = 755, // LANG_BG_EY_START_TWO_MINUTES = 755, - defined above
// Room for batleground/arena strings 756-799 not used // Room for batleground/arena strings 756-799 not used
// in game strings // in game strings

View file

@ -65,7 +65,8 @@ bool Map::ExistMap(uint32 mapid,int x,int y)
map_fileheader header; map_fileheader header;
fread(&header, sizeof(header), 1, pf); fread(&header, sizeof(header), 1, pf);
if (header.mapMagic != MAP_MAGIC || header.versionMagic != MAP_VERSION_MAGIC) if (header.mapMagic != uint32(MAP_MAGIC) ||
header.versionMagic != uint32(MAP_VERSION_MAGIC))
{ {
sLog.outError("Map file '%s' is non-compatible version (outdated?). Please, create new using ad.exe program.",tmp); sLog.outError("Map file '%s' is non-compatible version (outdated?). Please, create new using ad.exe program.",tmp);
delete [] tmp; delete [] tmp;
@ -1081,7 +1082,8 @@ bool GridMap::loadData(char *filename)
if (!in) if (!in)
return true; return true;
fread(&header, sizeof(header),1,in); fread(&header, sizeof(header),1,in);
if (header.mapMagic == MAP_MAGIC && header.versionMagic == MAP_VERSION_MAGIC) if (header.mapMagic == uint32(MAP_MAGIC) &&
header.versionMagic == uint32(MAP_VERSION_MAGIC))
{ {
// loadup area data // loadup area data
if (header.areaMapOffset && !loadAreaData(in, header.areaMapOffset, header.areaMapSize)) if (header.areaMapOffset && !loadAreaData(in, header.areaMapOffset, header.areaMapSize))
@ -1132,11 +1134,11 @@ bool GridMap::loadAreaData(FILE *in, uint32 offset, uint32 size)
map_areaHeader header; map_areaHeader header;
fseek(in, offset, SEEK_SET); fseek(in, offset, SEEK_SET);
fread(&header, sizeof(header), 1, in); fread(&header, sizeof(header), 1, in);
if (header.fourcc != MAP_AREA_MAGIC) if (header.fourcc != uint32(MAP_AREA_MAGIC))
return false; return false;
m_gridArea = header.gridArea; m_gridArea = header.gridArea;
if (!(header.flags&MAP_AREA_NO_AREA)) if (!(header.flags & MAP_AREA_NO_AREA))
{ {
m_area_map = new uint16 [16*16]; m_area_map = new uint16 [16*16];
fread(m_area_map, sizeof(uint16), 16*16, in); fread(m_area_map, sizeof(uint16), 16*16, in);
@ -1149,13 +1151,13 @@ bool GridMap::loadHeihgtData(FILE *in, uint32 offset, uint32 size)
map_heightHeader header; map_heightHeader header;
fseek(in, offset, SEEK_SET); fseek(in, offset, SEEK_SET);
fread(&header, sizeof(header), 1, in); fread(&header, sizeof(header), 1, in);
if (header.fourcc != MAP_HEIGTH_MAGIC) if (header.fourcc != uint32(MAP_HEIGTH_MAGIC))
return false; return false;
m_gridHeight = header.gridHeight; m_gridHeight = header.gridHeight;
if (!(header.flags&MAP_HEIGHT_NO_HIGHT)) if (!(header.flags & MAP_HEIGHT_NO_HIGHT))
{ {
if ((header.flags&MAP_HEIGHT_AS_INT16)) if ((header.flags & MAP_HEIGHT_AS_INT16))
{ {
m_uint16_V9 = new uint16 [129*129]; m_uint16_V9 = new uint16 [129*129];
m_uint16_V8 = new uint16 [128*128]; m_uint16_V8 = new uint16 [128*128];
@ -1164,7 +1166,7 @@ bool GridMap::loadHeihgtData(FILE *in, uint32 offset, uint32 size)
m_gridIntHeightMultiplier = (header.gridMaxHeight - header.gridHeight) / 65535; m_gridIntHeightMultiplier = (header.gridMaxHeight - header.gridHeight) / 65535;
m_gridGetHeight = &GridMap::getHeightFromUint16; m_gridGetHeight = &GridMap::getHeightFromUint16;
} }
else if ((header.flags&MAP_HEIGHT_AS_INT8)) else if ((header.flags & MAP_HEIGHT_AS_INT8))
{ {
m_uint8_V9 = new uint8 [129*129]; m_uint8_V9 = new uint8 [129*129];
m_uint8_V8 = new uint8 [128*128]; m_uint8_V8 = new uint8 [128*128];
@ -1192,7 +1194,7 @@ bool GridMap::loadLiquidData(FILE *in, uint32 offset, uint32 size)
map_liquidHeader header; map_liquidHeader header;
fseek(in, offset, SEEK_SET); fseek(in, offset, SEEK_SET);
fread(&header, sizeof(header), 1, in); fread(&header, sizeof(header), 1, in);
if (header.fourcc != MAP_LIQUID_MAGIC) if (header.fourcc != uint32(MAP_LIQUID_MAGIC))
return false; return false;
m_liquidType = header.liquidType; m_liquidType = header.liquidType;
@ -1529,7 +1531,7 @@ inline ZLiquidStatus GridMap::getLiquidStatus(float x, float y, float z, uint8 R
} }
// For speed check as int values // For speed check as int values
int delta = (liquid_level - z) * 10; int delta = int((liquid_level - z) * 10);
// Get position delta // Get position delta
if (delta > 20) // Under water if (delta > 20) // Under water

View file

@ -43,8 +43,8 @@ MotionMaster::Initialize()
while(!empty()) while(!empty())
{ {
MovementGenerator *curr = top(); MovementGenerator *curr = top();
curr->Finalize(*i_owner);
pop(); pop();
curr->Finalize(*i_owner);
if( !isStatic( curr ) ) if( !isStatic( curr ) )
delete curr; delete curr;
} }
@ -66,8 +66,8 @@ MotionMaster::~MotionMaster()
while(!empty()) while(!empty())
{ {
MovementGenerator *curr = top(); MovementGenerator *curr = top();
curr->Finalize(*i_owner);
pop(); pop();
curr->Finalize(*i_owner);
if( !isStatic( curr ) ) if( !isStatic( curr ) )
delete curr; delete curr;
} }
@ -117,8 +117,8 @@ MotionMaster::DirectClean(bool reset)
while( !empty() && size() > 1 ) while( !empty() && size() > 1 )
{ {
MovementGenerator *curr = top(); MovementGenerator *curr = top();
curr->Finalize(*i_owner);
pop(); pop();
curr->Finalize(*i_owner);
if( !isStatic( curr ) ) if( !isStatic( curr ) )
delete curr; delete curr;
} }
@ -142,8 +142,8 @@ MotionMaster::DelayedClean()
while( !empty() && size() > 1 ) while( !empty() && size() > 1 )
{ {
MovementGenerator *curr = top(); MovementGenerator *curr = top();
curr->Finalize(*i_owner);
pop(); pop();
curr->Finalize(*i_owner);
if( !isStatic( curr ) ) if( !isStatic( curr ) )
m_expList->push_back(curr); m_expList->push_back(curr);
} }
@ -156,23 +156,26 @@ MotionMaster::DirectExpire(bool reset)
return; return;
MovementGenerator *curr = top(); MovementGenerator *curr = top();
curr->Finalize(*i_owner);
pop(); pop();
// also drop stored under top() targeted motions
while( !empty() && top()->GetMovementGeneratorType() == TARGETED_MOTION_TYPE )
{
MovementGenerator *temp = top();
pop();
temp ->Finalize(*i_owner);
delete temp;
}
// it can add another motions instead
curr->Finalize(*i_owner);
if( !isStatic(curr) ) if( !isStatic(curr) )
delete curr; delete curr;
assert( !empty() );
while( !empty() && top()->GetMovementGeneratorType() == TARGETED_MOTION_TYPE )
{
// Should check if target is still valid? If not valid it will crash.
curr = top();
curr->Finalize(*i_owner);
pop();
delete curr;
}
if( empty() ) if( empty() )
Initialize(); Initialize();
if (reset) top()->Reset(*i_owner); if (reset) top()->Reset(*i_owner);
} }
@ -183,23 +186,24 @@ MotionMaster::DelayedExpire()
return; return;
MovementGenerator *curr = top(); MovementGenerator *curr = top();
curr->Finalize(*i_owner);
pop(); pop();
if(!m_expList) if(!m_expList)
m_expList = new ExpireList(); m_expList = new ExpireList();
if( !isStatic(curr) ) // also drop stored under top() targeted motions
m_expList->push_back(curr);
while( !empty() && top()->GetMovementGeneratorType() == TARGETED_MOTION_TYPE ) while( !empty() && top()->GetMovementGeneratorType() == TARGETED_MOTION_TYPE )
{ {
// Should check if target is still valid? If not valid it will crash. MovementGenerator *temp = top();
curr = top();
curr->Finalize(*i_owner);
pop(); pop();
m_expList->push_back(curr); temp ->Finalize(*i_owner);
m_expList->push_back(temp );
} }
curr->Finalize(*i_owner);
if( !isStatic(curr) )
m_expList->push_back(curr);
} }
void MotionMaster::MoveIdle() void MotionMaster::MoveIdle()

View file

@ -294,7 +294,7 @@ bool Pet::LoadPetFromDB( Player* owner, uint32 petentry, uint32 petnumber, bool
AIM_Initialize(); AIM_Initialize();
map->Add((Creature*)this); map->Add((Creature*)this);
// Spells should be loaded after pet is added to map, because in CanCast is check on it // Spells should be loaded after pet is added to map, because in CheckCast is check on it
_LoadSpells(); _LoadSpells();
_LoadSpellCooldowns(); _LoadSpellCooldowns();

View file

@ -189,7 +189,7 @@ void WorldSession::HandlePetAction( WorldPacket & recv_data )
Spell *spell = new Spell(pet, spellInfo, false); Spell *spell = new Spell(pet, spellInfo, false);
int16 result = spell->PetCanCast(unit_target); SpellCastResult result = spell->CheckPetCast(unit_target);
//auto turn to target unless possessed //auto turn to target unless possessed
if(result == SPELL_FAILED_UNIT_NOT_INFRONT && !pet->HasAuraType(SPELL_AURA_MOD_POSSESS)) if(result == SPELL_FAILED_UNIT_NOT_INFRONT && !pet->HasAuraType(SPELL_AURA_MOD_POSSESS))
@ -200,10 +200,10 @@ void WorldSession::HandlePetAction( WorldPacket & recv_data )
if(Unit* powner = pet->GetCharmerOrOwner()) if(Unit* powner = pet->GetCharmerOrOwner())
if(powner->GetTypeId() == TYPEID_PLAYER) if(powner->GetTypeId() == TYPEID_PLAYER)
pet->SendUpdateToPlayer((Player*)powner); pet->SendUpdateToPlayer((Player*)powner);
result = -1; result = SPELL_CAST_OK;
} }
if(result == -1) if(result == SPELL_CAST_OK)
{ {
((Creature*)pet)->AddCreatureSpellCooldown(spellid); ((Creature*)pet)->AddCreatureSpellCooldown(spellid);
if (((Creature*)pet)->isPet()) if (((Creature*)pet)->isPet())
@ -611,8 +611,8 @@ void WorldSession::HandlePetCastSpellOpcode( WorldPacket& recvPacket )
spell->m_cast_count = cast_count; // probably pending spell cast spell->m_cast_count = cast_count; // probably pending spell cast
spell->m_targets = targets; spell->m_targets = targets;
int16 result = spell->PetCanCast(NULL); SpellCastResult result = spell->CheckPetCast(NULL);
if(result == -1) if(result == SPELL_CAST_OK)
{ {
pet->AddCreatureSpellCooldown(spellid); pet->AddCreatureSpellCooldown(spellid);
if(pet->isPet()) if(pet->isPet())

View file

@ -750,9 +750,9 @@ bool Player::Create( uint32 guidlow, const std::string& name, uint8 race, uint8
} }
// if this is ammo then use it // if this is ammo then use it
uint8 msg = CanUseAmmo( pItem->GetProto()->ItemId ); uint8 msg = CanUseAmmo( pItem->GetEntry() );
if( msg == EQUIP_ERR_OK ) if( msg == EQUIP_ERR_OK )
SetAmmo( pItem->GetProto()->ItemId ); SetAmmo( pItem->GetEntry() );
} }
} }
} }
@ -2891,8 +2891,8 @@ bool Player::addSpell(uint32 spell_id, bool active, bool learning, bool dependen
continue; continue;
if(_spell_idx->second->learnOnGetSkill == ABILITY_LEARNED_ON_GET_RACE_OR_CLASS_SKILL || if(_spell_idx->second->learnOnGetSkill == ABILITY_LEARNED_ON_GET_RACE_OR_CLASS_SKILL ||
// lockpicking special case, not have ABILITY_LEARNED_ON_GET_RACE_OR_CLASS_SKILL // lockpicking/runeforging special case, not have ABILITY_LEARNED_ON_GET_RACE_OR_CLASS_SKILL
pSkill->id==SKILL_LOCKPICKING && _spell_idx->second->max_value==0 ) (pSkill->id==SKILL_LOCKPICKING || pSkill->id==SKILL_RUNEFORGING) && _spell_idx->second->max_value==0 )
{ {
switch(GetSkillRangeType(pSkill,_spell_idx->second->racemask!=0)) switch(GetSkillRangeType(pSkill,_spell_idx->second->racemask!=0))
{ {
@ -2929,8 +2929,8 @@ bool Player::addSpell(uint32 spell_id, bool active, bool learning, bool dependen
if(IsInWorld()) if(IsInWorld())
{ {
GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_LEARN_SPELL); GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_LEARN_SPELL,spell_id);
GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_LEARN_SKILLLINE_SPELLS); GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_LEARN_SKILLLINE_SPELLS,spell_id);
} }
// return true (for send learn packet) only if spell active (in case ranked spells) and not replace old spell // return true (for send learn packet) only if spell active (in case ranked spells) and not replace old spell
@ -3101,8 +3101,8 @@ void Player::removeSpell(uint32 spell_id, bool disabled, bool update_action_bar_
continue; continue;
if(_spell_idx->second->learnOnGetSkill == ABILITY_LEARNED_ON_GET_RACE_OR_CLASS_SKILL || if(_spell_idx->second->learnOnGetSkill == ABILITY_LEARNED_ON_GET_RACE_OR_CLASS_SKILL ||
// lockpicking special case, not have ABILITY_LEARNED_ON_GET_RACE_OR_CLASS_SKILL // lockpicking/runeforging special case, not have ABILITY_LEARNED_ON_GET_RACE_OR_CLASS_SKILL
pSkill->id==SKILL_LOCKPICKING && _spell_idx->second->max_value==0 ) (pSkill->id==SKILL_LOCKPICKING || pSkill->id==SKILL_RUNEFORGING) && _spell_idx->second->max_value==0 )
{ {
// not reset skills for professions and racial abilities // not reset skills for professions and racial abilities
if( (pSkill->categoryId==SKILL_CATEGORY_SECONDARY || pSkill->categoryId==SKILL_CATEGORY_PROFESSION) && if( (pSkill->categoryId==SKILL_CATEGORY_SECONDARY || pSkill->categoryId==SKILL_CATEGORY_PROFESSION) &&
@ -4029,7 +4029,7 @@ void Player::CreateCorpse()
flags |= CORPSE_FLAG_HIDE_HELM; flags |= CORPSE_FLAG_HIDE_HELM;
if(HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_HIDE_CLOAK)) if(HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_HIDE_CLOAK))
flags |= CORPSE_FLAG_HIDE_CLOAK; flags |= CORPSE_FLAG_HIDE_CLOAK;
if(InBattleGround()) if(InBattleGround() && !InArena())
flags |= CORPSE_FLAG_LOOTABLE; // to be able to remove insignia flags |= CORPSE_FLAG_LOOTABLE; // to be able to remove insignia
corpse->SetUInt32Value( CORPSE_FIELD_FLAGS, flags ); corpse->SetUInt32Value( CORPSE_FIELD_FLAGS, flags );
@ -5344,12 +5344,12 @@ void Player::SendInitialActionButtons()
sLog.outDetail( "Action Buttons for '%u' Initialized", GetGUIDLow() ); sLog.outDetail( "Action Buttons for '%u' Initialized", GetGUIDLow() );
} }
void Player::addActionButton(const uint8 button, const uint16 action, const uint8 type, const uint8 misc) bool Player::addActionButton(const uint8 button, const uint16 action, const uint8 type, const uint8 misc)
{ {
if(button >= MAX_ACTION_BUTTONS) if(button >= MAX_ACTION_BUTTONS)
{ {
sLog.outError( "Action %u not added into button %u for player %s: button must be < 132", action, button, GetName() ); sLog.outError( "Action %u not added into button %u for player %s: button must be < 132", action, button, GetName() );
return; return false;
} }
// check cheating with adding non-known spells to action bar // check cheating with adding non-known spells to action bar
@ -5358,13 +5358,13 @@ void Player::addActionButton(const uint8 button, const uint16 action, const uint
if(!sSpellStore.LookupEntry(action)) if(!sSpellStore.LookupEntry(action))
{ {
sLog.outError( "Action %u not added into button %u for player %s: spell not exist", action, button, GetName() ); sLog.outError( "Action %u not added into button %u for player %s: spell not exist", action, button, GetName() );
return; return false;
} }
if(!HasSpell(action)) if(!HasSpell(action))
{ {
sLog.outError( "Action %u not added into button %u for player %s: player don't known this spell", action, button, GetName() ); sLog.outError( "Action %u not added into button %u for player %s: player don't known this spell", action, button, GetName() );
return; return false;
} }
} }
@ -5382,6 +5382,7 @@ void Player::addActionButton(const uint8 button, const uint16 action, const uint
}; };
sLog.outDetail( "Player '%u' Added Action '%u' to Button '%u'", GetGUIDLow(), action, button ); sLog.outDetail( "Player '%u' Added Action '%u' to Button '%u'", GetGUIDLow(), action, button );
return true;
} }
void Player::removeActionButton(uint8 button) void Player::removeActionButton(uint8 button)
@ -5934,8 +5935,8 @@ bool Player::ModifyOneFactionReputation(FactionEntry const* factionEntry, int32
} }
} }
} }
GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_GAIN_REPUTATION); GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_GAIN_REPUTATION,factionEntry->ID);
GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_GAIN_EXALTED_REPUTATION); GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_GAIN_EXALTED_REPUTATION,factionEntry->ID);
SendFactionState(&(itr->second)); SendFactionState(&(itr->second));
return true; return true;
@ -6001,8 +6002,8 @@ bool Player::SetOneFactionReputation(FactionEntry const* factionEntry, int32 sta
SetFactionAtWar(&itr->second,true); SetFactionAtWar(&itr->second,true);
SendFactionState(&(itr->second)); SendFactionState(&(itr->second));
GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_GAIN_REPUTATION); GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_GAIN_REPUTATION,factionEntry->ID);
GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_GAIN_EXALTED_REPUTATION); GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_GAIN_EXALTED_REPUTATION,factionEntry->ID);
return true; return true;
} }
return false; return false;
@ -7004,7 +7005,7 @@ void Player::ApplyEquipSpell(SpellEntry const* spellInfo, Item* item, bool apply
if(apply) if(apply)
{ {
// Cannot be used in this stance/form // Cannot be used in this stance/form
if(GetErrorAtShapeshiftedCast(spellInfo, m_form)!=0) if(GetErrorAtShapeshiftedCast(spellInfo, m_form) != SPELL_CAST_OK)
return; return;
if(form_change) // check aura active state from other form if(form_change) // check aura active state from other form
@ -7038,7 +7039,7 @@ void Player::ApplyEquipSpell(SpellEntry const* spellInfo, Item* item, bool apply
if(form_change) // check aura compatibility if(form_change) // check aura compatibility
{ {
// Cannot be used in this stance/form // Cannot be used in this stance/form
if(GetErrorAtShapeshiftedCast(spellInfo, m_form)==0) if(GetErrorAtShapeshiftedCast(spellInfo, m_form)==SPELL_CAST_OK)
return; // and remove only not compatible at form change return; // and remove only not compatible at form change
} }
@ -7450,6 +7451,9 @@ void Player::SendLootRelease( uint64 guid )
void Player::SendLoot(uint64 guid, LootType loot_type) void Player::SendLoot(uint64 guid, LootType loot_type)
{ {
if (uint64 lguid = GetLootGUID())
m_session->DoLootRelease(lguid);
Loot *loot = 0; Loot *loot = 0;
PermissionTypes permission = ALL_PERMISSION; PermissionTypes permission = ALL_PERMISSION;
@ -10667,6 +10671,8 @@ Item* Player::EquipItem( uint16 pos, Item *pItem, bool update )
} }
} }
// only for full equip instead adding to stack
GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_EQUIP_ITEM, pItem->GetEntry());
return pItem; return pItem;
} }
@ -10913,60 +10919,60 @@ void Player::DestroyItem( uint8 bag, uint8 slot, bool update )
void Player::DestroyItemCount( uint32 item, uint32 count, bool update, bool unequip_check) void Player::DestroyItemCount( uint32 item, uint32 count, bool update, bool unequip_check)
{ {
sLog.outDebug( "STORAGE: DestroyItemCount item = %u, count = %u", item, count); sLog.outDebug( "STORAGE: DestroyItemCount item = %u, count = %u", item, count);
Item *pItem;
ItemPrototype const *pProto;
uint32 remcount = 0; uint32 remcount = 0;
// in inventory // in inventory
for(int i = INVENTORY_SLOT_ITEM_START; i < INVENTORY_SLOT_ITEM_END; i++) for(int i = INVENTORY_SLOT_ITEM_START; i < INVENTORY_SLOT_ITEM_END; i++)
{ {
pItem = GetItemByPos( INVENTORY_SLOT_BAG_0, i ); if (Item* pItem = GetItemByPos( INVENTORY_SLOT_BAG_0, i ))
if( pItem && pItem->GetEntry() == item )
{ {
if( pItem->GetCount() + remcount <= count ) if (pItem->GetEntry() == item)
{ {
// all items in inventory can unequipped if (pItem->GetCount() + remcount <= count)
remcount += pItem->GetCount(); {
DestroyItem( INVENTORY_SLOT_BAG_0, i, update); // all items in inventory can unequipped
remcount += pItem->GetCount();
DestroyItem( INVENTORY_SLOT_BAG_0, i, update);
if(remcount >=count) if (remcount >=count)
return;
}
else
{
ItemRemovedQuestCheck( pItem->GetEntry(), count - remcount );
pItem->SetCount( pItem->GetCount() - count + remcount );
if (IsInWorld() & update)
pItem->SendUpdateToPlayer( this );
pItem->SetState(ITEM_CHANGED, this);
return; return;
} }
else
{
pProto = pItem->GetProto();
ItemRemovedQuestCheck( pItem->GetEntry(), count - remcount );
pItem->SetCount( pItem->GetCount() - count + remcount );
if( IsInWorld() & update )
pItem->SendUpdateToPlayer( this );
pItem->SetState(ITEM_CHANGED, this);
return;
} }
} }
} }
for(int i = KEYRING_SLOT_START; i < QUESTBAG_SLOT_END; i++) for(int i = KEYRING_SLOT_START; i < QUESTBAG_SLOT_END; i++)
{ {
pItem = GetItemByPos( INVENTORY_SLOT_BAG_0, i ); if (Item* pItem = GetItemByPos( INVENTORY_SLOT_BAG_0, i ))
if( pItem && pItem->GetEntry() == item )
{ {
if( pItem->GetCount() + remcount <= count ) if (pItem->GetEntry() == item)
{ {
// all keys can be unequipped if (pItem->GetCount() + remcount <= count)
remcount += pItem->GetCount(); {
DestroyItem( INVENTORY_SLOT_BAG_0, i, update); // all keys can be unequipped
remcount += pItem->GetCount();
DestroyItem( INVENTORY_SLOT_BAG_0, i, update);
if(remcount >=count) if (remcount >=count)
return;
}
else
{
ItemRemovedQuestCheck( pItem->GetEntry(), count - remcount );
pItem->SetCount( pItem->GetCount() - count + remcount );
if (IsInWorld() & update)
pItem->SendUpdateToPlayer( this );
pItem->SetState(ITEM_CHANGED, this);
return; return;
} }
else
{
pProto = pItem->GetProto();
ItemRemovedQuestCheck( pItem->GetEntry(), count - remcount );
pItem->SetCount( pItem->GetCount() - count + remcount );
if( IsInWorld() & update )
pItem->SendUpdateToPlayer( this );
pItem->SetState(ITEM_CHANGED, this);
return;
} }
} }
} }
@ -10978,27 +10984,28 @@ void Player::DestroyItemCount( uint32 item, uint32 count, bool update, bool uneq
{ {
for(uint32 j = 0; j < pBag->GetBagSize(); j++) for(uint32 j = 0; j < pBag->GetBagSize(); j++)
{ {
pItem = pBag->GetItemByPos(j); if(Item* pItem = pBag->GetItemByPos(j))
if( pItem && pItem->GetEntry() == item )
{ {
// all items in bags can be unequipped if (pItem->GetEntry() == item)
if( pItem->GetCount() + remcount <= count )
{ {
remcount += pItem->GetCount(); // all items in bags can be unequipped
DestroyItem( i, j, update ); if (pItem->GetCount() + remcount <= count)
{
remcount += pItem->GetCount();
DestroyItem( i, j, update );
if(remcount >=count) if (remcount >=count)
return;
}
else
{
ItemRemovedQuestCheck( pItem->GetEntry(), count - remcount );
pItem->SetCount( pItem->GetCount() - count + remcount );
if (IsInWorld() && update)
pItem->SendUpdateToPlayer( this );
pItem->SetState(ITEM_CHANGED, this);
return; return;
} }
else
{
pProto = pItem->GetProto();
ItemRemovedQuestCheck( pItem->GetEntry(), count - remcount );
pItem->SetCount( pItem->GetCount() - count + remcount );
if( IsInWorld() && update )
pItem->SendUpdateToPlayer( this );
pItem->SetState(ITEM_CHANGED, this);
return;
} }
} }
} }
@ -11008,29 +11015,30 @@ void Player::DestroyItemCount( uint32 item, uint32 count, bool update, bool uneq
// in equipment and bag list // in equipment and bag list
for(int i = EQUIPMENT_SLOT_START; i < INVENTORY_SLOT_BAG_END; i++) for(int i = EQUIPMENT_SLOT_START; i < INVENTORY_SLOT_BAG_END; i++)
{ {
pItem = GetItemByPos( INVENTORY_SLOT_BAG_0, i ); if (Item* pItem = GetItemByPos( INVENTORY_SLOT_BAG_0, i ))
if( pItem && pItem->GetEntry() == item )
{ {
if( pItem->GetCount() + remcount <= count ) if (pItem && pItem->GetEntry() == item)
{ {
if(!unequip_check || CanUnequipItem(INVENTORY_SLOT_BAG_0 << 8 | i,false) == EQUIP_ERR_OK ) if (pItem->GetCount() + remcount <= count)
{ {
remcount += pItem->GetCount(); if (!unequip_check || CanUnequipItem(INVENTORY_SLOT_BAG_0 << 8 | i,false) == EQUIP_ERR_OK )
DestroyItem( INVENTORY_SLOT_BAG_0, i, update); {
remcount += pItem->GetCount();
DestroyItem( INVENTORY_SLOT_BAG_0, i, update);
if(remcount >=count) if (remcount >=count)
return; return;
}
}
else
{
ItemRemovedQuestCheck( pItem->GetEntry(), count - remcount );
pItem->SetCount( pItem->GetCount() - count + remcount );
if (IsInWorld() & update)
pItem->SendUpdateToPlayer( this );
pItem->SetState(ITEM_CHANGED, this);
return;
} }
}
else
{
pProto = pItem->GetProto();
ItemRemovedQuestCheck( pItem->GetEntry(), count - remcount );
pItem->SetCount( pItem->GetCount() - count + remcount );
if( IsInWorld() & update )
pItem->SendUpdateToPlayer( this );
pItem->SetState(ITEM_CHANGED, this);
return;
} }
} }
} }
@ -11042,40 +11050,28 @@ void Player::DestroyZoneLimitedItem( bool update, uint32 new_zone )
// in inventory // in inventory
for(int i = INVENTORY_SLOT_ITEM_START; i < INVENTORY_SLOT_ITEM_END; i++) for(int i = INVENTORY_SLOT_ITEM_START; i < INVENTORY_SLOT_ITEM_END; i++)
{ if (Item* pItem = GetItemByPos( INVENTORY_SLOT_BAG_0, i ))
Item* pItem = GetItemByPos( INVENTORY_SLOT_BAG_0, i ); if (pItem->IsLimitedToAnotherMapOrZone(GetMapId(),new_zone))
if( pItem && pItem->IsLimitedToAnotherMapOrZone(GetMapId(),new_zone) ) DestroyItem( INVENTORY_SLOT_BAG_0, i, update);
DestroyItem( INVENTORY_SLOT_BAG_0, i, update);
}
for(int i = KEYRING_SLOT_START; i < QUESTBAG_SLOT_END; i++) for(int i = KEYRING_SLOT_START; i < QUESTBAG_SLOT_END; i++)
{ if (Item* pItem = GetItemByPos( INVENTORY_SLOT_BAG_0, i ))
Item* pItem = GetItemByPos( INVENTORY_SLOT_BAG_0, i ); if (pItem->IsLimitedToAnotherMapOrZone(GetMapId(),new_zone))
if( pItem && pItem->IsLimitedToAnotherMapOrZone(GetMapId(),new_zone) ) DestroyItem( INVENTORY_SLOT_BAG_0, i, update);
DestroyItem( INVENTORY_SLOT_BAG_0, i, update);
}
// in inventory bags // in inventory bags
for(int i = INVENTORY_SLOT_BAG_START; i < INVENTORY_SLOT_BAG_END; i++) for(int i = INVENTORY_SLOT_BAG_START; i < INVENTORY_SLOT_BAG_END; i++)
{ if (Bag* pBag = (Bag*)GetItemByPos( INVENTORY_SLOT_BAG_0, i ))
Bag* pBag = (Bag*)GetItemByPos( INVENTORY_SLOT_BAG_0, i );
if( pBag )
{
for(uint32 j = 0; j < pBag->GetBagSize(); j++) for(uint32 j = 0; j < pBag->GetBagSize(); j++)
{ if (Item* pItem = pBag->GetItemByPos(j))
Item* pItem = pBag->GetItemByPos(j); if (pItem->IsLimitedToAnotherMapOrZone(GetMapId(),new_zone))
if( pItem && pItem->IsLimitedToAnotherMapOrZone(GetMapId(),new_zone) ) DestroyItem( i, j, update);
DestroyItem( i, j, update);
}
}
}
// in equipment and bag list // in equipment and bag list
for(int i = EQUIPMENT_SLOT_START; i < INVENTORY_SLOT_BAG_END; i++) for(int i = EQUIPMENT_SLOT_START; i < INVENTORY_SLOT_BAG_END; i++)
{ if (Item* pItem = GetItemByPos( INVENTORY_SLOT_BAG_0, i ))
Item* pItem = GetItemByPos( INVENTORY_SLOT_BAG_0, i ); if (pItem->IsLimitedToAnotherMapOrZone(GetMapId(),new_zone))
if( pItem && pItem->IsLimitedToAnotherMapOrZone(GetMapId(),new_zone) ) DestroyItem( INVENTORY_SLOT_BAG_0, i, update);
DestroyItem( INVENTORY_SLOT_BAG_0, i, update);
}
} }
void Player::DestroyConjuredItems( bool update ) void Player::DestroyConjuredItems( bool update )
@ -11086,40 +11082,23 @@ void Player::DestroyConjuredItems( bool update )
// in inventory // in inventory
for(int i = INVENTORY_SLOT_ITEM_START; i < INVENTORY_SLOT_ITEM_END; i++) for(int i = INVENTORY_SLOT_ITEM_START; i < INVENTORY_SLOT_ITEM_END; i++)
{ if (Item* pItem = GetItemByPos( INVENTORY_SLOT_BAG_0, i ))
Item* pItem = GetItemByPos( INVENTORY_SLOT_BAG_0, i ); if (pItem->IsConjuredConsumable())
if( pItem && pItem->GetProto() && DestroyItem( INVENTORY_SLOT_BAG_0, i, update);
(pItem->GetProto()->Class == ITEM_CLASS_CONSUMABLE) &&
(pItem->GetProto()->Flags & ITEM_FLAGS_CONJURED) )
DestroyItem( INVENTORY_SLOT_BAG_0, i, update);
}
// in inventory bags // in inventory bags
for(int i = INVENTORY_SLOT_BAG_START; i < INVENTORY_SLOT_BAG_END; i++) for(int i = INVENTORY_SLOT_BAG_START; i < INVENTORY_SLOT_BAG_END; i++)
{ if (Bag* pBag = (Bag*)GetItemByPos( INVENTORY_SLOT_BAG_0, i ))
Bag* pBag = (Bag*)GetItemByPos( INVENTORY_SLOT_BAG_0, i );
if( pBag )
{
for(uint32 j = 0; j < pBag->GetBagSize(); j++) for(uint32 j = 0; j < pBag->GetBagSize(); j++)
{ if (Item* pItem = pBag->GetItemByPos(j))
Item* pItem = pBag->GetItemByPos(j); if (pItem->IsConjuredConsumable())
if( pItem && pItem->GetProto() && DestroyItem( i, j, update);
(pItem->GetProto()->Class == ITEM_CLASS_CONSUMABLE) &&
(pItem->GetProto()->Flags & ITEM_FLAGS_CONJURED) )
DestroyItem( i, j, update);
}
}
}
// in equipment and bag list // in equipment and bag list
for(int i = EQUIPMENT_SLOT_START; i < INVENTORY_SLOT_BAG_END; i++) for(int i = EQUIPMENT_SLOT_START; i < INVENTORY_SLOT_BAG_END; i++)
{ if (Item* pItem = GetItemByPos( INVENTORY_SLOT_BAG_0, i ))
Item* pItem = GetItemByPos( INVENTORY_SLOT_BAG_0, i ); if (pItem->IsConjuredConsumable())
if( pItem && pItem->GetProto() && DestroyItem( INVENTORY_SLOT_BAG_0, i, update);
(pItem->GetProto()->Class == ITEM_CLASS_CONSUMABLE) &&
(pItem->GetProto()->Flags & ITEM_FLAGS_CONJURED) )
DestroyItem( INVENTORY_SLOT_BAG_0, i, update);
}
} }
void Player::DestroyItemCount( Item* pItem, uint32 &count, bool update ) void Player::DestroyItemCount( Item* pItem, uint32 &count, bool update )
@ -12250,7 +12229,7 @@ void Player::SendNewItem(Item *item, uint32 count, bool received, bool created,
data << GetItemCount(item->GetEntry()); // count of items in inventory data << GetItemCount(item->GetEntry()); // count of items in inventory
if (broadcast && GetGroup()) if (broadcast && GetGroup())
GetGroup()->BroadcastPacket(&data); GetGroup()->BroadcastPacket(&data, true);
else else
GetSession()->SendPacket(&data); GetSession()->SendPacket(&data);
} }
@ -12817,7 +12796,7 @@ void Player::RewardQuest( Quest const *pQuest, uint32 reward, Object* questGiver
GiveXP( XP , NULL ); GiveXP( XP , NULL );
else else
{ {
int32 money = int32(pQuest->GetRewMoneyMaxLevel() * sWorld.getRate(RATE_DROP_MONEY)); uint32 money = uint32(pQuest->GetRewMoneyMaxLevel() * sWorld.getRate(RATE_DROP_MONEY));
ModifyMoney( money ); ModifyMoney( money );
GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_MONEY_FROM_QUEST_REWARD, money); GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_MONEY_FROM_QUEST_REWARD, money);
} }
@ -12826,7 +12805,9 @@ void Player::RewardQuest( Quest const *pQuest, uint32 reward, Object* questGiver
if(pQuest->GetRewOrReqMoney()) if(pQuest->GetRewOrReqMoney())
{ {
ModifyMoney( pQuest->GetRewOrReqMoney() ); ModifyMoney( pQuest->GetRewOrReqMoney() );
GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_MONEY_FROM_QUEST_REWARD, pQuest->GetRewOrReqMoney());
if(pQuest->GetRewOrReqMoney() > 0)
GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_MONEY_FROM_QUEST_REWARD, pQuest->GetRewOrReqMoney());
} }
// honor reward // honor reward
@ -14785,9 +14766,15 @@ void Player::_LoadActions(QueryResult *result)
uint8 button = fields[0].GetUInt8(); uint8 button = fields[0].GetUInt8();
addActionButton(button, fields[1].GetUInt16(), fields[2].GetUInt8(), fields[3].GetUInt8()); if(addActionButton(button, fields[1].GetUInt16(), fields[2].GetUInt8(), fields[3].GetUInt8()))
m_actionButtons[button].uState = ACTIONBUTTON_UNCHANGED;
else
{
sLog.outError( " ...at loading, and will deleted in DB also");
m_actionButtons[button].uState = ACTIONBUTTON_UNCHANGED; // Will deleted in DB at next save (it can create data until save but marked as deleted)
m_actionButtons[button].uState = ACTIONBUTTON_DELETED;
}
} }
while( result->NextRow() ); while( result->NextRow() );
@ -18261,7 +18248,8 @@ void Player::ClearComboPoints()
void Player::SetGroup(Group *group, int8 subgroup) void Player::SetGroup(Group *group, int8 subgroup)
{ {
if(group == NULL) m_group.unlink(); if(group == NULL)
m_group.unlink();
else else
{ {
// never use SetGroup without a subgroup unless you specify NULL for group // never use SetGroup without a subgroup unless you specify NULL for group
@ -19215,7 +19203,7 @@ void Player::UpdateAreaDependentAuras( uint32 newArea )
for(AuraMap::iterator iter = m_Auras.begin(); iter != m_Auras.end();) for(AuraMap::iterator iter = m_Auras.begin(); iter != m_Auras.end();)
{ {
// use m_zoneUpdateId for speed: UpdateArea called from UpdateZone or instead UpdateZone in both cases m_zoneUpdateId up-to-date // use m_zoneUpdateId for speed: UpdateArea called from UpdateZone or instead UpdateZone in both cases m_zoneUpdateId up-to-date
if(spellmgr.GetSpellAllowedInLocationError(iter->second->GetSpellProto(),GetMapId(),m_zoneUpdateId,newArea,this)!=0) if(spellmgr.GetSpellAllowedInLocationError(iter->second->GetSpellProto(),GetMapId(),m_zoneUpdateId,newArea,this) != SPELL_CAST_OK)
RemoveAura(iter); RemoveAura(iter);
else else
++iter; ++iter;
@ -19348,6 +19336,41 @@ PartyResult Player::CanUninviteFromGroup() const
return PARTY_RESULT_OK; return PARTY_RESULT_OK;
} }
void Player::SetBattleGroundRaid(Group* group, int8 subgroup)
{
//we must move references from m_group to m_originalGroup
SetOriginalGroup(GetGroup(), GetSubGroup());
m_group.unlink();
m_group.link(group, this);
m_group.setSubGroup((uint8)subgroup);
}
void Player::RemoveFromBattleGroundRaid()
{
//remove existing reference
m_group.unlink();
if( Group* group = GetOriginalGroup() )
{
m_group.link(group, this);
m_group.setSubGroup(GetOriginalSubGroup());
}
SetOriginalGroup(NULL);
}
void Player::SetOriginalGroup(Group *group, int8 subgroup)
{
if( group == NULL )
m_originalGroup.unlink();
else
{
// never use SetOriginalGroup without a subgroup unless you specify NULL for group
assert(subgroup >= 0);
m_originalGroup.link(group, this);
m_originalGroup.setSubGroup((uint8)subgroup);
}
}
void Player::UpdateUnderwaterState( Map* m, float x, float y, float z ) void Player::UpdateUnderwaterState( Map* m, float x, float y, float z )
{ {
LiquidData liquid_status; LiquidData liquid_status;
@ -19425,6 +19448,7 @@ bool Player::CanUseBattleGroundObject()
{ {
return ( //InBattleGround() && // in battleground - not need, check in other cases return ( //InBattleGround() && // in battleground - not need, check in other cases
//!IsMounted() && - not correct, player is dismounted when he clicks on flag //!IsMounted() && - not correct, player is dismounted when he clicks on flag
//i'm not sure if these two are correct, because invisible players should get visible when they click on flag
!HasStealthAura() && // not stealthed !HasStealthAura() && // not stealthed
!HasInvisibilityAura() && // not invisible !HasInvisibilityAura() && // not invisible
!HasAura(SPELL_RECENTLY_DROPPED_FLAG, 0) && // can't pickup !HasAura(SPELL_RECENTLY_DROPPED_FLAG, 0) && // can't pickup
@ -19742,8 +19766,20 @@ void Player::_LoadSkills()
else else
SetUInt32Value(PLAYER_SKILL_INDEX(i), MAKE_PAIR32(id,0)); SetUInt32Value(PLAYER_SKILL_INDEX(i), MAKE_PAIR32(id,0));
uint32 vskill = SKILL_VALUE(GetUInt32Value(PLAYER_SKILL_VALUE_INDEX(i))); // set fixed skill ranges
switch(GetSkillRangeType(pSkill,false))
{
case SKILL_RANGE_LANGUAGE: // 300..300
SetUInt32Value(PLAYER_SKILL_VALUE_INDEX(i),MAKE_SKILL_VALUE(300,300));
break;
case SKILL_RANGE_MONO: // 1..1, grey monolite bar
SetUInt32Value(PLAYER_SKILL_VALUE_INDEX(i),MAKE_SKILL_VALUE(1,1));
break;
default:
break;
}
uint32 vskill = SKILL_VALUE(GetUInt32Value(PLAYER_SKILL_VALUE_INDEX(i)));
learnSkillRewardedSpells(id, vskill); learnSkillRewardedSpells(id, vskill);
} }

View file

@ -1189,7 +1189,6 @@ class MANGOS_DLL_SPEC Player : public Unit
void AddArmorProficiency(uint32 newflag) { m_ArmorProficiency |= newflag; } void AddArmorProficiency(uint32 newflag) { m_ArmorProficiency |= newflag; }
uint32 GetWeaponProficiency() const { return m_WeaponProficiency; } uint32 GetWeaponProficiency() const { return m_WeaponProficiency; }
uint32 GetArmorProficiency() const { return m_ArmorProficiency; } uint32 GetArmorProficiency() const { return m_ArmorProficiency; }
bool IsInFeralForm() const { return m_form == FORM_CAT || m_form == FORM_BEAR || m_form == FORM_DIREBEAR; }
bool IsUseEquipedWeapon( bool mainhand ) const bool IsUseEquipedWeapon( bool mainhand ) const
{ {
// disarm applied only to mainhand weapon // disarm applied only to mainhand weapon
@ -1548,7 +1547,7 @@ class MANGOS_DLL_SPEC Player : public Unit
m_cinematic = cine; m_cinematic = cine;
} }
void addActionButton(uint8 button, uint16 action, uint8 type, uint8 misc); bool addActionButton(uint8 button, uint16 action, uint8 type, uint8 misc);
void removeActionButton(uint8 button); void removeActionButton(uint8 button);
void SendInitialActionButtons(); void SendInitialActionButtons();
@ -2153,6 +2152,13 @@ class MANGOS_DLL_SPEC Player : public Unit
void SetAuraUpdateMask(uint8 slot) { m_auraUpdateMask |= (uint64(1) << slot); } void SetAuraUpdateMask(uint8 slot) { m_auraUpdateMask |= (uint64(1) << slot); }
Player* GetNextRandomRaidMember(float radius); Player* GetNextRandomRaidMember(float radius);
PartyResult CanUninviteFromGroup() const; PartyResult CanUninviteFromGroup() const;
// BattleGround Group System
void SetBattleGroundRaid(Group *group, int8 subgroup = -1);
void RemoveFromBattleGroundRaid();
Group * GetOriginalGroup() { return m_originalGroup.getTarget(); }
GroupReference& GetOriginalGroupRef() { return m_originalGroup; }
uint8 GetOriginalSubGroup() const { return m_originalGroup.getSubGroup(); }
void SetOriginalGroup(Group *group, int8 subgroup = -1);
GridReference<Player> &GetGridRef() { return m_gridRef; } GridReference<Player> &GetGridRef() { return m_gridRef; }
MapReference &GetMapRef() { return m_mapRef; } MapReference &GetMapRef() { return m_mapRef; }
@ -2393,6 +2399,7 @@ class MANGOS_DLL_SPEC Player : public Unit
// Groups // Groups
GroupReference m_group; GroupReference m_group;
GroupReference m_originalGroup;
Group *m_groupInvite; Group *m_groupInvite;
uint32 m_groupUpdateMask; uint32 m_groupUpdateMask;
uint64 m_auraUpdateMask; uint64 m_auraUpdateMask;

View file

@ -74,6 +74,9 @@ bool LoadScriptingModule(char const* libName)
||!(testScript->GOQuestAccept =(scriptCallGOQuestAccept )MANGOS_GET_PROC_ADDR(testScript->hScriptsLib,"GOQuestAccept" )) ||!(testScript->GOQuestAccept =(scriptCallGOQuestAccept )MANGOS_GET_PROC_ADDR(testScript->hScriptsLib,"GOQuestAccept" ))
||!(testScript->ReceiveEmote =(scriptCallReceiveEmote )MANGOS_GET_PROC_ADDR(testScript->hScriptsLib,"ReceiveEmote" )) ||!(testScript->ReceiveEmote =(scriptCallReceiveEmote )MANGOS_GET_PROC_ADDR(testScript->hScriptsLib,"ReceiveEmote" ))
||!(testScript->ItemUse =(scriptCallItemUse )MANGOS_GET_PROC_ADDR(testScript->hScriptsLib,"ItemUse" )) ||!(testScript->ItemUse =(scriptCallItemUse )MANGOS_GET_PROC_ADDR(testScript->hScriptsLib,"ItemUse" ))
||!(testScript->EffectDummyGameObj =(scriptCallEffectDummyGameObj )MANGOS_GET_PROC_ADDR(testScript->hScriptsLib,"EffectDummyGameObj" ))
||!(testScript->EffectDummyCreature =(scriptCallEffectDummyCreature )MANGOS_GET_PROC_ADDR(testScript->hScriptsLib,"EffectDummyCreature" ))
||!(testScript->EffectDummyItem =(scriptCallEffectDummyItem )MANGOS_GET_PROC_ADDR(testScript->hScriptsLib,"EffectDummyItem" ))
||!(testScript->GetAI =(scriptCallGetAI )MANGOS_GET_PROC_ADDR(testScript->hScriptsLib,"GetAI" )) ||!(testScript->GetAI =(scriptCallGetAI )MANGOS_GET_PROC_ADDR(testScript->hScriptsLib,"GetAI" ))
||!(testScript->CreateInstanceData =(scriptCallCreateInstanceData )MANGOS_GET_PROC_ADDR(testScript->hScriptsLib,"CreateInstanceData" )) ||!(testScript->CreateInstanceData =(scriptCallCreateInstanceData )MANGOS_GET_PROC_ADDR(testScript->hScriptsLib,"CreateInstanceData" ))
) )

View file

@ -56,6 +56,9 @@ typedef bool(MANGOS_IMPORT * scriptCallGOQuestAccept)(Player *player, GameObject
typedef bool(MANGOS_IMPORT * scriptCallGOChooseReward)(Player *player, GameObject *, Quest const*, uint32 opt ); typedef bool(MANGOS_IMPORT * scriptCallGOChooseReward)(Player *player, GameObject *, Quest const*, uint32 opt );
typedef bool(MANGOS_IMPORT * scriptCallReceiveEmote) ( Player *player, Creature *_Creature, uint32 emote ); typedef bool(MANGOS_IMPORT * scriptCallReceiveEmote) ( Player *player, Creature *_Creature, uint32 emote );
typedef bool(MANGOS_IMPORT * scriptCallItemUse) (Player *player, Item *_Item, SpellCastTargets const& targets); typedef bool(MANGOS_IMPORT * scriptCallItemUse) (Player *player, Item *_Item, SpellCastTargets const& targets);
typedef bool(MANGOS_IMPORT * scriptCallEffectDummyGameObj) (Unit *caster, uint32 spellId, uint32 effIndex, GameObject *gameObjTarget);
typedef bool(MANGOS_IMPORT * scriptCallEffectDummyCreature) (Unit *caster, uint32 spellId, uint32 effIndex, Creature *crTarget);
typedef bool(MANGOS_IMPORT * scriptCallEffectDummyItem) (Unit *caster, uint32 spellId, uint32 effIndex, Item *itemTarget);
typedef CreatureAI* (MANGOS_IMPORT * scriptCallGetAI) ( Creature *_Creature ); typedef CreatureAI* (MANGOS_IMPORT * scriptCallGetAI) ( Creature *_Creature );
typedef InstanceData* (MANGOS_IMPORT * scriptCallCreateInstanceData) (Map *map); typedef InstanceData* (MANGOS_IMPORT * scriptCallCreateInstanceData) (Map *map);
@ -82,6 +85,9 @@ typedef struct
scriptCallGOQuestAccept GOQuestAccept; scriptCallGOQuestAccept GOQuestAccept;
scriptCallReceiveEmote ReceiveEmote; scriptCallReceiveEmote ReceiveEmote;
scriptCallItemUse ItemUse; scriptCallItemUse ItemUse;
scriptCallEffectDummyGameObj EffectDummyGameObj;
scriptCallEffectDummyCreature EffectDummyCreature;
scriptCallEffectDummyItem EffectDummyItem;
scriptCallGetAI GetAI; scriptCallGetAI GetAI;
scriptCallCreateInstanceData CreateInstanceData; scriptCallCreateInstanceData CreateInstanceData;

View file

@ -684,6 +684,194 @@ enum SpellEffects
TOTAL_SPELL_EFFECTS = 163 TOTAL_SPELL_EFFECTS = 163
}; };
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_CAST_OK = 255 //custom value, don't must be send to client
};
// Spell aura states // Spell aura states
enum AuraState enum AuraState
{ // (C) used in caster aura state (T) used in target aura state { // (C) used in caster aura state (T) used in target aura state
@ -841,10 +1029,11 @@ enum Targets
TARGET_SINGLE_FRIEND_2 = 57, TARGET_SINGLE_FRIEND_2 = 57,
TARGET_AREAEFFECT_PARTY_AND_CLASS = 61, TARGET_AREAEFFECT_PARTY_AND_CLASS = 61,
TARGET_DUELVSPLAYER_COORDINATES = 63, TARGET_DUELVSPLAYER_COORDINATES = 63,
TARGET_BEHIND_VICTIM = 65, // uses in teleport behind spells TARGET_BEHIND_VICTIM = 65, // uses in teleport behind spells, caster/target dependent from spell effect
TARGET_DYNAMIC_OBJECT_COORDINATES = 76, TARGET_DYNAMIC_OBJECT_COORDINATES = 76,
TARGET_SINGLE_ENEMY = 77, TARGET_SINGLE_ENEMY = 77,
TARGET_SELF2 = 87, TARGET_SELF2 = 87,
TARGET_DIRECTLY_FORWARD = 89,
TARGET_NONCOMBAT_PET = 90, TARGET_NONCOMBAT_PET = 90,
}; };
@ -1698,6 +1887,8 @@ inline uint8 ClassByQuestSort(int32 QuestSort)
enum SkillType enum SkillType
{ {
SKILL_NONE = 0,
SKILL_FROST = 6, SKILL_FROST = 6,
SKILL_FIRE = 8, SKILL_FIRE = 8,
SKILL_ARMS = 26, SKILL_ARMS = 26,
@ -1852,6 +2043,20 @@ enum SkillType
#define MAX_SKILL_TYPE 789 #define MAX_SKILL_TYPE 789
inline SkillType SkillByLockType(LockType locktype)
{
switch(locktype)
{
case LOCKTYPE_PICKLOCK: return SKILL_LOCKPICKING;
case LOCKTYPE_HERBALISM: return SKILL_HERBALISM;
case LOCKTYPE_MINING: return SKILL_MINING;
case LOCKTYPE_FISHING: return SKILL_FISHING;
case LOCKTYPE_INSCRIPTION: return SKILL_INSCRIPTION;
default: break;
}
return SKILL_NONE;
}
inline uint32 SkillByQuestSort(int32 QuestSort) inline uint32 SkillByQuestSort(int32 QuestSort)
{ {
switch(QuestSort) switch(QuestSort)

File diff suppressed because it is too large Load diff

View file

@ -20,6 +20,7 @@
#define __SPELL_H #define __SPELL_H
#include "GridDefines.h" #include "GridDefines.h"
#include "SharedDefines.h"
class WorldSession; class WorldSession;
class Unit; class Unit;
@ -249,6 +250,7 @@ class Spell
void EffectSummonWild(uint32 i); void EffectSummonWild(uint32 i);
void EffectSummonGuardian(uint32 i); void EffectSummonGuardian(uint32 i);
void EffectHealMechanical(uint32 i); void EffectHealMechanical(uint32 i);
void EffectJump(uint32 i);
void EffectTeleUnitsFaceCaster(uint32 i); void EffectTeleUnitsFaceCaster(uint32 i);
void EffectLearnSkill(uint32 i); void EffectLearnSkill(uint32 i);
void EffectAddHonor(uint32 i); void EffectAddHonor(uint32 i);
@ -331,14 +333,13 @@ class Spell
void cast(bool skipCheck = false); void cast(bool skipCheck = false);
void finish(bool ok = true); void finish(bool ok = true);
void TakePower(); void TakePower();
uint8 CheckRuneCost(uint32 runeCostID);
void TakeRunePower(); void TakeRunePower();
void TakeReagents(); void TakeReagents();
void TakeCastItem(); void TakeCastItem();
void TriggerSpell(); void TriggerSpell();
uint8 CanCast(bool strict);
int16 PetCanCast(Unit* target); SpellCastResult CheckCast(bool strict);
bool CanAutoCast(Unit* target); SpellCastResult CheckPetCast(Unit* target);
// handlers // handlers
void handle_immediate(); void handle_immediate();
@ -347,10 +348,11 @@ class Spell
void _handle_immediate_phase(); void _handle_immediate_phase();
void _handle_finish_phase(); void _handle_finish_phase();
uint8 CheckItems(); SpellCastResult CheckItems();
uint8 CheckRange(bool strict); SpellCastResult CheckRange(bool strict);
uint8 CheckPower(); SpellCastResult CheckPower();
uint8 CheckCasterAuras() const; SpellCastResult CheckRuneCost(uint32 runeCostID);
SpellCastResult CheckCasterAuras() const;
int32 CalculateDamage(uint8 i, Unit* target) { return m_caster->CalculateSpellDamage(m_spellInfo,i,m_currentBasePoints[i],target); } int32 CalculateDamage(uint8 i, Unit* target) { return m_caster->CalculateSpellDamage(m_spellInfo,i,m_currentBasePoints[i],target); }
int32 CalculatePowerCost(); int32 CalculatePowerCost();
@ -370,8 +372,9 @@ class Spell
Unit* SelectMagnetTarget(); Unit* SelectMagnetTarget();
bool CheckTarget( Unit* target, uint32 eff ); bool CheckTarget( Unit* target, uint32 eff );
bool CanAutoCast(Unit* target);
void SendCastResult(uint8 result); void SendCastResult(SpellCastResult result);
void SendSpellStart(); void SendSpellStart();
void SendSpellGo(); void SendSpellGo();
void SendSpellCooldown(); void SendSpellCooldown();
@ -546,6 +549,7 @@ class Spell
void DoAllEffectOnTarget(GOTargetInfo *target); void DoAllEffectOnTarget(GOTargetInfo *target);
void DoAllEffectOnTarget(ItemTargetInfo *target); void DoAllEffectOnTarget(ItemTargetInfo *target);
bool IsAliveUnitPresentInTargetList(); bool IsAliveUnitPresentInTargetList();
SpellCastResult CanOpenLock(uint32 effIndex, uint32 lockid, SkillType& skillid, int32& reqSkillValue, int32& skillValue);
// ------------------------------------------- // -------------------------------------------
//List For Triggered Spells //List For Triggered Spells

View file

@ -39,6 +39,7 @@
#include "Formulas.h" #include "Formulas.h"
#include "BattleGround.h" #include "BattleGround.h"
#include "CreatureAI.h" #include "CreatureAI.h"
#include "ScriptCalls.h"
#include "Util.h" #include "Util.h"
#include "GridNotifiers.h" #include "GridNotifiers.h"
#include "GridNotifiersImpl.h" #include "GridNotifiersImpl.h"
@ -1442,7 +1443,7 @@ void Aura::TriggerSpell()
caster->ModifyPower( POWER_MANA, mana ); caster->ModifyPower( POWER_MANA, mana );
caster->SendEnergizeSpellLog(caster, 23493, mana, POWER_MANA); caster->SendEnergizeSpellLog(caster, 23493, mana, POWER_MANA);
} }
break; return;
} }
// // Stoneclaw Totem Passive TEST // // Stoneclaw Totem Passive TEST
// case 23792: break; // case 23792: break;
@ -1510,8 +1511,11 @@ void Aura::TriggerSpell()
// case 28522: break; // case 28522: break;
// // Silithyst // // Silithyst
// case 29519: break; // case 29519: break;
// // Inoculate Nestlewood Owlkin // Inoculate Nestlewood Owlkin
case 29528: trigger_spell_id = 28713; break; case 29528:
if(target->GetTypeId()!=TYPEID_UNIT)// prevent error reports in case ignored player target
return;
break;
// // Overload // // Overload
// case 29768: break; // case 29768: break;
// // Return Fire // // Return Fire
@ -1553,7 +1557,6 @@ void Aura::TriggerSpell()
creature->SetHealth(0); // just for nice GM-mode view creature->SetHealth(0); // just for nice GM-mode view
} }
return; return;
break;
} }
// Quake // Quake
case 30576: trigger_spell_id = 30571; break; case 30576: trigger_spell_id = 30571; break;
@ -1934,13 +1937,9 @@ void Aura::TriggerSpell()
default: default:
break; break;
} }
// Reget trigger spell proto // Reget trigger spell proto
triggeredSpellInfo = sSpellStore.LookupEntry(trigger_spell_id); triggeredSpellInfo = sSpellStore.LookupEntry(trigger_spell_id);
if(triggeredSpellInfo == NULL)
{
sLog.outError("Aura::TriggerSpell: Spell %u have 0 in EffectTriggered[%d], not handled custom case?",GetId(),GetEffIndex());
return;
}
} }
else else
{ {
@ -1992,8 +1991,12 @@ void Aura::TriggerSpell()
} }
} }
} }
// All ok cast by default case // All ok cast by default case
caster->CastSpell(target, triggeredSpellInfo, true, 0, this); if(triggeredSpellInfo)
caster->CastSpell(target, triggeredSpellInfo, true, 0, this);
else if(target->GetTypeId()!=TYPEID_UNIT || !Script->EffectDummyCreature(caster, GetId(), GetEffIndex(), (Creature*)target))
sLog.outError("Aura::TriggerSpell: Spell %u have 0 in EffectTriggered[%d], not handled custom case?",GetId(),GetEffIndex());
} }
void Aura::TriggerSpellWithValue() void Aura::TriggerSpellWithValue()
@ -2261,6 +2264,45 @@ void Aura::HandleAuraDummy(bool apply, bool Real)
} }
case SPELLFAMILY_DRUID: case SPELLFAMILY_DRUID:
{ {
switch(GetId())
{
case 34246: // Idol of the Emerald Queen
{
if (m_target->GetTypeId() != TYPEID_PLAYER)
return;
if(apply)
{
SpellModifier *mod = new SpellModifier;
mod->op = SPELLMOD_DOT;
mod->value = m_modifier.m_amount/7;
mod->type = SPELLMOD_FLAT;
mod->spellId = GetId();
mod->mask = 0x001000000000LL;
mod->mask2= 0LL;
m_spellmod = mod;
}
((Player*)m_target)->AddSpellMod(m_spellmod, apply);
return;
}
case 61336: // Survival Instincts
{
if(apply)
{
if (!m_target->IsInFeralForm())
return;
int32 bp0 = int32(m_target->GetMaxHealth() * m_modifier.m_amount / 100);
m_target->CastCustomSpell(m_target, 50322, &bp0, NULL, NULL, true);
}
else
m_target-> RemoveAurasDueToSpell(50322);
return;
}
}
// Lifebloom // Lifebloom
if ( GetSpellProto()->SpellFamilyFlags & 0x1000000000LL ) if ( GetSpellProto()->SpellFamilyFlags & 0x1000000000LL )
{ {
@ -2300,25 +2342,6 @@ void Aura::HandleAuraDummy(bool apply, bool Real)
((Player*)m_target)->UpdateAttackPowerAndDamage(); ((Player*)m_target)->UpdateAttackPowerAndDamage();
return; return;
} }
// Idol of the Emerald Queen
if ( GetId() == 34246 && m_target->GetTypeId()==TYPEID_PLAYER )
{
if(apply)
{
SpellModifier *mod = new SpellModifier;
mod->op = SPELLMOD_DOT;
mod->value = m_modifier.m_amount/7;
mod->type = SPELLMOD_FLAT;
mod->spellId = GetId();
mod->mask = 0x001000000000LL;
mod->mask2= 0LL;
m_spellmod = mod;
}
((Player*)m_target)->AddSpellMod(m_spellmod, apply);
return;
}
break; break;
} }
case SPELLFAMILY_HUNTER: case SPELLFAMILY_HUNTER:
@ -3329,7 +3352,7 @@ void Aura::HandleAuraModDisarm(bool apply, bool Real)
return; return;
// main-hand attack speed already set to special value for feral form already and don't must change and reset at remove. // main-hand attack speed already set to special value for feral form already and don't must change and reset at remove.
if (((Player *)m_target)->IsInFeralForm()) if (m_target->IsInFeralForm())
return; return;
if (apply) if (apply)
@ -4693,6 +4716,7 @@ void Aura::HandleAuraModIncreaseHealth(bool apply, bool Real)
case 28726: // Nightmare Seed ( Nightmare Seed ) case 28726: // Nightmare Seed ( Nightmare Seed )
case 34511: // Valor (Bulwark of Kings, Bulwark of the Ancient Kings) case 34511: // Valor (Bulwark of Kings, Bulwark of the Ancient Kings)
case 44055: // Tremendous Fortitude (Battlemaster's Alacrity) case 44055: // Tremendous Fortitude (Battlemaster's Alacrity)
case 50322: // Survival Instincts
{ {
if(Real) if(Real)
{ {
@ -5924,6 +5948,15 @@ void Aura::PeriodicTick()
} }
case SPELL_AURA_PERIODIC_MANA_LEECH: case SPELL_AURA_PERIODIC_MANA_LEECH:
{ {
if(m_modifier.m_miscvalue < 0 || m_modifier.m_miscvalue >= MAX_POWERS)
return;
Powers power = Powers(m_modifier.m_miscvalue);
// power type might have changed between aura applying and tick (druid's shapeshift)
if(m_target->getPowerType() != power)
return;
Unit *pCaster = GetCaster(); Unit *pCaster = GetCaster();
if(!pCaster) if(!pCaster)
return; return;
@ -5942,18 +5975,20 @@ void Aura::PeriodicTick()
// ignore non positive values (can be result apply spellmods to aura damage // ignore non positive values (can be result apply spellmods to aura damage
uint32 pdamage = m_modifier.m_amount > 0 ? m_modifier.m_amount : 0; uint32 pdamage = m_modifier.m_amount > 0 ? m_modifier.m_amount : 0;
// Special case: draining x% of mana (up to a maximum of 2*x% of the caster's maximum mana)
// It's mana percent cost spells, m_modifier.m_amount is percent drain from target
if (m_spellProto->ManaCostPercentage)
{
// max value
uint32 maxmana = pCaster->GetMaxPower(power) * pdamage * 2 / 100;
pdamage = m_target->GetMaxPower(power) * pdamage / 100;
if(pdamage > maxmana)
pdamage = maxmana;
}
sLog.outDetail("PeriodicTick: %u (TypeId: %u) power leech of %u (TypeId: %u) for %u dmg inflicted by %u", sLog.outDetail("PeriodicTick: %u (TypeId: %u) power leech of %u (TypeId: %u) for %u dmg inflicted by %u",
GUID_LOPART(GetCasterGUID()), GuidHigh2TypeId(GUID_HIPART(GetCasterGUID())), m_target->GetGUIDLow(), m_target->GetTypeId(), pdamage, GetId()); GUID_LOPART(GetCasterGUID()), GuidHigh2TypeId(GUID_HIPART(GetCasterGUID())), m_target->GetGUIDLow(), m_target->GetTypeId(), pdamage, GetId());
if(m_modifier.m_miscvalue < 0 || m_modifier.m_miscvalue >= MAX_POWERS)
break;
Powers power = Powers(m_modifier.m_miscvalue);
// power type might have changed between aura applying and tick (druid's shapeshift)
if(m_target->getPowerType() != power)
break;
int32 drain_amount = m_target->GetPower(power) > pdamage ? pdamage : m_target->GetPower(power); int32 drain_amount = m_target->GetPower(power) > pdamage ? pdamage : m_target->GetPower(power);
// resilience reduce mana draining effect at spell crit damage reduction (added in 2.4) // resilience reduce mana draining effect at spell crit damage reduction (added in 2.4)

View file

@ -99,7 +99,7 @@ pEffect SpellEffects[TOTAL_SPELL_EFFECTS]=
&Spell::EffectUnused, // 39 SPELL_EFFECT_LANGUAGE &Spell::EffectUnused, // 39 SPELL_EFFECT_LANGUAGE
&Spell::EffectDualWield, // 40 SPELL_EFFECT_DUAL_WIELD &Spell::EffectDualWield, // 40 SPELL_EFFECT_DUAL_WIELD
&Spell::EffectUnused, // 41 SPELL_EFFECT_JUMP &Spell::EffectUnused, // 41 SPELL_EFFECT_JUMP
&Spell::EffectUnused, // 42 SPELL_EFFECT_JUMP2 &Spell::EffectJump, // 42 SPELL_EFFECT_JUMP2
&Spell::EffectTeleUnitsFaceCaster, // 43 SPELL_EFFECT_TELEPORT_UNITS_FACE_CASTER &Spell::EffectTeleUnitsFaceCaster, // 43 SPELL_EFFECT_TELEPORT_UNITS_FACE_CASTER
&Spell::EffectLearnSkill, // 44 SPELL_EFFECT_SKILL_STEP &Spell::EffectLearnSkill, // 44 SPELL_EFFECT_SKILL_STEP
&Spell::EffectAddHonor, // 45 SPELL_EFFECT_ADD_HONOR honor/pvp related &Spell::EffectAddHonor, // 45 SPELL_EFFECT_ADD_HONOR honor/pvp related
@ -1119,7 +1119,7 @@ void Spell::EffectDummy(uint32 i)
return; return;
unitTarget->CastSpell(unitTarget, 58419, true); unitTarget->CastSpell(unitTarget, 58419, true);
break; return;
} }
case 58420: // Portal to Stormwind case 58420: // Portal to Stormwind
{ {
@ -1127,7 +1127,7 @@ void Spell::EffectDummy(uint32 i)
return; return;
unitTarget->CastSpell(unitTarget, 58421, true); unitTarget->CastSpell(unitTarget, 58421, true);
break; return;
} }
} }
@ -1750,6 +1750,15 @@ void Spell::EffectDummy(uint32 i)
m_caster->AddPetAura(petSpell); m_caster->AddPetAura(petSpell);
return; return;
} }
// Script based implementation. Must be used only for not good for implementation in core spell effects
// So called only for not proccessed cases
if(gameObjTarget)
Script->EffectDummyGameObj(m_caster, m_spellInfo->Id, i, gameObjTarget);
else if(unitTarget && unitTarget->GetTypeId()==TYPEID_UNIT)
Script->EffectDummyCreature(m_caster, m_spellInfo->Id, i, (Creature*)unitTarget);
else if(itemTarget)
Script->EffectDummyItem(m_caster, m_spellInfo->Id, i, itemTarget);
} }
void Spell::EffectTriggerSpellWithValue(uint32 i) void Spell::EffectTriggerSpellWithValue(uint32 i)
@ -2000,6 +2009,55 @@ void Spell::EffectTriggerMissileSpell(uint32 effect_idx)
m_caster->CastSpell(m_targets.m_destX, m_targets.m_destY, m_targets.m_destZ, spellInfo, true, m_CastItem, 0, m_originalCasterGUID); m_caster->CastSpell(m_targets.m_destX, m_targets.m_destY, m_targets.m_destZ, spellInfo, true, m_CastItem, 0, m_originalCasterGUID);
} }
void Spell::EffectJump(uint32 i)
{
if(m_caster->isInFlight())
return;
// Init dest coordinates
float x,y,z,o;
if(m_targets.m_targetMask & TARGET_FLAG_DEST_LOCATION)
{
x = m_targets.m_destX;
y = m_targets.m_destY;
z = m_targets.m_destZ;
if(m_spellInfo->EffectImplicitTargetA[i] == TARGET_BEHIND_VICTIM)
{
// explicit cast data from client or server-side cast
// some spell at client send caster
Unit* pTarget = NULL;
if(m_targets.getUnitTarget() && m_targets.getUnitTarget()!=m_caster)
pTarget = m_targets.getUnitTarget();
else if(unitTarget->getVictim())
pTarget = m_caster->getVictim();
else if(m_caster->GetTypeId() == TYPEID_PLAYER)
pTarget = ObjectAccessor::GetUnit(*m_caster, ((Player*)m_caster)->GetSelection());
o = pTarget ? pTarget->GetOrientation() : m_caster->GetOrientation();
}
else
o = m_caster->GetOrientation();
}
else if(unitTarget)
{
unitTarget->GetContactPoint(m_caster,x,y,z,CONTACT_DISTANCE);
o = m_caster->GetOrientation();
}
else if(gameObjTarget)
{
gameObjTarget->GetContactPoint(m_caster,x,y,z,CONTACT_DISTANCE);
o = m_caster->GetOrientation();
}
else
{
sLog.outError( "Spell::EffectJump - unsupported target mode for spell ID %u", m_spellInfo->Id );
return;
}
m_caster->NearTeleportTo(x,y,z,o,true);
}
void Spell::EffectTeleportUnits(uint32 i) void Spell::EffectTeleportUnits(uint32 i)
{ {
if(!unitTarget || unitTarget->isInFlight()) if(!unitTarget || unitTarget->isInFlight())
@ -2018,45 +2076,38 @@ void Spell::EffectTeleportUnits(uint32 i)
} }
case TARGET_TABLE_X_Y_Z_COORDINATES: case TARGET_TABLE_X_Y_Z_COORDINATES:
{ {
// TODO: Only players can teleport?
if (unitTarget->GetTypeId() != TYPEID_PLAYER)
return;
SpellTargetPosition const* st = spellmgr.GetSpellTargetPosition(m_spellInfo->Id); SpellTargetPosition const* st = spellmgr.GetSpellTargetPosition(m_spellInfo->Id);
if(!st) if(!st)
{ {
sLog.outError( "Spell::EffectTeleportUnits - unknown Teleport coordinates for spell ID %u", m_spellInfo->Id ); sLog.outError( "Spell::EffectTeleportUnits - unknown Teleport coordinates for spell ID %u", m_spellInfo->Id );
return; return;
} }
((Player*)unitTarget)->TeleportTo(st->target_mapId,st->target_X,st->target_Y,st->target_Z,st->target_Orientation,unitTarget==m_caster ? TELE_TO_SPELL : 0);
if(st->target_mapId==unitTarget->GetMapId())
unitTarget->NearTeleportTo(st->target_X,st->target_Y,st->target_Z,st->target_Orientation,unitTarget==m_caster);
else if(unitTarget->GetTypeId()==TYPEID_PLAYER)
((Player*)unitTarget)->TeleportTo(st->target_mapId,st->target_X,st->target_Y,st->target_Z,st->target_Orientation,unitTarget==m_caster ? TELE_TO_SPELL : 0);
break; break;
} }
case TARGET_BEHIND_VICTIM: case TARGET_BEHIND_VICTIM:
{ {
// Get selected target for player (or victim for units)
Unit *pTarget = NULL; Unit *pTarget = NULL;
if(m_caster->GetTypeId() == TYPEID_PLAYER)
pTarget = ObjectAccessor::GetUnit(*m_caster, ((Player*)m_caster)->GetSelection()); // explicit cast data from client or server-side cast
else // some spell at client send caster
pTarget = m_caster->getVictim(); if(m_targets.getUnitTarget() && m_targets.getUnitTarget()!=unitTarget)
// No target present - return pTarget = m_targets.getUnitTarget();
if (!pTarget) else if(unitTarget->getVictim())
return; pTarget = unitTarget->getVictim();
else if(unitTarget->GetTypeId() == TYPEID_PLAYER)
pTarget = ObjectAccessor::GetUnit(*unitTarget, ((Player*)unitTarget)->GetSelection());
// Init dest coordinates // Init dest coordinates
uint32 mapid = m_caster->GetMapId();
float x = m_targets.m_destX; float x = m_targets.m_destX;
float y = m_targets.m_destY; float y = m_targets.m_destY;
float z = m_targets.m_destZ; float z = m_targets.m_destZ;
float orientation = pTarget->GetOrientation(); float orientation = pTarget ? pTarget->GetOrientation() : unitTarget->GetOrientation();
// Teleport unitTarget->NearTeleportTo(x,y,z,orientation,unitTarget==m_caster);
if(unitTarget->GetTypeId() == TYPEID_PLAYER)
((Player*)unitTarget)->TeleportTo(mapid, x, y, z, orientation, TELE_TO_NOT_LEAVE_COMBAT | TELE_TO_NOT_UNSUMMON_PET | (unitTarget==m_caster ? TELE_TO_SPELL : 0));
else
{
m_caster->GetMap()->CreatureRelocation((Creature*)unitTarget, x, y, z, orientation);
WorldPacket data;
unitTarget->BuildTeleportAckMsg(&data, x, y, z, orientation);
unitTarget->SendMessageToSet(&data, false);
}
return; return;
} }
default: default:
@ -2074,15 +2125,7 @@ void Spell::EffectTeleportUnits(uint32 i)
float z = m_targets.m_destZ; float z = m_targets.m_destZ;
float orientation = unitTarget->GetOrientation(); float orientation = unitTarget->GetOrientation();
// Teleport // Teleport
if(unitTarget->GetTypeId() == TYPEID_PLAYER) unitTarget->NearTeleportTo(x,y,z,orientation,unitTarget==m_caster);
((Player*)unitTarget)->TeleportTo(mapid, x, y, z, orientation, TELE_TO_NOT_LEAVE_COMBAT | TELE_TO_NOT_UNSUMMON_PET | (unitTarget==m_caster ? TELE_TO_SPELL : 0));
else
{
m_caster->GetMap()->CreatureRelocation((Creature*)unitTarget, x, y, z, orientation);
WorldPacket data;
unitTarget->BuildTeleportAckMsg(&data, x, y, z, orientation);
unitTarget->SendMessageToSet(&data, false);
}
return; return;
} }
} }
@ -2903,7 +2946,7 @@ void Spell::SendLoot(uint64 guid, LootType loottype)
player->SendLoot(guid, loottype); player->SendLoot(guid, loottype);
} }
void Spell::EffectOpenLock(uint32 /*i*/) void Spell::EffectOpenLock(uint32 effIndex)
{ {
if(!m_caster || m_caster->GetTypeId() != TYPEID_PLAYER) if(!m_caster || m_caster->GetTypeId() != TYPEID_PLAYER)
{ {
@ -2913,7 +2956,6 @@ void Spell::EffectOpenLock(uint32 /*i*/)
Player* player = (Player*)m_caster; Player* player = (Player*)m_caster;
LootType loottype = LOOT_CORPSE;
uint32 lockId = 0; uint32 lockId = 0;
uint64 guid = 0; uint64 guid = 0;
@ -2925,7 +2967,7 @@ void Spell::EffectOpenLock(uint32 /*i*/)
if( goInfo->type == GAMEOBJECT_TYPE_BUTTON && goInfo->button.noDamageImmune || if( goInfo->type == GAMEOBJECT_TYPE_BUTTON && goInfo->button.noDamageImmune ||
goInfo->type == GAMEOBJECT_TYPE_GOOBER && goInfo->goober.losOK ) goInfo->type == GAMEOBJECT_TYPE_GOOBER && goInfo->goober.losOK )
{ {
//CanUseBattleGroundObject() already called in CanCast() //CanUseBattleGroundObject() already called in CheckCast()
// in battleground check // in battleground check
if(BattleGround *bg = player->GetBattleGround()) if(BattleGround *bg = player->GetBattleGround())
{ {
@ -2937,7 +2979,7 @@ void Spell::EffectOpenLock(uint32 /*i*/)
} }
else if (goInfo->type == GAMEOBJECT_TYPE_FLAGSTAND) else if (goInfo->type == GAMEOBJECT_TYPE_FLAGSTAND)
{ {
//CanUseBattleGroundObject() already called in CanCast() //CanUseBattleGroundObject() already called in CheckCast()
// in battleground check // in battleground check
if(BattleGround *bg = player->GetBattleGround()) if(BattleGround *bg = player->GetBattleGround())
{ {
@ -2960,91 +3002,39 @@ void Spell::EffectOpenLock(uint32 /*i*/)
return; return;
} }
if(!lockId) // possible case for GO and maybe for items. SkillType skillId = SKILL_NONE;
int32 reqSkillValue = 0;
int32 skillValue;
SpellCastResult res = CanOpenLock(effIndex,lockId,skillId,reqSkillValue,skillValue);
if(res != SPELL_CAST_OK)
{ {
SendLoot(guid, loottype); SendCastResult(res);
return; return;
} }
// Get LockInfo SendLoot(guid, LOOT_SKINNING);
LockEntry const *lockInfo = sLockStore.LookupEntry(lockId);
if (!lockInfo) // not allow use skill grow at item base open
if(!m_CastItem && skillId != SKILL_NONE)
{ {
sLog.outError( "Spell::EffectOpenLock: %s [guid = %u] has an unknown lockId: %u!",
(gameObjTarget ? "gameobject" : "item"), GUID_LOPART(guid), lockId);
SendCastResult(SPELL_FAILED_BAD_TARGETS);
return;
}
// check key
for(int i = 0; i < 8; ++i)
{
// Type==1 This means lockInfo->Index[i] is an item
if(lockInfo->Type[i]==LOCK_KEY_ITEM && lockInfo->Index[i] && m_CastItem && m_CastItem->GetEntry()==lockInfo->Index[i])
{
SendLoot(guid, loottype);
return;
}
}
uint32 SkillId = 0;
// Check and skill-up skill
if( m_spellInfo->Effect[1] == SPELL_EFFECT_SKILL )
SkillId = m_spellInfo->EffectMiscValue[1];
// pickpocketing spells
else if( m_spellInfo->EffectMiscValue[0] == LOCKTYPE_PICKLOCK )
SkillId = SKILL_LOCKPICKING;
// skill bonus provided by casting spell (mostly item spells)
uint32 spellSkillBonus = uint32(m_currentBasePoints[0]+1);
uint32 reqSkillValue = lockInfo->Skill[0];
if(lockInfo->Skill[1]) // required pick lock skill applying
{
if(SkillId != SKILL_LOCKPICKING) // wrong skill (cheating?)
{
SendCastResult(SPELL_FAILED_FIZZLE);
return;
}
reqSkillValue = lockInfo->Skill[1];
}
else if(SkillId == SKILL_LOCKPICKING) // apply picklock skill to wrong target
{
SendCastResult(SPELL_FAILED_BAD_TARGETS);
return;
}
if ( SkillId )
{
loottype = LOOT_SKINNING;
if ( player->GetSkillValue(SkillId) + spellSkillBonus < reqSkillValue )
{
SendCastResult(SPELL_FAILED_LOW_CASTLEVEL);
return;
}
// update skill if really known // update skill if really known
if(uint32 SkillValue = player->GetPureSkillValue(SkillId)) if(uint32 pureSkillValue = player->GetPureSkillValue(skillId))
{ {
if(gameObjTarget) if(gameObjTarget)
{ {
// Allow one skill-up until respawned // Allow one skill-up until respawned
if ( !gameObjTarget->IsInSkillupList( player->GetGUIDLow() ) && if ( !gameObjTarget->IsInSkillupList( player->GetGUIDLow() ) &&
player->UpdateGatherSkill(SkillId, SkillValue, reqSkillValue) ) player->UpdateGatherSkill(skillId, pureSkillValue, reqSkillValue) )
gameObjTarget->AddToSkillupList( player->GetGUIDLow() ); gameObjTarget->AddToSkillupList( player->GetGUIDLow() );
} }
else if(itemTarget) else if(itemTarget)
{ {
// Do one skill-up // Do one skill-up
player->UpdateGatherSkill(SkillId, SkillValue, reqSkillValue); player->UpdateGatherSkill(skillId, pureSkillValue, reqSkillValue);
} }
} }
} }
SendLoot(guid, loottype);
} }
void Spell::EffectSummonChangeItem(uint32 i) void Spell::EffectSummonChangeItem(uint32 i)
@ -3743,16 +3733,12 @@ void Spell::EffectTeleUnitsFaceCaster(uint32 i)
if(unitTarget->isInFlight()) if(unitTarget->isInFlight())
return; return;
uint32 mapid = m_caster->GetMapId();
float dis = GetSpellRadius(sSpellRadiusStore.LookupEntry(m_spellInfo->EffectRadiusIndex[i])); float dis = GetSpellRadius(sSpellRadiusStore.LookupEntry(m_spellInfo->EffectRadiusIndex[i]));
float fx,fy,fz; float fx,fy,fz;
m_caster->GetClosePoint(fx,fy,fz,unitTarget->GetObjectSize(),dis); m_caster->GetClosePoint(fx,fy,fz,unitTarget->GetObjectSize(),dis);
if(unitTarget->GetTypeId() == TYPEID_PLAYER) unitTarget->NearTeleportTo(fx,fy,fz,-m_caster->GetOrientation(),unitTarget==m_caster);
((Player*)unitTarget)->TeleportTo(mapid, fx, fy, fz, -m_caster->GetOrientation(), TELE_TO_NOT_LEAVE_COMBAT | TELE_TO_NOT_UNSUMMON_PET | (unitTarget==m_caster ? TELE_TO_SPELL : 0));
else
m_caster->GetMap()->CreatureRelocation((Creature*)m_caster, fx, fy, fz, -m_caster->GetOrientation());
} }
void Spell::EffectLearnSkill(uint32 i) void Spell::EffectLearnSkill(uint32 i)
@ -3773,17 +3759,26 @@ void Spell::EffectAddHonor(uint32 /*i*/)
if(unitTarget->GetTypeId() != TYPEID_PLAYER) if(unitTarget->GetTypeId() != TYPEID_PLAYER)
return; return;
uint32 honor_reward = MaNGOS::Honor::hk_honor_at_level(unitTarget->getLevel(), damage); // not scale value for item based reward (/10 value expected)
sLog.outDebug("SpellEffect::AddHonor called for spell_id %u, that rewards %u honor points to player: %u", m_spellInfo->Id, honor_reward, ((Player*)unitTarget)->GetGUIDLow()); if(m_CastItem)
{
((Player*)unitTarget)->RewardHonor(NULL, 1, damage/10);
sLog.outError("SpellEffect::AddHonor (spell_id %u) rewards %d honor points (item %u) for player: %u", m_spellInfo->Id, damage/10, m_CastItem->GetEntry(),((Player*)unitTarget)->GetGUIDLow());
return;
}
// do not allow to add too many honor for player (50 * 21) = 1040 at level 70, or (50 * 31) = 1550 at level 80 // do not allow to add too many honor for player (50 * 21) = 1040 at level 70, or (50 * 31) = 1550 at level 80
if( damage <= 50 ) if( damage <= 50)
{
uint32 honor_reward = MaNGOS::Honor::hk_honor_at_level(unitTarget->getLevel(), damage);
((Player*)unitTarget)->RewardHonor(NULL, 1, honor_reward); ((Player*)unitTarget)->RewardHonor(NULL, 1, honor_reward);
sLog.outDebug("SpellEffect::AddHonor (spell_id %u) rewards %u honor points (scale) to player: %u", m_spellInfo->Id, honor_reward, ((Player*)unitTarget)->GetGUIDLow());
}
else else
{ {
//maybe we have correct honor_gain in damage already //maybe we have correct honor_gain in damage already
((Player*)unitTarget)->RewardHonor(NULL, 1, damage); ((Player*)unitTarget)->RewardHonor(NULL, 1, damage);
sLog.outError("SpellEffect::AddHonor called for spell_id %u, that rewards %d * honor for one honorable kill and it is too much (%u of honor) for player: %u", m_spellInfo->Id, damage, honor_reward, ((Player*)unitTarget)->GetGUIDLow()); sLog.outError("SpellEffect::AddHonor (spell_id %u) rewards %u honor points (non scale) for player: %u", m_spellInfo->Id, damage, ((Player*)unitTarget)->GetGUIDLow());
} }
} }
@ -5757,7 +5752,6 @@ void Spell::EffectMomentMove(uint32 i)
if( m_spellInfo->rangeIndex== 1) //self range if( m_spellInfo->rangeIndex== 1) //self range
{ {
uint32 mapid = m_caster->GetMapId();
float dis = GetSpellRadius(sSpellRadiusStore.LookupEntry(m_spellInfo->EffectRadiusIndex[i])); float dis = GetSpellRadius(sSpellRadiusStore.LookupEntry(m_spellInfo->EffectRadiusIndex[i]));
// before caster // before caster
@ -5767,7 +5761,7 @@ void Spell::EffectMomentMove(uint32 i)
unitTarget->GetPosition(ox,oy,oz); unitTarget->GetPosition(ox,oy,oz);
float fx2,fy2,fz2; // getObjectHitPos overwrite last args in any result case float fx2,fy2,fz2; // getObjectHitPos overwrite last args in any result case
if(VMAP::VMapFactory::createOrGetVMapManager()->getObjectHitPos(mapid, ox,oy,oz+0.5, fx,fy,oz+0.5,fx2,fy2,fz2, -0.5)) if(VMAP::VMapFactory::createOrGetVMapManager()->getObjectHitPos(unitTarget->GetMapId(), ox,oy,oz+0.5, fx,fy,oz+0.5,fx2,fy2,fz2, -0.5))
{ {
fx = fx2; fx = fx2;
fy = fy2; fy = fy2;
@ -5775,10 +5769,7 @@ void Spell::EffectMomentMove(uint32 i)
unitTarget->UpdateGroundPositionZ(fx,fy,fz); unitTarget->UpdateGroundPositionZ(fx,fy,fz);
} }
if(unitTarget->GetTypeId() == TYPEID_PLAYER) unitTarget->NearTeleportTo(fx, fy, fz, unitTarget->GetOrientation(),unitTarget==m_caster);
((Player*)unitTarget)->TeleportTo(mapid, fx, fy, fz, unitTarget->GetOrientation(), TELE_TO_NOT_LEAVE_COMBAT | TELE_TO_NOT_UNSUMMON_PET | (unitTarget==m_caster ? TELE_TO_SPELL : 0));
else
m_caster->GetMap()->CreatureRelocation((Creature*)unitTarget, fx, fy, fz, unitTarget->GetOrientation());
} }
} }

View file

@ -317,6 +317,7 @@ bool IsPositiveEffect(uint32 spellId, uint32 effIndex)
{ {
case 13139: // net-o-matic special effect case 13139: // net-o-matic special effect
case 23445: // evil twin case 23445: // evil twin
case 35679: // Protectorate Demolitionist
case 38637: // Nether Exhaustion (red) case 38637: // Nether Exhaustion (red)
case 38638: // Nether Exhaustion (green) case 38638: // Nether Exhaustion (green)
case 38639: // Nether Exhaustion (blue) case 38639: // Nether Exhaustion (blue)
@ -535,13 +536,13 @@ bool IsAuraAddedBySpell(uint32 auraType, uint32 spellId)
return false; return false;
} }
uint8 GetErrorAtShapeshiftedCast (SpellEntry const *spellInfo, uint32 form) SpellCastResult GetErrorAtShapeshiftedCast (SpellEntry const *spellInfo, uint32 form)
{ {
// talents that learn spells can have stance requirements that need ignore // talents that learn spells can have stance requirements that need ignore
// (this requirement only for client-side stance show in talent description) // (this requirement only for client-side stance show in talent description)
if( GetTalentSpellCost(spellInfo->Id) > 0 && if( GetTalentSpellCost(spellInfo->Id) > 0 &&
(spellInfo->Effect[0]==SPELL_EFFECT_LEARN_SPELL || spellInfo->Effect[1]==SPELL_EFFECT_LEARN_SPELL || spellInfo->Effect[2]==SPELL_EFFECT_LEARN_SPELL) ) (spellInfo->Effect[0]==SPELL_EFFECT_LEARN_SPELL || spellInfo->Effect[1]==SPELL_EFFECT_LEARN_SPELL || spellInfo->Effect[2]==SPELL_EFFECT_LEARN_SPELL) )
return 0; return SPELL_CAST_OK;
uint32 stanceMask = (form ? 1 << (form - 1) : 0); uint32 stanceMask = (form ? 1 << (form - 1) : 0);
@ -549,7 +550,7 @@ uint8 GetErrorAtShapeshiftedCast (SpellEntry const *spellInfo, uint32 form)
return SPELL_FAILED_NOT_SHAPESHIFT; return SPELL_FAILED_NOT_SHAPESHIFT;
if (stanceMask & spellInfo->Stances) // can explicitly be casted in this stance if (stanceMask & spellInfo->Stances) // can explicitly be casted in this stance
return 0; return SPELL_CAST_OK;
bool actAsShifted = false; bool actAsShifted = false;
if (form > 0) if (form > 0)
@ -558,7 +559,7 @@ uint8 GetErrorAtShapeshiftedCast (SpellEntry const *spellInfo, uint32 form)
if (!shapeInfo) if (!shapeInfo)
{ {
sLog.outError("GetErrorAtShapeshiftedCast: unknown shapeshift %u", form); sLog.outError("GetErrorAtShapeshiftedCast: unknown shapeshift %u", form);
return 0; return SPELL_CAST_OK;
} }
actAsShifted = !(shapeInfo->flags1 & 1); // shapeshift acts as normal form for spells actAsShifted = !(shapeInfo->flags1 & 1); // shapeshift acts as normal form for spells
} }
@ -577,7 +578,7 @@ uint8 GetErrorAtShapeshiftedCast (SpellEntry const *spellInfo, uint32 form)
return SPELL_FAILED_ONLY_SHAPESHIFT; return SPELL_FAILED_ONLY_SHAPESHIFT;
} }
return 0; return SPELL_CAST_OK;
} }
void SpellMgr::LoadSpellTargetPositions() void SpellMgr::LoadSpellTargetPositions()
@ -1336,6 +1337,10 @@ bool SpellMgr::IsNoStackSpellDueToSpell(uint32 spellId_1, uint32 spellId_2) cons
// Cat Energy (Feral T4 (2)) and Omen of Clarity // Cat Energy (Feral T4 (2)) and Omen of Clarity
if( spellInfo_1->Id == 16864 && spellInfo_2->Id == 37311 || spellInfo_2->Id == 16864 && spellInfo_1->Id == 37311 ) if( spellInfo_1->Id == 16864 && spellInfo_2->Id == 37311 || spellInfo_2->Id == 16864 && spellInfo_1->Id == 37311 )
return false; return false;
// Survival Instincts and Survival Instincts
if( spellInfo_1->Id == 61336 && spellInfo_2->Id == 50322 || spellInfo_2->Id == 61336 && spellInfo_1->Id == 50322 )
return false;
} }
// Leader of the Pack and Scroll of Stamina (multi-family check) // Leader of the Pack and Scroll of Stamina (multi-family check)
@ -2559,7 +2564,7 @@ void SpellMgr::LoadSpellAreas()
sLog.outString( ">> Loaded %u spell area requirements", count ); sLog.outString( ">> Loaded %u spell area requirements", count );
} }
uint8 SpellMgr::GetSpellAllowedInLocationError(SpellEntry const *spellInfo, uint32 map_id, uint32 zone_id, uint32 area_id, Player const* player) SpellCastResult SpellMgr::GetSpellAllowedInLocationError(SpellEntry const *spellInfo, uint32 map_id, uint32 zone_id, uint32 area_id, Player const* player)
{ {
// normal case // normal case
if( spellInfo->AreaGroupId > 0) if( spellInfo->AreaGroupId > 0)
@ -2585,7 +2590,7 @@ uint8 SpellMgr::GetSpellAllowedInLocationError(SpellEntry const *spellInfo, uint
for(SpellAreaMap::const_iterator itr = saBounds.first; itr != saBounds.second; ++itr) for(SpellAreaMap::const_iterator itr = saBounds.first; itr != saBounds.second; ++itr)
{ {
if(itr->second.IsFitToRequirements(player,zone_id,area_id)) if(itr->second.IsFitToRequirements(player,zone_id,area_id))
return 0; return SPELL_CAST_OK;
} }
return SPELL_FAILED_INCORRECT_AREA; return SPELL_FAILED_INCORRECT_AREA;
} }
@ -2595,9 +2600,9 @@ uint8 SpellMgr::GetSpellAllowedInLocationError(SpellEntry const *spellInfo, uint
{ {
case 23333: // Warsong Flag case 23333: // Warsong Flag
case 23335: // Silverwing Flag case 23335: // Silverwing Flag
return map_id == 489 && player && player->InBattleGround() ? 0 : SPELL_FAILED_REQUIRES_AREA; return map_id == 489 && player && player->InBattleGround() ? SPELL_CAST_OK : SPELL_FAILED_REQUIRES_AREA;
case 34976: // Netherstorm Flag case 34976: // Netherstorm Flag
return map_id == 566 && player && player->InBattleGround() ? 0 : SPELL_FAILED_REQUIRES_AREA; return map_id == 566 && player && player->InBattleGround() ? SPELL_CAST_OK : SPELL_FAILED_REQUIRES_AREA;
case 2584: // Waiting to Resurrect case 2584: // Waiting to Resurrect
case 22011: // Spirit Heal Channel case 22011: // Spirit Heal Channel
case 22012: // Spirit Heal case 22012: // Spirit Heal
@ -2610,7 +2615,7 @@ uint8 SpellMgr::GetSpellAllowedInLocationError(SpellEntry const *spellInfo, uint
if(!mapEntry) if(!mapEntry)
return SPELL_FAILED_INCORRECT_AREA; return SPELL_FAILED_INCORRECT_AREA;
return mapEntry->IsBattleGround() && player && player->InBattleGround() ? 0 : SPELL_FAILED_REQUIRES_AREA; return mapEntry->IsBattleGround() && player && player->InBattleGround() ? SPELL_CAST_OK : SPELL_FAILED_REQUIRES_AREA;
} }
case 44521: // Preparation case 44521: // Preparation
{ {
@ -2625,7 +2630,7 @@ uint8 SpellMgr::GetSpellAllowedInLocationError(SpellEntry const *spellInfo, uint
return SPELL_FAILED_REQUIRES_AREA; return SPELL_FAILED_REQUIRES_AREA;
BattleGround* bg = player->GetBattleGround(); BattleGround* bg = player->GetBattleGround();
return bg && bg->GetStatus()==STATUS_WAIT_JOIN ? 0 : SPELL_FAILED_REQUIRES_AREA; return bg && bg->GetStatus()==STATUS_WAIT_JOIN ? SPELL_CAST_OK : SPELL_FAILED_REQUIRES_AREA;
} }
case 32724: // Gold Team (Alliance) case 32724: // Gold Team (Alliance)
case 32725: // Green Team (Alliance) case 32725: // Green Team (Alliance)
@ -2636,7 +2641,7 @@ uint8 SpellMgr::GetSpellAllowedInLocationError(SpellEntry const *spellInfo, uint
if(!mapEntry) if(!mapEntry)
return SPELL_FAILED_INCORRECT_AREA; return SPELL_FAILED_INCORRECT_AREA;
return mapEntry->IsBattleArena() && player && player->InBattleGround() ? 0 : SPELL_FAILED_REQUIRES_AREA; return mapEntry->IsBattleArena() && player && player->InBattleGround() ? SPELL_CAST_OK : SPELL_FAILED_REQUIRES_AREA;
} }
case 32727: // Arena Preparation case 32727: // Arena Preparation
{ {
@ -2651,11 +2656,11 @@ uint8 SpellMgr::GetSpellAllowedInLocationError(SpellEntry const *spellInfo, uint
return SPELL_FAILED_REQUIRES_AREA; return SPELL_FAILED_REQUIRES_AREA;
BattleGround* bg = player->GetBattleGround(); BattleGround* bg = player->GetBattleGround();
return bg && bg->GetStatus()==STATUS_WAIT_JOIN ? 0 : SPELL_FAILED_REQUIRES_AREA; return bg && bg->GetStatus()==STATUS_WAIT_JOIN ? SPELL_CAST_OK : SPELL_FAILED_REQUIRES_AREA;
} }
} }
return 0; return SPELL_CAST_OK;
} }
void SpellMgr::LoadSkillLineAbilityMap() void SpellMgr::LoadSkillLineAbilityMap()

View file

@ -37,192 +37,6 @@ class Spell;
extern SQLStorage sSpellThreatStore; extern SQLStorage sSpellThreatStore;
enum SpellFailedReason
{
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
};
// only used in code // only used in code
enum SpellCategories enum SpellCategories
{ {
@ -428,7 +242,7 @@ inline bool IsAutoRepeatRangedSpell(SpellEntry const* spellInfo)
return (spellInfo->Attributes & SPELL_ATTR_RANGED) && (spellInfo->AttributesEx2 & SPELL_ATTR_EX2_AUTOREPEAT_FLAG); return (spellInfo->Attributes & SPELL_ATTR_RANGED) && (spellInfo->AttributesEx2 & SPELL_ATTR_EX2_AUTOREPEAT_FLAG);
} }
uint8 GetErrorAtShapeshiftedCast (SpellEntry const *spellInfo, uint32 form); SpellCastResult GetErrorAtShapeshiftedCast (SpellEntry const *spellInfo, uint32 form);
inline bool IsChanneledSpell(SpellEntry const* spellInfo) inline bool IsChanneledSpell(SpellEntry const* spellInfo)
{ {
@ -996,7 +810,7 @@ class SpellMgr
return NULL; return NULL;
} }
uint8 GetSpellAllowedInLocationError(SpellEntry const *spellInfo, uint32 map_id, uint32 zone_id, uint32 area_id, Player const* player = NULL); SpellCastResult GetSpellAllowedInLocationError(SpellEntry const *spellInfo, uint32 map_id, uint32 zone_id, uint32 area_id, Player const* player = NULL);
SpellAreaMapBounds GetSpellAreaMapBounds(uint32 spell_id) const SpellAreaMapBounds GetSpellAreaMapBounds(uint32 spell_id) const
{ {

View file

@ -92,8 +92,6 @@ template<class T>
void void
TargetedMovementGenerator<T>::Initialize(T &owner) TargetedMovementGenerator<T>::Initialize(T &owner)
{ {
if(!&owner)
return;
owner.RemoveUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); owner.RemoveUnitMovementFlag(MOVEMENTFLAG_WALK_MODE);
if (owner.GetTypeId() == TYPEID_UNIT && ((Creature*)&owner)->canFly()) if (owner.GetTypeId() == TYPEID_UNIT && ((Creature*)&owner)->canFly())

View file

@ -2830,7 +2830,7 @@ uint32 Unit::GetWeaponSkillValue (WeaponAttackType attType, Unit const* target)
if(attType != BASE_ATTACK && !item ) if(attType != BASE_ATTACK && !item )
return 0; return 0;
if(((Player*)this)->IsInFeralForm()) if(IsInFeralForm())
return GetMaxSkillValueForLevel(); // always maximized SKILL_FERAL_COMBAT in fact return GetMaxSkillValueForLevel(); // always maximized SKILL_FERAL_COMBAT in fact
// weapon skill or (unarmed for base attack) // weapon skill or (unarmed for base attack)
@ -2956,7 +2956,7 @@ void Unit::_UpdateAutoRepeatSpell()
if (isAttackReady(RANGED_ATTACK)) if (isAttackReady(RANGED_ATTACK))
{ {
// Check if able to cast // Check if able to cast
if(m_currentSpells[CURRENT_AUTOREPEAT_SPELL]->CanCast(true)) if(m_currentSpells[CURRENT_AUTOREPEAT_SPELL]->CheckCast(true) != SPELL_CAST_OK)
{ {
InterruptSpell(CURRENT_AUTOREPEAT_SPELL); InterruptSpell(CURRENT_AUTOREPEAT_SPELL);
return; return;
@ -7120,6 +7120,7 @@ bool Unit::Attack(Unit *victim, bool meleeAttack)
if(HasAuraType(SPELL_AURA_MOD_UNATTACKABLE)) if(HasAuraType(SPELL_AURA_MOD_UNATTACKABLE))
RemoveSpellsCausingAura(SPELL_AURA_MOD_UNATTACKABLE); RemoveSpellsCausingAura(SPELL_AURA_MOD_UNATTACKABLE);
// in fighting already
if (m_attacking) if (m_attacking)
{ {
if (m_attacking == victim) if (m_attacking == victim)
@ -7133,7 +7134,16 @@ bool Unit::Attack(Unit *victim, bool meleeAttack)
} }
return false; return false;
} }
AttackStop();
// remove old target data
AttackStop(true);
}
// new battle
else
{
// set position before any AI calls/assistance
if(GetTypeId()==TYPEID_UNIT)
((Creature*)this)->SetCombatStartPosition(GetPositionX(), GetPositionY(), GetPositionZ());
} }
//Set our target //Set our target
@ -7142,10 +7152,6 @@ bool Unit::Attack(Unit *victim, bool meleeAttack)
if(meleeAttack) if(meleeAttack)
addUnitState(UNIT_STAT_MELEE_ATTACKING); addUnitState(UNIT_STAT_MELEE_ATTACKING);
// set position before any AI calls/assistance
if(GetTypeId()==TYPEID_UNIT)
((Creature*)this)->SetCombatStartPosition(GetPositionX(), GetPositionY(), GetPositionZ());
m_attacking = victim; m_attacking = victim;
m_attacking->_addAttacker(this); m_attacking->_addAttacker(this);
@ -7172,7 +7178,7 @@ bool Unit::Attack(Unit *victim, bool meleeAttack)
return true; return true;
} }
bool Unit::AttackStop() bool Unit::AttackStop(bool targetSwitch /*=false*/)
{ {
if (!m_attacking) if (!m_attacking)
return false; return false;
@ -7189,11 +7195,9 @@ bool Unit::AttackStop()
InterruptSpell(CURRENT_MELEE_SPELL); InterruptSpell(CURRENT_MELEE_SPELL);
if( GetTypeId()==TYPEID_UNIT ) // reset only at real combat stop
{ if(!targetSwitch && GetTypeId()==TYPEID_UNIT )
// reset call assistance
((Creature*)this)->SetNoCallAssistance(false); ((Creature*)this)->SetNoCallAssistance(false);
}
SendAttackStop(victim); SendAttackStop(victim);
@ -9629,7 +9633,7 @@ uint32 Unit::GetCreatureType() const
{ {
if(GetTypeId() == TYPEID_PLAYER) if(GetTypeId() == TYPEID_PLAYER)
{ {
SpellShapeshiftEntry const* ssEntry = sSpellShapeshiftStore.LookupEntry(((Player*)this)->m_form); SpellShapeshiftEntry const* ssEntry = sSpellShapeshiftStore.LookupEntry(m_form);
if(ssEntry && ssEntry->creatureType > 0) if(ssEntry && ssEntry->creatureType > 0)
return ssEntry->creatureType; return ssEntry->creatureType;
else else
@ -10599,8 +10603,11 @@ Player* Unit::GetSpellModOwner()
} }
///----------Pet responses methods----------------- ///----------Pet responses methods-----------------
void Unit::SendPetCastFail(uint32 spellid, uint8 msg) void Unit::SendPetCastFail(uint32 spellid, SpellCastResult msg)
{ {
if(msg == SPELL_CAST_OK)
return;
Unit *owner = GetCharmerOrOwner(); Unit *owner = GetCharmerOrOwner();
if(!owner || owner->GetTypeId() != TYPEID_PLAYER) if(!owner || owner->GetTypeId() != TYPEID_PLAYER)
return; return;
@ -11361,3 +11368,19 @@ void Unit::SetPhaseMask(uint32 newPhaseMask, bool update)
if(Pet* pet = GetPet()) if(Pet* pet = GetPet())
pet->SetPhaseMask(newPhaseMask,true); pet->SetPhaseMask(newPhaseMask,true);
} }
void Unit::NearTeleportTo( float x, float y, float z, float orientation, bool casting /*= false*/ )
{
if(GetTypeId() == TYPEID_PLAYER)
((Player*)this)->TeleportTo(GetMapId(), x, y, z, orientation, TELE_TO_NOT_LEAVE_TRANSPORT | TELE_TO_NOT_LEAVE_COMBAT | TELE_TO_NOT_UNSUMMON_PET | (casting ? TELE_TO_SPELL : 0));
else
{
GetMap()->CreatureRelocation((Creature*)this, x, y, z, orientation);
WorldPacket data;
// Work strange for many spells: triggered active mover set for targeted player to creature
//BuildTeleportAckMsg(&data, x, y, z, orientation);
BuildHeartBeatMsg(&data);
SendMessageToSet(&data, false);
}
}

View file

@ -75,7 +75,7 @@ enum SpellAuraInterruptFlags
AURA_INTERRUPT_FLAG_MOUNTING = 0x00020000, // 17 removed by mounting AURA_INTERRUPT_FLAG_MOUNTING = 0x00020000, // 17 removed by mounting
AURA_INTERRUPT_FLAG_NOT_SEATED = 0x00040000, // 18 removed by standing up AURA_INTERRUPT_FLAG_NOT_SEATED = 0x00040000, // 18 removed by standing up
AURA_INTERRUPT_FLAG_CHANGE_MAP = 0x00080000, // 19 leaving map/getting teleported AURA_INTERRUPT_FLAG_CHANGE_MAP = 0x00080000, // 19 leaving map/getting teleported
AURA_INTERRUPT_FLAG_UNK20 = 0x00100000, // 20 AURA_INTERRUPT_FLAG_IMMUNE_OR_STEALTH = 0x00100000, // 20 removed when player on himself casts immunity spell or vanish?
AURA_INTERRUPT_FLAG_UNK21 = 0x00200000, // 21 AURA_INTERRUPT_FLAG_UNK21 = 0x00200000, // 21
AURA_INTERRUPT_FLAG_UNK22 = 0x00400000, // 22 AURA_INTERRUPT_FLAG_UNK22 = 0x00400000, // 22
AURA_INTERRUPT_FLAG_ENTER_PVP_COMBAT = 0x00800000, // 23 removed by entering pvp combat AURA_INTERRUPT_FLAG_ENTER_PVP_COMBAT = 0x00800000, // 23 removed by entering pvp combat
@ -850,7 +850,7 @@ class MANGOS_DLL_SPEC Unit : public WorldObject
} }
bool Attack(Unit *victim, bool meleeAttack); bool Attack(Unit *victim, bool meleeAttack);
void CastStop(uint32 except_spellid = 0); void CastStop(uint32 except_spellid = 0);
bool AttackStop(); bool AttackStop(bool targetSwitch = false);
void RemoveAllAttackers(); void RemoveAllAttackers();
AttackerSet const& getAttackers() const { return m_attackers; } AttackerSet const& getAttackers() const { return m_attackers; }
bool isAttackingPlayer() const; bool isAttackingPlayer() const;
@ -1066,6 +1066,8 @@ class MANGOS_DLL_SPEC Unit : public WorldObject
void SendSpellNonMeleeDamageLog(Unit *target,uint32 SpellID,uint32 Damage, SpellSchoolMask damageSchoolMask,uint32 AbsorbedDamage, uint32 Resist,bool PhysicalDamage, uint32 Blocked, bool CriticalHit = false); void SendSpellNonMeleeDamageLog(Unit *target,uint32 SpellID,uint32 Damage, SpellSchoolMask damageSchoolMask,uint32 AbsorbedDamage, uint32 Resist,bool PhysicalDamage, uint32 Blocked, bool CriticalHit = false);
void SendSpellMiss(Unit *target, uint32 spellID, SpellMissInfo missInfo); void SendSpellMiss(Unit *target, uint32 spellID, SpellMissInfo missInfo);
void NearTeleportTo(float x, float y, float z, float orientation, bool casting = false);
void SendMonsterMove(float NewPosX, float NewPosY, float NewPosZ, uint8 type, uint32 MovementFlags, uint32 Time, Player* player = NULL); void SendMonsterMove(float NewPosX, float NewPosY, float NewPosZ, uint8 type, uint32 MovementFlags, uint32 Time, Player* player = NULL);
void SendMonsterMoveByPath(Path const& path, uint32 start, uint32 end, uint32 MovementFlags); void SendMonsterMoveByPath(Path const& path, uint32 start, uint32 end, uint32 MovementFlags);
void SendMonsterMoveWithSpeed(float x, float y, float z, uint32 transitTime = 0, Player* player = NULL); void SendMonsterMoveWithSpeed(float x, float y, float z, uint32 transitTime = 0, Player* player = NULL);
@ -1195,8 +1197,11 @@ class MANGOS_DLL_SPEC Unit : public WorldObject
uint64 m_ObjectSlot[4]; uint64 m_ObjectSlot[4];
uint32 m_detectInvisibilityMask; uint32 m_detectInvisibilityMask;
uint32 m_invisibilityMask; uint32 m_invisibilityMask;
uint32 m_ShapeShiftFormSpellId; uint32 m_ShapeShiftFormSpellId;
ShapeshiftForm m_form; ShapeshiftForm m_form;
bool IsInFeralForm() const { return m_form == FORM_CAT || m_form == FORM_BEAR || m_form == FORM_DIREBEAR; }
float m_modMeleeHitChance; float m_modMeleeHitChance;
float m_modRangedHitChance; float m_modRangedHitChance;
float m_modSpellHitChance; float m_modSpellHitChance;
@ -1401,7 +1406,7 @@ class MANGOS_DLL_SPEC Unit : public WorldObject
void ClearComboPointHolders(); void ClearComboPointHolders();
///----------Pet responses methods----------------- ///----------Pet responses methods-----------------
void SendPetCastFail(uint32 spellid, uint8 msg); void SendPetCastFail(uint32 spellid, SpellCastResult msg);
void SendPetActionFeedback (uint8 msg); void SendPetActionFeedback (uint8 msg);
void SendPetTalk (uint32 pettalk); void SendPetTalk (uint32 pettalk);
void SendPetSpellCooldown (uint32 spellid, time_t cooltime); void SendPetSpellCooldown (uint32 spellid, time_t cooltime);

View file

@ -245,11 +245,13 @@ void FlightPathMovementGenerator::Initialize(Player &player)
void FlightPathMovementGenerator::Finalize(Player & player) void FlightPathMovementGenerator::Finalize(Player & player)
{ {
// remove flag to prevent send object build movement packets for flight state and crash (movement generator already not at top of stack)
player.clearUnitState(UNIT_STAT_IN_FLIGHT);
float x, y, z; float x, y, z;
i_destinationHolder.GetLocationNow(player.GetMapId(), x, y, z); i_destinationHolder.GetLocationNow(player.GetMapId(), x, y, z);
player.SetPosition(x, y, z, player.GetOrientation()); player.SetPosition(x, y, z, player.GetOrientation());
player.clearUnitState(UNIT_STAT_IN_FLIGHT);
player.Unmount(); player.Unmount();
player.RemoveFlag(UNIT_FIELD_FLAGS,UNIT_FLAG_DISABLE_MOVE | UNIT_FLAG_TAXI_FLIGHT); player.RemoveFlag(UNIT_FIELD_FLAGS,UNIT_FLAG_DISABLE_MOVE | UNIT_FLAG_TAXI_FLIGHT);

View file

@ -374,6 +374,7 @@ struct AchievementCriteriaEntry
struct struct
{ {
uint32 itemID; // 3 uint32 itemID; // 3
uint32 count; // 4
} equip_item; } equip_item;
// ACHIEVEMENT_CRITERIA_TYPE_MONEY_FROM_QUEST_REWARD= 62 // ACHIEVEMENT_CRITERIA_TYPE_MONEY_FROM_QUEST_REWARD= 62
@ -975,13 +976,15 @@ struct ItemSetEntry
uint32 required_skill_value; // 52 m_requiredSkillRank uint32 required_skill_value; // 52 m_requiredSkillRank
}; };
#define MAX_LOCK_CASE 8
struct LockEntry struct LockEntry
{ {
uint32 ID; // 0 m_ID uint32 ID; // 0 m_ID
uint32 Type[8]; // 1-8 m_Type uint32 Type[MAX_LOCK_CASE]; // 1-8 m_Type
uint32 Index[8]; // 9-16 m_Index uint32 Index[MAX_LOCK_CASE]; // 9-16 m_Index
uint32 Skill[8]; // 17-24 m_Skill uint32 Skill[MAX_LOCK_CASE]; // 17-24 m_Skill
//uint32 Action[8]; // 25-32 m_Action //uint32 Action[MAX_LOCK_CASE]; // 25-32 m_Action
}; };
struct MailTemplateEntry struct MailTemplateEntry

View file

@ -1,4 +1,4 @@
#ifndef __REVISION_NR_H__ #ifndef __REVISION_NR_H__
#define __REVISION_NR_H__ #define __REVISION_NR_H__
#define REVISION_NR "7440" #define REVISION_NR "7483"
#endif // __REVISION_NR_H__ #endif // __REVISION_NR_H__