diff --git a/contrib/Makefile.am b/contrib/Makefile.am deleted file mode 100644 index d39f2caa8..000000000 --- a/contrib/Makefile.am +++ /dev/null @@ -1,23 +0,0 @@ -# Copyright (C) 2005-2009 MaNGOS -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -## Process this file with automake to produce Makefile.in - -## Sub-directories to parse -SUBDIRS = extractor - -## Additional files to include when running 'make dist' -# Nothing yet. diff --git a/contrib/extractor/CMakeLists.txt b/contrib/extractor/CMakeLists.txt new file mode 100644 index 000000000..a00dda120 --- /dev/null +++ b/contrib/extractor/CMakeLists.txt @@ -0,0 +1,21 @@ +# Copyright (C) 2005-2009 MaNGOS project +# +# This file is free software; as a special exception the author gives +# unlimited permission to copy and/or distribute it, with or without +# modifications, as long as this notice is preserved. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY, to the extent permitted by law; without even the +# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +cmake_minimum_required (VERSION 2.6) +project (MANGOS_MAP_EXTRACTOR) + +add_subdirectory (libmpq) + +include_directories (${MANGOS_MAP_EXTRACTOR_SOURCE_DIR}/libmpq) +link_directories (${MANGOS_MAP_EXTRACTOR_SOURCE_DIR}/libmpq) + +add_executable (ad adt.cpp dbcfile.cpp mpq_libmpq.cpp System.cpp) + +target_link_libraries (ad libmpq) diff --git a/contrib/extractor/Makefile.am b/contrib/extractor/Makefile.am deleted file mode 100644 index b84617069..000000000 --- a/contrib/extractor/Makefile.am +++ /dev/null @@ -1,10 +0,0 @@ -# The top-level input Makefile for mpq-tools - -# Any directories which should be built and installed. -SUBDIRS = libmpq - -# The directories which are part of the distribution. -DIST_SUBDIRS = $(SUBDIRS) - -EXTRA_DIST = \ - README.linux diff --git a/contrib/extractor/README.linux b/contrib/extractor/README.linux index e1ebdb8bb..1986831e7 100644 --- a/contrib/extractor/README.linux +++ b/contrib/extractor/README.linux @@ -1,13 +1,7 @@ Linux instructions ------------------ -1. Configure and build MaNGOS. -2. cd contrib/map_extractor/libmpq/ +1. install cmake +2. cmake -i 3. make -4. cd .. -5. make -6. run ad - -if there are any problems create folder named .deps in contrib/map_extractor/ -it is old bug from first extractor and i am too lasy to fix it :) - +4. ./ad diff --git a/contrib/extractor/libmpq/CMakeLists.txt b/contrib/extractor/libmpq/CMakeLists.txt new file mode 100644 index 000000000..c00120c6e --- /dev/null +++ b/contrib/extractor/libmpq/CMakeLists.txt @@ -0,0 +1,13 @@ +# Copyright (C) 2005-2009 MaNGOS project +# +# This file is free software; as a special exception the author gives +# unlimited permission to copy and/or distribute it, with or without +# modifications, as long as this notice is preserved. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY, to the extent permitted by law; without even the +# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +add_library (libmpq common.cpp explode.cpp extract.cpp huffman.cpp mpq.cpp parser.cpp wave.cpp ) +# link libmpq with zlib +target_link_libraries (libmpq z) diff --git a/contrib/extractor/libmpq/Makefile.am b/contrib/extractor/libmpq/Makefile.am deleted file mode 100644 index 192bd1369..000000000 --- a/contrib/extractor/libmpq/Makefile.am +++ /dev/null @@ -1,23 +0,0 @@ -# The input Makefile for the main mpq-tools - -lib_LTLIBRARIES = libmpq.la -noinst_HEADERS = explode.h huffman.h wave.h common.h - -# The directory where the include files will be installed. -libmpq_includedir = $(includedir)/libmpq - -# Which header files to install. -libmpq_include_HEADERS = mpq.h - -libmpq_la_SOURCES = $(GENERAL_SRCS) -libmpq_la_LDFLAGS = -release $(LIBMPQ_VERSION) -libmpq_la_LIBADD = @Z_LIBS@ - -GENERAL_SRCS = \ - common.c \ - huffman.c \ - extract.c \ - explode.c \ - mpq.c \ - parser.c \ - wave.c diff --git a/sql/characters.sql b/sql/characters.sql index 701a2cee8..078afe024 100644 --- a/sql/characters.sql +++ b/sql/characters.sql @@ -21,7 +21,7 @@ DROP TABLE IF EXISTS `character_db_version`; CREATE TABLE `character_db_version` ( - `required_7075_01_characters_character_spell` bit(1) default NULL + `required_7113_01_characters_character_achievement_progress` bit(1) default NULL ) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=FIXED COMMENT='Last applied sql update to DB'; -- diff --git a/sql/mangos.sql b/sql/mangos.sql index 1854d1492..686c3a8fc 100644 --- a/sql/mangos.sql +++ b/sql/mangos.sql @@ -22,7 +22,7 @@ DROP TABLE IF EXISTS `db_version`; CREATE TABLE `db_version` ( `version` varchar(120) default NULL, - `required_7075_02_mangos_spell_learn_spell` bit(1) default NULL + `required_7133_02_mangos_spell_loot_template` bit(1) default NULL ) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=FIXED COMMENT='Used DB version notes'; -- @@ -2661,7 +2661,7 @@ INSERT INTO `mangos_string` VALUES (518,'%d - |cffffffff|Hitemset:%d|h[%s %s]|h|r ',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), (519,'|cffffffff|Htele:%s|h[%s]|h|r ',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), (520,'%d - |cffffffff|Hspell:%d|h[%s]|h|r ',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), -(521,'%d - |cffffffff|Hskill:%d|h[%s %s]|h|r %s',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(521,'%d - |cffffffff|Hskill:%d|h[%s %s]|h|r %s %s',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), (522,'Game Object (GUID: %u) not found',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), (523,'>> Game Object %s (GUID: %u) at %f %f %f. Orientation %f.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), (524,'Selected object:\n|cffffffff|Hitemset:%d|h[%s]|h|r\nGUID: %u ID: %u\nX: %f Y: %f Z: %f MapId: %u\nOrientation: %f',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), @@ -2841,7 +2841,7 @@ INSERT INTO `mangos_string` VALUES (1106,'%d - %s %s',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), (1107,'%d - %s',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), (1108,'%d - %s %s',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), -(1109,'%d - %s %s %s',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1109,'%d - %s %s %s %s',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), (1110,'%d - %s X:%f Y:%f Z:%f MapId:%d',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), (1111,'%d - %s X:%f Y:%f Z:%f MapId:%d',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), (1112,'Failed to open file: %s',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), @@ -2853,7 +2853,8 @@ INSERT INTO `mangos_string` VALUES (1118,'%d - guild: %s (guid: %u) %s',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), (1119,'You must use male or female as gender.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), (1120,'You change gender of %s to %s.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), -(1121,'Your gender changed to %s by %s.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL); +(1121,'Your gender changed to %s by %s.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1122,'(%u/%u +perm %u +temp %u)',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL); /*!40000 ALTER TABLE `mangos_string` ENABLE KEYS */; UNLOCK TABLES; @@ -9291,6 +9292,105 @@ INSERT INTO `player_levelstats` VALUES /*!40000 ALTER TABLE `player_levelstats` ENABLE KEYS */; UNLOCK TABLES; +-- ---------------------------- +-- Table structure for player_xp_for_level +-- ---------------------------- +DROP TABLE IF EXISTS `player_xp_for_level`; +CREATE TABLE `player_xp_for_level` ( + `lvl` int(3) unsigned NOT NULL, + `xp_for_next_level` int(10) unsigned NOT NULL, + PRIMARY KEY (`lvl`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; + +-- +-- Dumping data for table `player_xp_for_level` +-- + +LOCK TABLES `player_xp_for_level` WRITE; +/*!40000 ALTER TABLE `player_xp_for_level` DISABLE KEYS */; +INSERT INTO `player_xp_for_level` VALUES +('1', '400'), +('2', '900'), +('3', '1400'), +('4', '2100'), +('5', '2800'), +('6', '3600'), +('7', '4500'), +('8', '5400'), +('9', '6500'), +('10', '7600'), +('11', '8700'), +('12', '9800'), +('13', '11000'), +('14', '12300'), +('15', '13600'), +('16', '15000'), +('17', '16400'), +('18', '17800'), +('19', '19300'), +('20', '20800'), +('21', '22400'), +('22', '24000'), +('23', '25500'), +('24', '27200'), +('25', '28900'), +('26', '30500'), +('27', '32200'), +('28', '33900'), +('29', '36300'), +('30', '38800'), +('31', '41600'), +('32', '44600'), +('33', '48000'), +('34', '51400'), +('35', '55000'), +('36', '58700'), +('37', '62400'), +('38', '66200'), +('39', '70200'), +('40', '74300'), +('41', '78500'), +('42', '82800'), +('43', '87100'), +('44', '91600'), +('45', '96300'), +('46', '101000'), +('47', '105800'), +('48', '110700'), +('49', '115700'), +('50', '120900'), +('51', '126100'), +('52', '131500'), +('53', '137000'), +('54', '142500'), +('55', '148200'), +('56', '154000'), +('57', '159900'), +('58', '165800'), +('59', '172000'), +('60', '290000'), +('61', '317000'), +('62', '349000'), +('63', '386000'), +('64', '428000'), +('65', '475000'), +('66', '527000'), +('67', '585000'), +('68', '648000'), +('69', '717000'), +('70', '1523800'), +('71', '1539600'), +('72', '1555700'), +('73', '1571800'), +('74', '1587900'), +('75', '1604200'), +('76', '1620700'), +('77', '1637400'), +('78', '1653900'), +('79', '1670800'); +/*!40000 ALTER TABLE `player_xp_for_level` ENABLE KEYS */; +UNLOCK TABLES; + -- -- Table structure for table `playercreateinfo` -- @@ -12899,8 +12999,9 @@ DROP TABLE IF EXISTS `skill_discovery_template`; CREATE TABLE `skill_discovery_template` ( `spellId` mediumint(8) unsigned NOT NULL default '0' COMMENT 'SpellId of the discoverable spell', `reqSpell` mediumint(8) unsigned NOT NULL default '0' COMMENT 'spell requirement', + `reqSkillValue` smallint(5) unsigned NOT NULL default '0' COMMENT 'skill points requirement', `chance` float NOT NULL default '0' COMMENT 'chance to discover', - PRIMARY KEY (`spellId`) + PRIMARY KEY (`spellId`,`reqSpell`) ) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=FIXED COMMENT='Skill Discovery System'; -- @@ -16124,6 +16225,33 @@ INSERT INTO `spell_learn_spell` VALUES /*!40000 ALTER TABLE `spell_learn_spell` ENABLE KEYS */; UNLOCK TABLES; +-- +-- Table structure for table `spell_loot_template` +-- + +DROP TABLE IF EXISTS `spell_loot_template`; +CREATE TABLE `spell_loot_template` ( + `entry` mediumint(8) unsigned NOT NULL default '0', + `item` mediumint(8) unsigned NOT NULL default '0', + `ChanceOrQuestChance` float NOT NULL default '100', + `groupid` tinyint(3) unsigned NOT NULL default '0', + `mincountOrRef` mediumint(9) NOT NULL default '1', + `maxcount` tinyint(3) unsigned NOT NULL default '1', + `lootcondition` tinyint(3) unsigned NOT NULL default '0', + `condition_value1` mediumint(8) unsigned NOT NULL default '0', + `condition_value2` mediumint(8) unsigned NOT NULL default '0', + PRIMARY KEY (`entry`,`item`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=FIXED COMMENT='Loot System'; + +-- +-- Dumping data for table `spell_loot_template` +-- + +LOCK TABLES `spell_loot_template` WRITE; +/*!40000 ALTER TABLE `spell_loot_template` DISABLE KEYS */; +/*!40000 ALTER TABLE `spell_loot_template` ENABLE KEYS */; +UNLOCK TABLES; + -- -- Table structure for table `spell_pet_auras` -- @@ -16324,7 +16452,7 @@ INSERT INTO `spell_proc_event` VALUES (15362, 0x00000000, 6, 0x10001E00, 0x00010004, 0x00000000, 0x00000000, 0x00000002, 0.000000, 0.000000, 0), (15363, 0x00000000, 6, 0x10001E00, 0x00010004, 0x00000000, 0x00000000, 0x00000002, 0.000000, 0.000000, 0), (15600, 0x00000000, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 1.000000, 0.000000, 0), -(16164, 0x00000000, 11, 0x90100003, 0x00000000, 0x00000000, 0x00000000, 0x00000002, 0.000000, 0.000000, 0), +(16164, 0x00000000, 11, 0x901000C3, 0x00000000, 0x00000000, 0x00000000, 0x00000002, 0.000000, 0.000000, 0), (16176, 0x00000000, 11, 0x000001C0, 0x00000000, 0x00000000, 0x00000000, 0x00000002, 0.000000, 0.000000, 0), (16180, 0x00000000, 11, 0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000002, 0.000000, 0.000000, 0), (16196, 0x00000000, 11, 0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000002, 0.000000, 0.000000, 0), @@ -16548,6 +16676,8 @@ INSERT INTO `spell_proc_event` VALUES (31833, 0x00000000, 10, 0x80000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 0), (31835, 0x00000000, 10, 0x80000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 0), (31836, 0x00000000, 10, 0x80000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 0), +(31871, 0x00000000, 10, 0x00000010, 0x00000000, 0x00000000, 0x00004000, 0x00000000, 0.000000, 0.000000, 0), +(31872, 0x00000000, 10, 0x00000010, 0x00000000, 0x00000000, 0x00004000, 0x00000000, 0.000000, 0.000000, 0), (31876, 0x00000000, 10, 0x00800000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 0), (31877, 0x00000000, 10, 0x00800000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 0), (31878, 0x00000000, 10, 0x00800000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 0), @@ -16629,9 +16759,9 @@ INSERT INTO `spell_proc_event` VALUES (35080, 0x00000000, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 1.000000, 0.000000, 60), (35083, 0x00000000, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 60), (35086, 0x00000000, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 60), -(35100, 0x00000000, 9, 0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 0), -(35102, 0x00000000, 9, 0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 0), -(35103, 0x00000000, 9, 0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 0), +(35100, 0x00000000, 9, 0x00003001, 0x00000000, 0x00000000, 0x00010140, 0x00000000, 0.000000, 0.000000, 0), +(35102, 0x00000000, 9, 0x00003001, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 0), +(35103, 0x00000000, 9, 0x00003001, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 0), (35121, 0x00000000, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000002, 0.000000, 0.000000, 0), (36096, 0x00000000, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000800, 0.000000, 0.000000, 0), (36111, 0x00000000, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 0), @@ -16709,6 +16839,7 @@ INSERT INTO `spell_proc_event` VALUES (42136, 0x00000000, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 90), (42368, 0x00000000, 10, 0x40000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 0), (42370, 0x00000000, 11, 0x00000040, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 0), +(42770, 0x00000000, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00010000, 0.000000, 0.000000, 0), (43019, 0x00000000, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000400, 0.000000, 0.000000, 0), (43020, 0x00000000, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000400, 0.000000, 0.000000, 0), (43338, 0x00000000, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000002, 0.000000, 0.000000, 0), @@ -16722,6 +16853,9 @@ INSERT INTO `spell_proc_event` VALUES (43748, 0x00000000, 11, 0x90100000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 0), (43750, 0x00000000, 11, 0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 0), (43819, 0x00000000, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00010000, 0.000000, 0.000000, 0), +(44394, 0x00000000, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000400, 0.000000, 0.000000, 0), +(44395, 0x00000000, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000400, 0.000000, 0.000000, 0), +(44396, 0x00000000, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000400, 0.000000, 0.000000, 0), (44404, 0x00000000, 3, 0x20000021, 0x00009000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 0), (44445, 0x00000000, 3, 0x00000013, 0x00001000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 0), (44446, 0x00000000, 3, 0x00000013, 0x00001000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 0), @@ -16786,11 +16920,11 @@ INSERT INTO `spell_proc_event` VALUES (47515, 0x00000000, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000002, 0.000000, 0.000000, 0), (47516, 0x00000000, 6, 0x00001800, 0x00010000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 0), (47517, 0x00000000, 6, 0x00001800, 0x00010000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 0), -(47535, 0x00000000, 6, 0x00001800, 0x00800000, 0x00000000, 0x00000000, 0x00010000, 0.000000, 0.000000, 0), -(47536, 0x00000000, 6, 0x00001800, 0x00800000, 0x00000000, 0x00000000, 0x00010000, 0.000000, 0.000000, 0), -(47537, 0x00000000, 6, 0x00001800, 0x00800000, 0x00000000, 0x00000000, 0x00010000, 0.000000, 0.000000, 0), -(47538, 0x00000000, 6, 0x00001800, 0x00800000, 0x00000000, 0x00000000, 0x00010000, 0.000000, 0.000000, 0), -(47539, 0x00000000, 6, 0x00001800, 0x00800000, 0x00000000, 0x00000000, 0x00010000, 0.000000, 0.000000, 0), +(47535, 0x00000000, 6, 0x00001800, 0x00800000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 0), +(47536, 0x00000000, 6, 0x00001800, 0x00800000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 0), +(47537, 0x00000000, 6, 0x00001800, 0x00800000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 0), +(47538, 0x00000000, 6, 0x00001800, 0x00800000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 0), +(47539, 0x00000000, 6, 0x00001800, 0x00800000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 0), (47549, 0x00000000, 6, 0x00000000, 0x00020000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 0), (47551, 0x00000000, 6, 0x00000000, 0x00020000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 0), (47552, 0x00000000, 6, 0x00000000, 0x00020000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 0), @@ -16798,9 +16932,9 @@ INSERT INTO `spell_proc_event` VALUES (47556, 0x00000000, 6, 0x00001800, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 0), (47557, 0x00000000, 6, 0x00001800, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 0), (47572, 0x00000000, 6, 0x00010000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 0), -(47580, 0x00000000, 6, 0x00000000, 0x00000000, 0x00000040, 0x00000000, 0x00000000, 0.000000, 0.000000, 0), -(47581, 0x00000000, 6, 0x00000000, 0x00000000, 0x00000040, 0x00000000, 0x00000000, 0.000000, 0.000000, 0), -(47582, 0x00000000, 6, 0x00000000, 0x00000000, 0x00000040, 0x00000000, 0x00000000, 0.000000, 0.000000, 0), +(47580, 0x00000000, 6, 0x00000000, 0x00000000, 0x00000040, 0x00000000, 0x00010000, 0.000000, 0.000000, 0), +(47581, 0x00000000, 6, 0x00000000, 0x00000000, 0x00000040, 0x00000000, 0x00010000, 0.000000, 0.000000, 0), +(47582, 0x00000000, 6, 0x00000000, 0x00000000, 0x00000040, 0x00000000, 0x00010000, 0.000000, 0.000000, 0), (48110, 0x00000000, 0, 0x00000000, 0x00000000, 0x00000000, 0x000A02A8, 0x00000000, 0.000000, 0.000000, 0), (48111, 0x00000000, 0, 0x00000000, 0x00000000, 0x00000000, 0x000A02A8, 0x00000000, 0.000000, 0.000000, 0), (48112, 0x00000000, 0, 0x00000000, 0x00000000, 0x00000000, 0x000A02A8, 0x00000000, 0.000000, 0.000000, 0), @@ -17029,6 +17163,7 @@ INSERT INTO `spell_proc_event` VALUES (60818, 0x00000000, 10, 0x00000000, 0x00000200, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 0), (60826, 0x00000000, 15, 0x01400000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 0), (61188, 0x00000000, 5, 0x00000004, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 0), +(61257, 0x00000000, 0, 0x00000000, 0x00000000, 0x00000000, 0x000202A8, 0x00010000, 0.000000, 0.000000, 0), (61324, 0x00000000, 10, 0x00000000, 0x00020000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 0); /*!40000 ALTER TABLE `spell_proc_event` ENABLE KEYS */; UNLOCK TABLES; diff --git a/sql/updates/2008_12_22_19_characters_item_instance.sql b/sql/updates/2008_12_22_19_characters_item_instance.sql index 96f31ff47..e737e24da 100644 --- a/sql/updates/2008_12_22_19_characters_item_instance.sql +++ b/sql/updates/2008_12_22_19_characters_item_instance.sql @@ -4,8 +4,8 @@ UPDATE item_instance SET data = REPLACE(data,' ',' '); UPDATE item_instance SET data = CONCAT(TRIM(data),' '); UPDATE item_instance SET data= CONCAT( - SUBSTRING_INDEX(SUBSTRING_INDEX(data,' ',30),' ',-30),' 0 0 0 ', - SUBSTRING_INDEX(SUBSTRING_INDEX(data,' ',60),' ',-60+30),' 0 ') + SUBSTRING_INDEX(SUBSTRING_INDEX(data,' ',54),' ',-54),' 0 0 0 ', + SUBSTRING_INDEX(SUBSTRING_INDEX(data,' ',60),' ',-60+54),' 0 ') WHERE SUBSTRING_INDEX(data,' ',60) = data AND SUBSTRING_INDEX(data,' ',60-1) <> data; UPDATE item_instance SET data= CONCAT( diff --git a/sql/updates/7077_01_characters_character_spell.sql b/sql/updates/7077_01_characters_character_spell.sql new file mode 100644 index 000000000..b68f99b1d --- /dev/null +++ b/sql/updates/7077_01_characters_character_spell.sql @@ -0,0 +1,214 @@ +ALTER TABLE character_db_version CHANGE COLUMN required_7075_01_characters_character_spell required_7077_01_characters_character_spell bit; + +UPDATE IGNORE character_spell SET spell = 2018 WHERE spell = 2020; +DELETE FROM character_spell WHERE spell = 2020; + +UPDATE IGNORE character_spell SET spell = 2018 WHERE spell = 2020; +DELETE FROM character_spell WHERE spell = 2020; + +UPDATE IGNORE character_spell SET spell = 3100 WHERE spell = 2021; +DELETE FROM character_spell WHERE spell = 2021; + +UPDATE IGNORE character_spell SET spell = 3104 WHERE spell = 2154; +DELETE FROM character_spell WHERE spell = 2154; + +UPDATE IGNORE character_spell SET spell = 2108 WHERE spell = 2155; +DELETE FROM character_spell WHERE spell = 2155; + +UPDATE IGNORE character_spell SET spell = 2259 WHERE spell = 2275; +DELETE FROM character_spell WHERE spell = 2275; + +UPDATE IGNORE character_spell SET spell = 3101 WHERE spell = 2280; +DELETE FROM character_spell WHERE spell = 2280; + +UPDATE IGNORE character_spell SET spell = 2366 WHERE spell = 2372; +DELETE FROM character_spell WHERE spell = 2372; + +UPDATE IGNORE character_spell SET spell = 2368 WHERE spell = 2373; +DELETE FROM character_spell WHERE spell = 2373; + +UPDATE IGNORE character_spell SET spell = 2550 WHERE spell = 2551; +DELETE FROM character_spell WHERE spell = 2551; + +UPDATE IGNORE character_spell SET spell = 2575 WHERE spell = 2581; +DELETE FROM character_spell WHERE spell = 2581; + +UPDATE IGNORE character_spell SET spell = 2576 WHERE spell = 2582; +DELETE FROM character_spell WHERE spell = 2582; + +UPDATE IGNORE character_spell SET spell = 3273 WHERE spell = 3279; +DELETE FROM character_spell WHERE spell = 3279; + +UPDATE IGNORE character_spell SET spell = 3274 WHERE spell = 3280; +DELETE FROM character_spell WHERE spell = 3280; + +UPDATE IGNORE character_spell SET spell = 3102 WHERE spell = 3412; +DELETE FROM character_spell WHERE spell = 3412; + +UPDATE IGNORE character_spell SET spell = 3464 WHERE spell = 3465; +DELETE FROM character_spell WHERE spell = 3465; + +UPDATE IGNORE character_spell SET spell = 3538 WHERE spell = 3539; +DELETE FROM character_spell WHERE spell = 3539; + +UPDATE IGNORE character_spell SET spell = 3564 WHERE spell = 3568; +DELETE FROM character_spell WHERE spell = 3568; + +UPDATE IGNORE character_spell SET spell = 3570 WHERE spell = 3571; +DELETE FROM character_spell WHERE spell = 3571; + +UPDATE IGNORE character_spell SET spell = 3811 WHERE spell = 3812; +DELETE FROM character_spell WHERE spell = 3812; + +UPDATE IGNORE character_spell SET spell = 3908 WHERE spell = 3911; +DELETE FROM character_spell WHERE spell = 3911; + +UPDATE IGNORE character_spell SET spell = 3909 WHERE spell = 3912; +DELETE FROM character_spell WHERE spell = 3912; + +UPDATE IGNORE character_spell SET spell = 3910 WHERE spell = 3913; +DELETE FROM character_spell WHERE spell = 3913; + +UPDATE IGNORE character_spell SET spell = 4036 WHERE spell = 4039; +DELETE FROM character_spell WHERE spell = 4039; + +UPDATE IGNORE character_spell SET spell = 4037 WHERE spell = 4040; +DELETE FROM character_spell WHERE spell = 4040; + +UPDATE IGNORE character_spell SET spell = 4038 WHERE spell = 4041; +DELETE FROM character_spell WHERE spell = 4041; + +UPDATE IGNORE character_spell SET spell = 7620 WHERE spell = 7733; +DELETE FROM character_spell WHERE spell = 7733; + +UPDATE IGNORE character_spell SET spell = 7731 WHERE spell = 7734; +DELETE FROM character_spell WHERE spell = 7734; + +UPDATE IGNORE character_spell SET spell = 8613 WHERE spell = 8615; +DELETE FROM character_spell WHERE spell = 8615; + +UPDATE IGNORE character_spell SET spell = 8617 WHERE spell = 8619; +DELETE FROM character_spell WHERE spell = 8619; + +UPDATE IGNORE character_spell SET spell = 8618 WHERE spell = 8620; +DELETE FROM character_spell WHERE spell = 8620; + +UPDATE IGNORE character_spell SET spell = 9785 WHERE spell = 9786; +DELETE FROM character_spell WHERE spell = 9786; + +UPDATE IGNORE character_spell SET spell = 10248 WHERE spell = 10249; +DELETE FROM character_spell WHERE spell = 10249; + +UPDATE IGNORE character_spell SET spell = 10662 WHERE spell = 10663; +DELETE FROM character_spell WHERE spell = 10663; + +UPDATE IGNORE character_spell SET spell = 10768 WHERE spell = 10769; +DELETE FROM character_spell WHERE spell = 10769; + +UPDATE IGNORE character_spell SET spell = 11611 WHERE spell = 11612; +DELETE FROM character_spell WHERE spell = 11612; + +UPDATE IGNORE character_spell SET spell = 11993 WHERE spell = 11994; +DELETE FROM character_spell WHERE spell = 11994; + +UPDATE IGNORE character_spell SET spell = 12180 WHERE spell = 12181; +DELETE FROM character_spell WHERE spell = 12181; + +UPDATE IGNORE character_spell SET spell = 12656 WHERE spell = 12657; +DELETE FROM character_spell WHERE spell = 12657; + +UPDATE IGNORE character_spell SET spell = 25229 WHERE spell = 25245; +DELETE FROM character_spell WHERE spell = 25245; + +UPDATE IGNORE character_spell SET spell = 25230 WHERE spell = 25246; +DELETE FROM character_spell WHERE spell = 25246; + +UPDATE IGNORE character_spell SET spell = 26790 WHERE spell = 26791; +DELETE FROM character_spell WHERE spell = 26791; + +UPDATE IGNORE character_spell SET spell = 28596 WHERE spell = 28597; +DELETE FROM character_spell WHERE spell = 28597; + +UPDATE IGNORE character_spell SET spell = 28695 WHERE spell = 28696; +DELETE FROM character_spell WHERE spell = 28696; + +UPDATE IGNORE character_spell SET spell = 28894 WHERE spell = 28896; +DELETE FROM character_spell WHERE spell = 28896; + +UPDATE IGNORE character_spell SET spell = 28895 WHERE spell = 28899; +DELETE FROM character_spell WHERE spell = 28899; + +UPDATE IGNORE character_spell SET spell = 28897 WHERE spell = 28901; +DELETE FROM character_spell WHERE spell = 28901; + +UPDATE IGNORE character_spell SET spell = 29354 WHERE spell = 29355; +DELETE FROM character_spell WHERE spell = 29355; + +UPDATE IGNORE character_spell SET spell = 29844 WHERE spell = 29845; +DELETE FROM character_spell WHERE spell = 29845; + +UPDATE IGNORE character_spell SET spell = 30350 WHERE spell = 30351; +DELETE FROM character_spell WHERE spell = 30351; + +UPDATE IGNORE character_spell SET spell = 32549 WHERE spell = 32550; +DELETE FROM character_spell WHERE spell = 32550; + +UPDATE IGNORE character_spell SET spell = 32678 WHERE spell = 32679; +DELETE FROM character_spell WHERE spell = 32679; + +UPDATE IGNORE character_spell SET spell = 45357 WHERE spell = 45375; +DELETE FROM character_spell WHERE spell = 45375; + +UPDATE IGNORE character_spell SET spell = 45358 WHERE spell = 45376; +DELETE FROM character_spell WHERE spell = 45376; + +UPDATE IGNORE character_spell SET spell = 45359 WHERE spell = 45377; +DELETE FROM character_spell WHERE spell = 45377; + +UPDATE IGNORE character_spell SET spell = 45360 WHERE spell = 45378; +DELETE FROM character_spell WHERE spell = 45378; + +UPDATE IGNORE character_spell SET spell = 45361 WHERE spell = 45379; +DELETE FROM character_spell WHERE spell = 45379; + +UPDATE IGNORE character_spell SET spell = 45363 WHERE spell = 45380; +DELETE FROM character_spell WHERE spell = 45380; + +UPDATE IGNORE character_spell SET spell = 45542 WHERE spell = 50299; +DELETE FROM character_spell WHERE spell = 50299; + +UPDATE IGNORE character_spell SET spell = 50305 WHERE spell = 50307; +DELETE FROM character_spell WHERE spell = 50307; + +UPDATE IGNORE character_spell SET spell = 50310 WHERE spell = 50309; +DELETE FROM character_spell WHERE spell = 50309; + +UPDATE IGNORE character_spell SET spell = 51294 WHERE spell = 51293; +DELETE FROM character_spell WHERE spell = 51293; + +UPDATE IGNORE character_spell SET spell = 51296 WHERE spell = 51295; +DELETE FROM character_spell WHERE spell = 51295; + +UPDATE IGNORE character_spell SET spell = 51300 WHERE spell = 51298; +DELETE FROM character_spell WHERE spell = 51298; + +UPDATE IGNORE character_spell SET spell = 51302 WHERE spell = 51301; +DELETE FROM character_spell WHERE spell = 51301; + +UPDATE IGNORE character_spell SET spell = 51304 WHERE spell = 51303; +DELETE FROM character_spell WHERE spell = 51303; + +UPDATE IGNORE character_spell SET spell = 51306 WHERE spell = 51305; +DELETE FROM character_spell WHERE spell = 51305; + +UPDATE IGNORE character_spell SET spell = 51309 WHERE spell = 51308; +DELETE FROM character_spell WHERE spell = 51308; + +UPDATE IGNORE character_spell SET spell = 51311 WHERE spell = 51310; +DELETE FROM character_spell WHERE spell = 51310; + +UPDATE IGNORE character_spell SET spell = 51313 WHERE spell = 51312; +DELETE FROM character_spell WHERE spell = 51312; + +UPDATE IGNORE character_spell SET spell = 33095 WHERE spell = 54084; +DELETE FROM character_spell WHERE spell = 54084; diff --git a/sql/updates/7078_01_mangos_spell_proc_event.sql b/sql/updates/7078_01_mangos_spell_proc_event.sql new file mode 100644 index 000000000..b5df2f7fa --- /dev/null +++ b/sql/updates/7078_01_mangos_spell_proc_event.sql @@ -0,0 +1,23 @@ +ALTER TABLE db_version CHANGE COLUMN required_7075_02_mangos_spell_learn_spell required_7078_01_mangos_spell_proc_event bit; + +-- (31871) Divine Purpose (Rank 1) +DELETE FROM `spell_proc_event` WHERE `entry` IN (31871); +INSERT INTO `spell_proc_event` VALUES (31871, 0x00, 10, 0x00000010, 0x00000000, 0x00000000, 0x00004000, 0x00000000, 0.000000, 0.000000, 0); + +-- (31872) Divine Purpose (Rank 2) +DELETE FROM `spell_proc_event` WHERE `entry` IN (31872); +INSERT INTO `spell_proc_event` VALUES (31872, 0x00, 10, 0x00000010, 0x00000000, 0x00000000, 0x00004000, 0x00000000, 0.000000, 0.000000, 0); + +-- (44394) Incanter's Absorption (Rank 1) +DELETE FROM `spell_proc_event` WHERE `entry` IN (44394); +INSERT INTO `spell_proc_event` VALUES (44394, 0x00, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000400, 0.000000, 0.000000, 0); + +-- (44395) Incanter's Absorption (Rank 2) +DELETE FROM `spell_proc_event` WHERE `entry` IN (44395); +INSERT INTO `spell_proc_event` VALUES (44395, 0x00, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000400, 0.000000, 0.000000, 0); + +-- (44396) Incanter's Absorption (Rank 3) +DELETE FROM `spell_proc_event` WHERE `entry` IN (44396); +INSERT INTO `spell_proc_event` VALUES (44396, 0x00, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000400, 0.000000, 0.000000, 0); + + \ No newline at end of file diff --git a/sql/updates/7092_01_mangos_player_xp_for_level.sql b/sql/updates/7092_01_mangos_player_xp_for_level.sql new file mode 100644 index 000000000..aa4fabd28 --- /dev/null +++ b/sql/updates/7092_01_mangos_player_xp_for_level.sql @@ -0,0 +1,93 @@ +ALTER TABLE db_version CHANGE COLUMN required_7078_01_mangos_spell_proc_event required_7092_01_mangos_player_xp_for_level bit; + +DROP TABLE IF EXISTS `player_xp_for_level`; +CREATE TABLE `player_xp_for_level` ( + `lvl` int(3) unsigned NOT NULL, + `xp_for_next_level` int(10) unsigned NOT NULL, + PRIMARY KEY (`lvl`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; + +-- +-- Dumping data for table `player_xp_for_level` +-- + +INSERT INTO `player_xp_for_level` VALUES +('1', '400'), +('2', '900'), +('3', '1400'), +('4', '2100'), +('5', '2800'), +('6', '3600'), +('7', '4500'), +('8', '5400'), +('9', '6500'), +('10', '7600'), +('11', '8700'), +('12', '9800'), +('13', '11000'), +('14', '12300'), +('15', '13600'), +('16', '15000'), +('17', '16400'), +('18', '17800'), +('19', '19300'), +('20', '20800'), +('21', '22400'), +('22', '24000'), +('23', '25500'), +('24', '27200'), +('25', '28900'), +('26', '30500'), +('27', '32200'), +('28', '33900'), +('29', '36300'), +('30', '38800'), +('31', '41600'), +('32', '44600'), +('33', '48000'), +('34', '51400'), +('35', '55000'), +('36', '58700'), +('37', '62400'), +('38', '66200'), +('39', '70200'), +('40', '74300'), +('41', '78500'), +('42', '82800'), +('43', '87100'), +('44', '91600'), +('45', '96300'), +('46', '101000'), +('47', '105800'), +('48', '110700'), +('49', '115700'), +('50', '120900'), +('51', '126100'), +('52', '131500'), +('53', '137000'), +('54', '142500'), +('55', '148200'), +('56', '154000'), +('57', '159900'), +('58', '165800'), +('59', '172000'), +('60', '290000'), +('61', '317000'), +('62', '349000'), +('63', '386000'), +('64', '428000'), +('65', '475000'), +('66', '527000'), +('67', '585000'), +('68', '648000'), +('69', '717000'), +('70', '1523800'), +('71', '1539600'), +('72', '1555700'), +('73', '1571800'), +('74', '1587900'), +('75', '1604200'), +('76', '1620700'), +('77', '1637400'), +('78', '1653900'), +('79', '1670800'); \ No newline at end of file diff --git a/sql/updates/7097_01_mangos_spell_proc_event.sql b/sql/updates/7097_01_mangos_spell_proc_event.sql new file mode 100644 index 000000000..abccb36c5 --- /dev/null +++ b/sql/updates/7097_01_mangos_spell_proc_event.sql @@ -0,0 +1,58 @@ +ALTER TABLE db_version CHANGE COLUMN required_7092_01_mangos_player_xp_for_level required_7097_01_mangos_spell_proc_event bit; + +-- (35100) Concussive Barrage (Rank 1) +DELETE FROM `spell_proc_event` WHERE `entry` IN (35100); +INSERT INTO `spell_proc_event` VALUES (35100, 0x00, 9, 0x00003001, 0x00000000, 0x00000000, 0x00010140, 0x00000000, 0.000000, 0.000000, 0); + +-- (35102) Concussive Barrage (Rank 2) +DELETE FROM `spell_proc_event` WHERE `entry` IN (35102); +INSERT INTO `spell_proc_event` VALUES (35102, 0x00, 9, 0x00003001, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 0); + +-- (35103) Concussive Barrage (Rank 3) +DELETE FROM `spell_proc_event` WHERE `entry` IN (35103); +INSERT INTO `spell_proc_event` VALUES (35103, 0x00, 9, 0x00003001, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 0); + +-- (16164) Elemental Focus () +DELETE FROM `spell_proc_event` WHERE `entry` IN (16164); +INSERT INTO `spell_proc_event` VALUES (16164, 0x00, 11, 0x901000C3, 0x00000000, 0x00000000, 0x00000000, 0x00000002, 0.000000, 0.000000, 0); + +-- (42770) Second Wind (Rank 2) +DELETE FROM `spell_proc_event` WHERE `entry` IN (42770); +INSERT INTO `spell_proc_event` VALUES (42770, 0x00, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00010000, 0.000000, 0.000000, 0); + +-- (47580) Pain and Suffering (Rank 1) +DELETE FROM `spell_proc_event` WHERE `entry` IN (47580); +INSERT INTO `spell_proc_event` VALUES (47580, 0x00, 6, 0x00000000, 0x00000000, 0x00000040, 0x00000000, 0x00010000, 0.000000, 0.000000, 0); + +-- (47581) Pain and Suffering (Rank 2) +DELETE FROM `spell_proc_event` WHERE `entry` IN (47581); +INSERT INTO `spell_proc_event` VALUES (47581, 0x00, 6, 0x00000000, 0x00000000, 0x00000040, 0x00000000, 0x00010000, 0.000000, 0.000000, 0); + +-- (47582) Pain and Suffering (Rank 3) +DELETE FROM `spell_proc_event` WHERE `entry` IN (47582); +INSERT INTO `spell_proc_event` VALUES (47582, 0x00, 6, 0x00000000, 0x00000000, 0x00000040, 0x00000000, 0x00010000, 0.000000, 0.000000, 0); + +-- (47535) Rapture (Rank 1) +DELETE FROM `spell_proc_event` WHERE `entry` IN (47535); +INSERT INTO `spell_proc_event` VALUES (47535, 0x00, 6, 0x00001800, 0x00800000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 0); + +-- (47536) Rapture (Rank 2) +DELETE FROM `spell_proc_event` WHERE `entry` IN (47536); +INSERT INTO `spell_proc_event` VALUES (47536, 0x00, 6, 0x00001800, 0x00800000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 0); + +-- (47537) Rapture (Rank 3) +DELETE FROM `spell_proc_event` WHERE `entry` IN (47537); +INSERT INTO `spell_proc_event` VALUES (47537, 0x00, 6, 0x00001800, 0x00800000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 0); + +-- (47538) Rapture (Rank 4) +DELETE FROM `spell_proc_event` WHERE `entry` IN (47538); +INSERT INTO `spell_proc_event` VALUES (47538, 0x00, 6, 0x00001800, 0x00800000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 0); + +-- (47539) Rapture (Rank 5) +DELETE FROM `spell_proc_event` WHERE `entry` IN (47539); +INSERT INTO `spell_proc_event` VALUES (47539, 0x00, 6, 0x00001800, 0x00800000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 0); + +-- (61257) Runic Power Back on Snare/Root (Rank 5) +DELETE FROM `spell_proc_event` WHERE `entry` IN (61257); +INSERT INTO `spell_proc_event` VALUES (61257, 0x00, 0, 0x00000000, 0x00000000, 0x00000000, 0x000202A8, 0x00010000, 0.000000, 0.000000, 0); + diff --git a/sql/updates/7100_01_characters_character_spell.sql b/sql/updates/7100_01_characters_character_spell.sql new file mode 100644 index 000000000..4d65b6c15 --- /dev/null +++ b/sql/updates/7100_01_characters_character_spell.sql @@ -0,0 +1,39 @@ +ALTER TABLE character_db_version CHANGE COLUMN required_7077_01_characters_character_spell required_7100_01_characters_character_spell bit; + +/* Warrior cleanup */ +DELETE FROM `character_spell` WHERE `spell` IN (1715,7372,7373); /* Hamstring old */ +DELETE FROM `character_spell` WHERE `spell` IN (72,17671,1672); /* Mortar Disturb old */ +DELETE FROM `character_spell` WHERE `spell` IN (7384,7887,11584,11586); /* Overpower old */ +DELETE FROM `character_spell` WHERE `spell`=23881; /* Bloodthirst old */ +DELETE FROM `character_spell` WHERE `spell` IN (6552,6554); /* Pummel old */ +DELETE FROM `character_spell` WHERE `spell` IN (694,7400,7402,20559,20560,25266); /* Mocking Blow old */ +/* Druid cleanup */ +DELETE FROM `character_spell` WHERE `spell`=22842; /* Frenzied Regeneration old */ +/* Hunter cleanup */ +DELETE FROM `character_spell` WHERE `spell`=14268; /* Wing Clip r1 old */ +DELETE FROM `character_spell` WHERE `spell`=14267; /* Wing Clip r2 old */ +/* Rogue */ +DELETE FROM `character_spell` WHERE `spell` IN (1766,1767,1768,1769,38768); /* Kick old */ +DELETE FROM `character_spell` WHERE `spell` IN (1776,1777,8629,11285,11286,38764);/* Gouge old */ +DELETE FROM `character_spell` WHERE `spell`=2842; /* Poisons old */ + +/* Hunter's training spells for pets */ +DELETE FROM `character_spell` WHERE `spell` IN (2949,2975,2976,2977,2980,2981,2982,3666,3667,4630,6327,6359,6362, + 7370,7832,7833,7834,7835,7871,7872,7873,7876,7877,7878,7879,7880,7881,7882,7883,7884,7885,7886,8318,8319,11764, + 11765,11768,11769,11772,11773,11776,11777,11781,11782,11783,11786,11787,17254,17262,17263,17264,17265,17266, + 17267,17268,17736,17753,17754,17755,17776,17855,17856,17857,17859,17860,19439,19444,19445,19446,19447,19481, + 19577,19648,19650,19661,19662,19663,19664,19737,19738,19739,20270,20312,20313,20314,20315,20316,20317,20318, + 20319,20320,20321,20322,20323,20324,20326,20327,20329,20377,20378,20379,20380,20381,20382,20383,20384,20385, + 20386,20387,20388,20389,20390,20391,20392,20393,20394,20395,20396,20397,20398,20399,20400,20401,20402,20403, + 20404,20405,20406,20407,20408,20426,20427,20428,20429,20430,20431,20432,20433,20434,20435,23100,23111,23112, + 23146,23149,23150,24424,24440,24441,24451,24454,24455,24463,24464,24475,24476,24477,24580,24581,24582,24584, + 24588,24589,24599,24607,24608,24609,24641,26065,26094,26184,26185,26186,26189,26190,26202,27347,27348,27349, + 27361,27366,27484,27485,27486,27487,27488,27489,27490,27491,27492,27493,27494,27495,27496,27497,27500,28343, + 33703,35299,35300,35302,35303,35304,35305,35306,35307,35308); +DELETE FROM `character_spell` WHERE `spell` IN (1853,14922,14923,14924,14925,14926,14927,27344); +DELETE FROM `character_spell` WHERE `spell` IN (27353,24516,24515,24514,24490); +DELETE FROM `character_spell` WHERE `spell` IN (27354,24513,24512,24511,24494,2119); +UPDATE IGNORE character_spell SET spell = 2108 WHERE spell = 3104; +DELETE FROM character_spell WHERE spell = 3104; +/* This cleanup character_action. This is like delete from character_action where type=0 and action not in character_spell for same player */ +DELETE FROM ca,cs USING `character_action` ca LEFT JOIN `character_spell` cs ON ca.`guid`=cs.`guid` AND ca.`action`=cs.`spell` WHERE ca.`type`=0 AND cs.`guid` IS NULL; diff --git a/sql/updates/7107_01_mangos_string.sql b/sql/updates/7107_01_mangos_string.sql new file mode 100644 index 000000000..bd4ee1ce6 --- /dev/null +++ b/sql/updates/7107_01_mangos_string.sql @@ -0,0 +1,7 @@ +ALTER TABLE db_version CHANGE COLUMN required_7097_01_mangos_spell_proc_event required_7107_01_mangos_string bit; + +DELETE FROM `mangos_string` WHERE `entry` IN (521,1109,1122); +INSERT INTO `mangos_string` VALUES +(521,'%d - |cffffffff|Hskill:%d|h[%s %s]|h|r %s %s',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1109,'%d - %s %s %s %s',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1122,'(%u/%u +perm %u +temp %u)',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL); diff --git a/sql/updates/7113_01_characters_character_achievement_progress.sql b/sql/updates/7113_01_characters_character_achievement_progress.sql new file mode 100644 index 000000000..6e38cd998 --- /dev/null +++ b/sql/updates/7113_01_characters_character_achievement_progress.sql @@ -0,0 +1,3 @@ +ALTER TABLE character_db_version CHANGE COLUMN required_7100_01_characters_character_spell required_7113_01_characters_character_achievement_progress bit; + +DELETE FROM character_achievement_progress WHERE counter=0; diff --git a/sql/updates/7118_01_mangos_skill_discovery_template.sql b/sql/updates/7118_01_mangos_skill_discovery_template.sql new file mode 100644 index 000000000..f854855e6 --- /dev/null +++ b/sql/updates/7118_01_mangos_skill_discovery_template.sql @@ -0,0 +1,6 @@ +ALTER TABLE db_version CHANGE COLUMN required_7107_01_mangos_string required_7118_01_mangos_skill_discovery_template bit; + +ALTER TABLE skill_discovery_template + DROP PRIMARY KEY, + ADD PRIMARY KEY (`spellId`,`reqSpell`), + ADD COLUMN reqClass tinyint(2) unsigned NOT NULL default '0' COMMENT 'class requirement' AFTER reqSpell; diff --git a/sql/updates/7133_01_mangos_skill_discovery_template.sql b/sql/updates/7133_01_mangos_skill_discovery_template.sql new file mode 100644 index 000000000..85653618c --- /dev/null +++ b/sql/updates/7133_01_mangos_skill_discovery_template.sql @@ -0,0 +1,5 @@ +ALTER TABLE db_version CHANGE COLUMN required_7118_01_mangos_skill_discovery_template required_7133_01_mangos_skill_discovery_template bit; + +ALTER TABLE skill_discovery_template + DROP `reqClass`, + ADD COLUMN `reqSkillValue` smallint(5) unsigned NOT NULL default '0' COMMENT 'skill points requirement' AFTER reqSpell; diff --git a/sql/updates/7133_02_mangos_spell_loot_template.sql b/sql/updates/7133_02_mangos_spell_loot_template.sql new file mode 100644 index 000000000..29b1681fb --- /dev/null +++ b/sql/updates/7133_02_mangos_spell_loot_template.sql @@ -0,0 +1,15 @@ +ALTER TABLE db_version CHANGE COLUMN required_7133_01_mangos_skill_discovery_template required_7133_02_mangos_spell_loot_template bit; + +DROP TABLE IF EXISTS `spell_loot_template`; +CREATE TABLE `spell_loot_template` ( + `entry` mediumint(8) unsigned NOT NULL default '0', + `item` mediumint(8) unsigned NOT NULL default '0', + `ChanceOrQuestChance` float NOT NULL default '100', + `groupid` tinyint(3) unsigned NOT NULL default '0', + `mincountOrRef` mediumint(9) NOT NULL default '1', + `maxcount` tinyint(3) unsigned NOT NULL default '1', + `lootcondition` tinyint(3) unsigned NOT NULL default '0', + `condition_value1` mediumint(8) unsigned NOT NULL default '0', + `condition_value2` mediumint(8) unsigned NOT NULL default '0', + PRIMARY KEY (`entry`,`item`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=FIXED COMMENT='Loot System'; diff --git a/sql/updates/Makefile.am b/sql/updates/Makefile.am index 33bc07947..f44216ebb 100644 --- a/sql/updates/Makefile.am +++ b/sql/updates/Makefile.am @@ -135,6 +135,16 @@ pkgdata_DATA = \ 7074_01_mangos_playercreateinfo_spell.sql \ 7075_01_characters_character_spell.sql \ 7075_02_mangos_spell_learn_spell.sql \ + 7077_01_characters_character_spell.sql \ + 7078_01_mangos_spell_proc_event.sql \ + 7092_01_mangos_player_xp_for_level.sql \ + 7097_01_mangos_spell_proc_event.sql \ + 7100_01_characters_character_spell.sql \ + 7107_01_mangos_string.sql \ + 7113_01_characters_character_achievement_progress.sql \ + 7118_01_mangos_skill_discovery_template.sql \ + 7133_01_mangos_skill_discovery_template.sql \ + 7133_02_mangos_spell_loot_template.sql \ README ## Additional files to include when running 'make dist' @@ -250,4 +260,14 @@ EXTRA_DIST = \ 7074_01_mangos_playercreateinfo_spell.sql \ 7075_01_characters_character_spell.sql \ 7075_02_mangos_spell_learn_spell.sql \ + 7077_01_characters_character_spell.sql \ + 7078_01_mangos_spell_proc_event.sql \ + 7092_01_mangos_player_xp_for_level.sql \ + 7097_01_mangos_spell_proc_event.sql \ + 7100_01_characters_character_spell.sql \ + 7107_01_mangos_string.sql \ + 7113_01_characters_character_achievement_progress.sql \ + 7118_01_mangos_skill_discovery_template.sql \ + 7133_01_mangos_skill_discovery_template.sql \ + 7133_02_mangos_spell_loot_template.sql \ README diff --git a/src/framework/GameSystem/NGrid.h b/src/framework/GameSystem/NGrid.h index b93e5d9a9..0271bd11a 100644 --- a/src/framework/GameSystem/NGrid.h +++ b/src/framework/GameSystem/NGrid.h @@ -74,12 +74,12 @@ class MANGOS_DLL_DECL NGrid const GridType& operator()(unsigned short x, unsigned short y) const { return i_cells[x][y]; } GridType& operator()(unsigned short x, unsigned short y) { return i_cells[x][y]; } - inline const uint32& GetGridId(void) const { return i_gridId; } - inline void SetGridId(const uint32 id) const { i_gridId = id; } - inline grid_state_t GetGridState(void) const { return i_cellstate; } - inline void SetGridState(grid_state_t s) { i_cellstate = s; } - inline int32 getX() const { return i_x; } - inline int32 getY() const { return i_y; } + const uint32& GetGridId(void) const { return i_gridId; } + void SetGridId(const uint32 id) const { i_gridId = id; } + grid_state_t GetGridState(void) const { return i_cellstate; } + void SetGridState(grid_state_t s) { i_cellstate = s; } + int32 getX() const { return i_x; } + int32 getY() const { return i_y; } void link(GridRefManager >* pTo) { diff --git a/src/framework/Policies/ObjectLifeTime.h b/src/framework/Policies/ObjectLifeTime.h index dab37a98c..82bf4ea8e 100644 --- a/src/framework/Policies/ObjectLifeTime.h +++ b/src/framework/Policies/ObjectLifeTime.h @@ -32,7 +32,7 @@ namespace MaNGOS class MANGOS_DLL_DECL ObjectLifeTime { public: - inline static void ScheduleCall(void (*destroyer)() ) + static void ScheduleCall(void (*destroyer)() ) { at_exit( destroyer ); } @@ -42,7 +42,7 @@ namespace MaNGOS }; template - inline void ObjectLifeTime::OnDeadReference(void)// We don't handle Dead Reference for now + void ObjectLifeTime::OnDeadReference(void) // We don't handle Dead Reference for now { throw std::runtime_error("Dead Reference"); } diff --git a/src/framework/Utilities/LinkedReference/Reference.h b/src/framework/Utilities/LinkedReference/Reference.h index d74723a42..42e4b0484 100644 --- a/src/framework/Utilities/LinkedReference/Reference.h +++ b/src/framework/Utilities/LinkedReference/Reference.h @@ -42,7 +42,7 @@ template class Reference : public LinkedListElement virtual ~Reference() {} // Create new link - inline void link(TO* toObj, FROM* fromObj) + void link(TO* toObj, FROM* fromObj) { assert(fromObj); // fromObj MUST not be NULL if(isValid()) @@ -57,16 +57,16 @@ template class Reference : public LinkedListElement // We don't need the reference anymore. Call comes from the refFrom object // Tell our refTo object, that the link is cut - inline void unlink() { targetObjectDestroyLink(); delink(); iRefTo = NULL; iRefFrom = NULL; } + void unlink() { targetObjectDestroyLink(); delink(); iRefTo = NULL; iRefFrom = NULL; } // Link is invalid due to destruction of referenced target object. Call comes from the refTo object // Tell our refFrom object, that the link is cut - inline void invalidate() // the iRefFrom MUST remain!! + void invalidate() // the iRefFrom MUST remain!! { sourceObjectDestroyLink(); delink(); iRefTo = NULL; } - inline bool isValid() const // Only check the iRefTo + bool isValid() const // Only check the iRefTo { return iRefTo != NULL; } @@ -81,10 +81,10 @@ template class Reference : public LinkedListElement Reference * nocheck_prev() { return((Reference *) LinkedListElement::nocheck_prev()); } Reference const * nocheck_prev() const { return((Reference const *) LinkedListElement::nocheck_prev()); } - inline TO* operator ->() const { return iRefTo; } - inline TO* getTarget() const { return iRefTo; } + TO* operator ->() const { return iRefTo; } + TO* getTarget() const { return iRefTo; } - inline FROM* getSource() const { return iRefFrom; } + FROM* getSource() const { return iRefFrom; } }; //===================================================== diff --git a/src/game/AchievementMgr.cpp b/src/game/AchievementMgr.cpp index fb6684892..2ae665c16 100644 --- a/src/game/AchievementMgr.cpp +++ b/src/game/AchievementMgr.cpp @@ -141,7 +141,8 @@ void AchievementMgr::SaveToDB() if(!m_criteriaProgress.empty()) { /// prepare deleting and insert - bool need_execute = false; + bool need_execute_del = false; + bool need_execute_ins = false; std::ostringstream ssdel; std::ostringstream ssins; for(CriteriaProgressMap::iterator iter = m_criteriaProgress.begin(); iter!=m_criteriaProgress.end(); ++iter) @@ -149,36 +150,53 @@ void AchievementMgr::SaveToDB() if(!iter->second.changed) continue; - /// first new/changed record prefix - if(!need_execute) + // deleted data (including 0 progress state) { - ssdel << "DELETE FROM character_achievement_progress WHERE guid = " << GetPlayer()->GetGUIDLow() << " AND criteria IN ("; - ssins << "INSERT INTO character_achievement_progress (guid, criteria, counter, date) VALUES "; - need_execute = true; - } - /// next new/changed record prefix - else - { - ssdel << ", "; - ssins << ", "; + /// first new/changed record prefix (for any counter value) + if(!need_execute_del) + { + ssdel << "DELETE FROM character_achievement_progress WHERE guid = " << GetPlayer()->GetGUIDLow() << " AND criteria IN ("; + need_execute_del = true; + } + /// next new/changed record prefix + else + ssdel << ", "; + + // new/changed record data + ssdel << iter->first; } - // new/changed record data - ssdel << iter->first; - ssins << "(" << GetPlayer()->GetGUIDLow() << ", " << iter->first << ", " << iter->second.counter << ", " << iter->second.date << ")"; + // store data only for real progress + if(iter->second.counter != 0) + { + /// first new/changed record prefix + if(!need_execute_ins) + { + ssins << "INSERT INTO character_achievement_progress (guid, criteria, counter, date) VALUES "; + need_execute_ins = true; + } + /// next new/changed record prefix + else + ssins << ", "; - /// mark as saved in db + // new/changed record data + ssins << "(" << GetPlayer()->GetGUIDLow() << ", " << iter->first << ", " << iter->second.counter << ", " << iter->second.date << ")"; + } + + /// mark as updated in db iter->second.changed = false; } - if(need_execute) + if(need_execute_del) // DELETE ... IN (.... _)_ ssdel << ")"; - if(need_execute) + if(need_execute_del || need_execute_ins) { CharacterDatabase.BeginTransaction (); - CharacterDatabase.Execute( ssdel.str().c_str() ); - CharacterDatabase.Execute( ssins.str().c_str() ); + if(need_execute_del) + CharacterDatabase.Execute( ssdel.str().c_str() ); + if(need_execute_ins) + CharacterDatabase.Execute( ssins.str().c_str() ); CharacterDatabase.CommitTransaction (); } } @@ -386,6 +404,10 @@ void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, ui if(GetPlayer()->HasSpell(achievementCriteria->learn_spell.spellID)) SetCriteriaProgress(achievementCriteria, 1); break; + case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_ACHIEVEMENT: + if(m_completedAchievements.find(achievementCriteria->complete_achievement.linkedAchievement) != m_completedAchievements.end()) + SetCriteriaProgress(achievementCriteria, 1); + break; case ACHIEVEMENT_CRITERIA_TYPE_DEATH_AT_MAP: // AchievementMgr::UpdateAchievementCriteria might also be called on login - skip in this case if(!miscvalue1) @@ -628,7 +650,7 @@ bool AchievementMgr::IsCompletedCriteria(AchievementCriteriaEntry const* achieve case ACHIEVEMENT_CRITERIA_TYPE_KILL_CREATURE: return progress->counter >= achievementCriteria->kill_creature.creatureCount; case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_ACHIEVEMENT: - return m_completedAchievements.find(achievementCriteria->complete_achievement.linkedAchievement) != m_completedAchievements.end(); + return progress->counter >= 1; case ACHIEVEMENT_CRITERIA_TYPE_REACH_SKILL_LEVEL: return progress->counter >= achievementCriteria->reach_skill_level.skillLevel; case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_QUEST_COUNT: @@ -729,6 +751,10 @@ void AchievementMgr::SetCriteriaProgress(AchievementCriteriaEntry const* entry, if(iter == m_criteriaProgress.end()) { + // not create record for 0 counter + if(newValue == 0) + return; + progress = &m_criteriaProgress[entry->ID]; progress->counter = newValue; progress->date = time(NULL); @@ -738,8 +764,11 @@ void AchievementMgr::SetCriteriaProgress(AchievementCriteriaEntry const* entry, progress = &iter->second; if(relative) newValue += progress->counter; + + // not update (not mark as changed) if counter will have same value if(progress->counter == newValue) return; + progress->counter = newValue; } diff --git a/src/game/AuctionHouseObject.h b/src/game/AuctionHouseObject.h index 077991e8c..927063eb6 100644 --- a/src/game/AuctionHouseObject.h +++ b/src/game/AuctionHouseObject.h @@ -82,20 +82,12 @@ class AuctionHouseObject AuctionEntry* GetAuction(uint32 id) const { AuctionEntryMap::const_iterator itr = AuctionsMap.find( id ); - if( itr != AuctionsMap.end() ) - return itr->second; - return NULL; + return itr != AuctionsMap.end() ? itr->second : NULL; } bool RemoveAuction(uint32 id) { - AuctionEntryMap::iterator i = AuctionsMap.find(id); - if (i == AuctionsMap.end()) - { - return false; - } - AuctionsMap.erase(i); - return true; + return AuctionsMap.erase(id) ? true : false; } private: diff --git a/src/game/BattleGround.cpp b/src/game/BattleGround.cpp index 24b64ad22..1e2e42f4a 100644 --- a/src/game/BattleGround.cpp +++ b/src/game/BattleGround.cpp @@ -116,7 +116,7 @@ BattleGround::~BattleGround() this->RemoveFromBGFreeSlotQueue(); } -void BattleGround::Update(time_t diff) +void BattleGround::Update(uint32 diff) { if(!GetPlayersSize() && !GetRemovedPlayersSize() && !GetReviveQueueSize()) //BG is empty @@ -552,7 +552,7 @@ void BattleGround::EndBattleGround(uint32 winner) sBattleGroundMgr.BuildPvpLogDataPacket(&data, this); plr->GetSession()->SendPacket(&data); - uint32 bgQueueTypeId = sBattleGroundMgr.BGQueueTypeId(GetTypeID(), GetArenaType()); + uint32 bgQueueTypeId = BattleGroundMgr::BGQueueTypeId(GetTypeID(), GetArenaType()); sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, this, plr->GetTeam(), plr->GetBattleGroundQueueIndex(bgQueueTypeId), STATUS_IN_PROGRESS, TIME_TO_AUTOREMOVE, GetStartTime()); plr->GetSession()->SendPacket(&data); plr->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_BATTLEGROUND, 1); @@ -573,7 +573,7 @@ void BattleGround::EndBattleGround(uint32 winner) } // inform invited players about the removal - sBattleGroundMgr.m_BattleGroundQueues[sBattleGroundMgr.BGQueueTypeId(GetTypeID(), GetArenaType())].BGEndedRemoveInvites(this); + sBattleGroundMgr.m_BattleGroundQueues[BattleGroundMgr::BGQueueTypeId(GetTypeID(), GetArenaType())].BGEndedRemoveInvites(this); if(Source) { @@ -769,7 +769,7 @@ void BattleGround::RemovePlayerAtLeave(uint64 guid, bool Transport, bool SendPac if(!team) team = plr->GetTeam(); uint32 bgTypeId = GetTypeID(); - uint32 bgQueueTypeId = sBattleGroundMgr.BGQueueTypeId(GetTypeID(), GetArenaType()); + uint32 bgQueueTypeId = BattleGroundMgr::BGQueueTypeId(GetTypeID(), GetArenaType()); // if arena, remove the specific arena auras if(isArena()) { @@ -1403,7 +1403,7 @@ void BattleGround::EndNow() SetStatus(STATUS_WAIT_LEAVE); SetEndTime(TIME_TO_AUTOREMOVE); // inform invited players about the removal - sBattleGroundMgr.m_BattleGroundQueues[sBattleGroundMgr.BGQueueTypeId(GetTypeID(), GetArenaType())].BGEndedRemoveInvites(this); + sBattleGroundMgr.m_BattleGroundQueues[BattleGroundMgr::BGQueueTypeId(GetTypeID(), GetArenaType())].BGEndedRemoveInvites(this); } // Battleground messages are localized using the dbc lang, they are not client language dependent diff --git a/src/game/BattleGround.h b/src/game/BattleGround.h index 6727c1a97..1e03c12cb 100644 --- a/src/game/BattleGround.h +++ b/src/game/BattleGround.h @@ -254,7 +254,7 @@ class BattleGround BattleGround(); /*BattleGround(const BattleGround& bg);*/ virtual ~BattleGround(); - virtual void Update(time_t diff); // must be implemented in BG subclass of BG specific update code, but must in begginning call parent version + virtual void Update(uint32 diff); // must be implemented in BG subclass of BG specific update code, but must in begginning call parent version virtual bool SetupBattleGround() // must be implemented in BG subclass { return true; diff --git a/src/game/BattleGroundAA.cpp b/src/game/BattleGroundAA.cpp index cc2404614..fcf9bd4ce 100644 --- a/src/game/BattleGroundAA.cpp +++ b/src/game/BattleGroundAA.cpp @@ -30,7 +30,7 @@ BattleGroundAA::~BattleGroundAA() } -void BattleGroundAA::Update(time_t diff) +void BattleGroundAA::Update(uint32 diff) { BattleGround::Update(diff); } diff --git a/src/game/BattleGroundAA.h b/src/game/BattleGroundAA.h index 767e4eb55..b144acae3 100644 --- a/src/game/BattleGroundAA.h +++ b/src/game/BattleGroundAA.h @@ -35,7 +35,7 @@ class BattleGroundAA : public BattleGround public: BattleGroundAA(); ~BattleGroundAA(); - void Update(time_t diff); + void Update(uint32 diff); /* inherited from BattlegroundClass */ virtual void AddPlayer(Player *plr); diff --git a/src/game/BattleGroundAB.cpp b/src/game/BattleGroundAB.cpp index 0a5186937..45421f908 100644 --- a/src/game/BattleGroundAB.cpp +++ b/src/game/BattleGroundAB.cpp @@ -38,7 +38,7 @@ BattleGroundAB::~BattleGroundAB() { } -void BattleGroundAB::Update(time_t diff) +void BattleGroundAB::Update(uint32 diff) { BattleGround::Update(diff); diff --git a/src/game/BattleGroundAB.h b/src/game/BattleGroundAB.h index 97615dc1c..e76f35209 100644 --- a/src/game/BattleGroundAB.h +++ b/src/game/BattleGroundAB.h @@ -236,7 +236,7 @@ class BattleGroundAB : public BattleGround BattleGroundAB(); ~BattleGroundAB(); - void Update(time_t diff); + void Update(uint32 diff); void AddPlayer(Player *plr); void RemovePlayer(Player *plr,uint64 guid); void HandleAreaTrigger(Player *Source, uint32 Trigger); diff --git a/src/game/BattleGroundAV.cpp b/src/game/BattleGroundAV.cpp index 99866f3f8..c444bcbb2 100644 --- a/src/game/BattleGroundAV.cpp +++ b/src/game/BattleGroundAV.cpp @@ -34,7 +34,7 @@ BattleGroundAV::~BattleGroundAV() } -void BattleGroundAV::Update(time_t diff) +void BattleGroundAV::Update(uint32 diff) { BattleGround::Update(diff); } diff --git a/src/game/BattleGroundAV.h b/src/game/BattleGroundAV.h index c77a6af88..c2e12a872 100644 --- a/src/game/BattleGroundAV.h +++ b/src/game/BattleGroundAV.h @@ -42,7 +42,7 @@ class BattleGroundAV : public BattleGround public: BattleGroundAV(); ~BattleGroundAV(); - void Update(time_t diff); + void Update(uint32 diff); /* inherited from BattlegroundClass */ virtual void AddPlayer(Player *plr); diff --git a/src/game/BattleGroundBE.cpp b/src/game/BattleGroundBE.cpp index cb38b0b80..cae899421 100644 --- a/src/game/BattleGroundBE.cpp +++ b/src/game/BattleGroundBE.cpp @@ -35,7 +35,7 @@ BattleGroundBE::~BattleGroundBE() } -void BattleGroundBE::Update(time_t diff) +void BattleGroundBE::Update(uint32 diff) { BattleGround::Update(diff); diff --git a/src/game/BattleGroundBE.h b/src/game/BattleGroundBE.h index c66d1b1b9..4e5663d03 100644 --- a/src/game/BattleGroundBE.h +++ b/src/game/BattleGroundBE.h @@ -55,7 +55,7 @@ class BattleGroundBE : public BattleGround public: BattleGroundBE(); ~BattleGroundBE(); - void Update(time_t diff); + void Update(uint32 diff); /* inherited from BattlegroundClass */ virtual void AddPlayer(Player *plr); diff --git a/src/game/BattleGroundDS.cpp b/src/game/BattleGroundDS.cpp index 276c0c84c..825a52967 100644 --- a/src/game/BattleGroundDS.cpp +++ b/src/game/BattleGroundDS.cpp @@ -30,7 +30,7 @@ BattleGroundDS::~BattleGroundDS() } -void BattleGroundDS::Update(time_t diff) +void BattleGroundDS::Update(uint32 diff) { BattleGround::Update(diff); } diff --git a/src/game/BattleGroundDS.h b/src/game/BattleGroundDS.h index afcb8f092..7f9de8ca7 100644 --- a/src/game/BattleGroundDS.h +++ b/src/game/BattleGroundDS.h @@ -35,7 +35,7 @@ class BattleGroundDS : public BattleGround public: BattleGroundDS(); ~BattleGroundDS(); - void Update(time_t diff); + void Update(uint32 diff); /* inherited from BattlegroundClass */ virtual void AddPlayer(Player *plr); diff --git a/src/game/BattleGroundEY.cpp b/src/game/BattleGroundEY.cpp index 7adca00f4..dcfc38337 100644 --- a/src/game/BattleGroundEY.cpp +++ b/src/game/BattleGroundEY.cpp @@ -42,7 +42,7 @@ BattleGroundEY::~BattleGroundEY() { } -void BattleGroundEY::Update(time_t diff) +void BattleGroundEY::Update(uint32 diff) { BattleGround::Update(diff); // after bg start we get there (once) diff --git a/src/game/BattleGroundEY.h b/src/game/BattleGroundEY.h index 8e19472b2..38291313d 100644 --- a/src/game/BattleGroundEY.h +++ b/src/game/BattleGroundEY.h @@ -298,7 +298,7 @@ class BattleGroundEY : public BattleGround public: BattleGroundEY(); ~BattleGroundEY(); - void Update(time_t diff); + void Update(uint32 diff); /* inherited from BattlegroundClass */ virtual void AddPlayer(Player *plr); diff --git a/src/game/BattleGroundHandler.cpp b/src/game/BattleGroundHandler.cpp index 323ec1a73..0158cd36b 100644 --- a/src/game/BattleGroundHandler.cpp +++ b/src/game/BattleGroundHandler.cpp @@ -94,7 +94,7 @@ void WorldSession::HandleBattleGroundJoinOpcode( WorldPacket & recv_data ) sLog.outDebug( "WORLD: Recvd CMSG_BATTLEMASTER_JOIN Message from: " I64FMT, guid); // can do this, since it's battleground, not arena - uint32 bgQueueTypeId = sBattleGroundMgr.BGQueueTypeId(bgTypeId, 0); + uint32 bgQueueTypeId = BattleGroundMgr::BGQueueTypeId(bgTypeId, 0); // ignore if player is already in BG if(_player->InBattleGround()) @@ -368,7 +368,7 @@ void WorldSession::HandleBattleGroundPlayerPortOpcode( WorldPacket &recv_data ) uint32 bgQueueTypeId = 0; // get the bg what we were invited to BattleGroundQueue::QueuedPlayersMap::iterator itrPlayerStatus; - bgQueueTypeId = sBattleGroundMgr.BGQueueTypeId(bgTypeId,type); + bgQueueTypeId = BattleGroundMgr::BGQueueTypeId(bgTypeId,type); itrPlayerStatus = sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].m_QueuedPlayers[_player->GetBattleGroundQueueIdFromLevel()].find(_player->GetGUID()); if(itrPlayerStatus == sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].m_QueuedPlayers[_player->GetBattleGroundQueueIdFromLevel()].end()) @@ -529,7 +529,7 @@ void WorldSession::HandleBattlefieldStatusOpcode( WorldPacket & /*recv_data*/ ) BattleGround *bg = _player->GetBattleGround(); if(bg) { - uint32 bgQueueTypeId = sBattleGroundMgr.BGQueueTypeId(bg->GetTypeID(), bg->GetArenaType()); + uint32 bgQueueTypeId = BattleGroundMgr::BGQueueTypeId(bg->GetTypeID(), bg->GetArenaType()); uint32 queueSlot = _player->GetBattleGroundQueueIndex(bgQueueTypeId); if((bg->GetStatus() <= STATUS_IN_PROGRESS)) { @@ -539,7 +539,7 @@ void WorldSession::HandleBattlefieldStatusOpcode( WorldPacket & /*recv_data*/ ) for (uint32 i = 0; i < PLAYER_MAX_BATTLEGROUND_QUEUES; i++) { uint32 queue_id = _player->GetBattleGroundQueueId(i); // battlegroundqueueid stores the type id, not the instance id, so this is definitely wrong - uint8 arenatype = sBattleGroundMgr.BGArenaType(queue_id); + uint8 arenatype = BattleGroundMgr::BGArenaType(queue_id); uint8 isRated = 0; if (i == queueSlot || !queue_id) // we need to get the instance ids continue; @@ -551,7 +551,7 @@ void WorldSession::HandleBattlefieldStatusOpcode( WorldPacket & /*recv_data*/ ) arenatype = itrPlayerStatus->second.GroupInfo->ArenaType; isRated = itrPlayerStatus->second.GroupInfo->IsRated; } - BattleGround *bg2 = sBattleGroundMgr.GetBattleGroundTemplate(sBattleGroundMgr.BGTemplateId(queue_id)); // try this + BattleGround *bg2 = sBattleGroundMgr.GetBattleGroundTemplate(BattleGroundMgr::BGTemplateId(queue_id)); // try this if(bg2) { //in this call is small bug, this call should be filled by player's waiting time in queue @@ -570,8 +570,8 @@ void WorldSession::HandleBattlefieldStatusOpcode( WorldPacket & /*recv_data*/ ) uint32 queue_id = _player->GetBattleGroundQueueId(i); if(!queue_id) continue; - uint32 bgTypeId = sBattleGroundMgr.BGTemplateId(queue_id); - uint8 arenatype = sBattleGroundMgr.BGArenaType(queue_id); + uint32 bgTypeId = BattleGroundMgr::BGTemplateId(queue_id); + uint8 arenatype = BattleGroundMgr::BGArenaType(queue_id); uint8 isRated = 0; BattleGround *bg = sBattleGroundMgr.GetBattleGroundTemplate(bgTypeId); BattleGroundQueue::QueuedPlayersMap::iterator itrPlayerStatus = sBattleGroundMgr.m_BattleGroundQueues[queue_id].m_QueuedPlayers[_player->GetBattleGroundQueueIdFromLevel()].find(_player->GetGUID()); @@ -699,7 +699,7 @@ void WorldSession::HandleBattleGroundArenaJoin( WorldPacket & recv_data ) } uint8 bgTypeId = bg->GetTypeID(); - uint32 bgQueueTypeId = sBattleGroundMgr.BGQueueTypeId(bgTypeId, arenatype); + uint32 bgQueueTypeId = BattleGroundMgr::BGQueueTypeId(bgTypeId, arenatype); // check queueing conditions if(!asGroup) diff --git a/src/game/BattleGroundMgr.cpp b/src/game/BattleGroundMgr.cpp index fe97ecca3..66c03df3b 100644 --- a/src/game/BattleGroundMgr.cpp +++ b/src/game/BattleGroundMgr.cpp @@ -37,7 +37,6 @@ #include "MapInstanced.h" #include "ObjectMgr.h" #include "ProgressBar.h" -#include "World.h" #include "Chat.h" #include "ArenaTeam.h" @@ -246,7 +245,7 @@ void BattleGroundQueue::AddPlayer(Player *plr, GroupQueueInfo *ginfo) ginfo->Players[plr->GetGUID()] = &info; } -void BattleGroundQueue::RemovePlayer(uint64 guid, bool decreaseInvitedCount) +void BattleGroundQueue::RemovePlayer(const uint64& guid, bool decreaseInvitedCount) { Player *plr = objmgr.GetPlayer(guid); @@ -349,7 +348,7 @@ void BattleGroundQueue::RemovePlayer(uint64 guid, bool decreaseInvitedCount) if(Player *plr2 = objmgr.GetPlayer(group->Players.begin()->first)) { BattleGround * bg = sBattleGroundMgr.GetBattleGroundTemplate(group->BgTypeId); - uint32 bgQueueTypeId = sBattleGroundMgr.BGQueueTypeId(group->BgTypeId,group->ArenaType); + uint32 bgQueueTypeId = BattleGroundMgr::BGQueueTypeId(group->BgTypeId,group->ArenaType); uint32 queueSlot = plr2->GetBattleGroundQueueIndex(bgQueueTypeId); plr2->RemoveBattleGroundQueueId(bgQueueTypeId); // must be called this way, because if you move this call to queue->removeplayer, it causes bugs WorldPacket data; @@ -362,7 +361,7 @@ void BattleGroundQueue::RemovePlayer(uint64 guid, bool decreaseInvitedCount) } } -void BattleGroundQueue::AnnounceWorld(GroupQueueInfo *ginfo, uint64 playerGUID, bool isAddedToQueue) +void BattleGroundQueue::AnnounceWorld(GroupQueueInfo *ginfo, const uint64& playerGUID, bool isAddedToQueue) { if(ginfo->ArenaType) //if Arena @@ -452,7 +451,7 @@ bool BattleGroundQueue::InviteGroupToBG(GroupQueueInfo * ginfo, BattleGround * b // not yet invited // set invitation ginfo->IsInvitedToBGInstanceGUID = bg->GetInstanceID(); - uint32 bgQueueTypeId = sBattleGroundMgr.BGQueueTypeId(bg->GetTypeID(), bg->GetArenaType()); + uint32 bgQueueTypeId = BattleGroundMgr::BGQueueTypeId(bg->GetTypeID(), bg->GetArenaType()); // loop through the players for(std::map::iterator itr = ginfo->Players.begin(); itr != ginfo->Players.end(); ++itr) { @@ -547,7 +546,7 @@ void BattleGroundQueue::BGEndedRemoveInvites(BattleGround *bg) { uint32 queue_id = bg->GetQueueType(); uint32 bgInstanceId = bg->GetInstanceID(); - uint32 bgQueueTypeId = sBattleGroundMgr.BGQueueTypeId(bg->GetTypeID(), bg->GetArenaType()); + uint32 bgQueueTypeId = BattleGroundMgr::BGQueueTypeId(bg->GetTypeID(), bg->GetArenaType()); QueuedGroupsList::iterator itr, next; for(itr = m_QueuedGroups[queue_id].begin(); itr != m_QueuedGroups[queue_id].end(); itr = next) { @@ -617,7 +616,7 @@ void BattleGroundQueue::Update(uint32 bgTypeId, uint32 queue_id, uint8 arenatype if (m_QueuedGroups[queue_id].empty()) return; - uint32 bgQueueTypeId = sBattleGroundMgr.BGQueueTypeId(bgTypeId, arenatype); + uint32 bgQueueTypeId = BattleGroundMgr::BGQueueTypeId(bgTypeId, arenatype); //battleground with free slot for player should be always the last in this queue BGFreeSlotQueueType::iterator itr, next; @@ -995,7 +994,7 @@ bool BGQueueInviteEvent::Execute(uint64 /*e_time*/, uint32 /*p_time*/) uint32 queueSlot = plr->GetBattleGroundQueueIndex(bg->GetTypeID()); if (queueSlot < PLAYER_MAX_BATTLEGROUND_QUEUES) // player is in queue { - uint32 bgQueueTypeId = sBattleGroundMgr.BGQueueTypeId(bg->GetTypeID(), bg->GetArenaType()); + uint32 bgQueueTypeId = BattleGroundMgr::BGQueueTypeId(bg->GetTypeID(), bg->GetArenaType()); uint32 queueSlot = plr->GetBattleGroundQueueIndex(bgQueueTypeId); if (queueSlot < PLAYER_MAX_BATTLEGROUND_QUEUES) // player is in queue { @@ -1032,7 +1031,7 @@ bool BGQueueRemoveEvent::Execute(uint64 /*e_time*/, uint32 /*p_time*/) sLog.outDebug("Battleground: removing player %u from bg queue for instance %u because of not pressing enter battle in time.",plr->GetGUIDLow(),m_BgInstanceGUID); - uint32 bgQueueTypeId = sBattleGroundMgr.BGQueueTypeId(bg->GetTypeID(), bg->GetArenaType()); + uint32 bgQueueTypeId = BattleGroundMgr::BGQueueTypeId(bg->GetTypeID(), bg->GetArenaType()); uint32 queueSlot = plr->GetBattleGroundQueueIndex(bgQueueTypeId); if (queueSlot < PLAYER_MAX_BATTLEGROUND_QUEUES) // player is in queue { @@ -1075,16 +1074,10 @@ void BGQueueRemoveEvent::Abort(uint64 /*e_time*/) /*** BATTLEGROUND MANAGER ***/ /*********************************************************/ -BattleGroundMgr::BattleGroundMgr() +BattleGroundMgr::BattleGroundMgr() : m_AutoDistributionTimeChecker(0), m_ArenaTesting(false) { m_BattleGrounds.clear(); - m_AutoDistributePoints = (bool)sWorld.getConfig(CONFIG_ARENA_AUTO_DISTRIBUTE_POINTS); - m_MaxRatingDifference = sWorld.getConfig(CONFIG_ARENA_MAX_RATING_DIFFERENCE); - m_RatingDiscardTimer = sWorld.getConfig(CONFIG_ARENA_RATING_DISCARD_TIMER); - m_PrematureFinishTimer = sWorld.getConfig(CONFIG_BATTLEGROUND_PREMATURE_FINISH_TIMER); - m_NextRatingDiscardUpdate = m_RatingDiscardTimer; - m_AutoDistributionTimeChecker = 0; - m_ArenaTesting = false; + m_NextRatingDiscardUpdate = sWorld.getConfig(CONFIG_ARENA_RATING_DISCARD_TIMER); } BattleGroundMgr::~BattleGroundMgr() @@ -1102,7 +1095,7 @@ BattleGroundMgr::~BattleGroundMgr() } // used to update running battlegrounds, and delete finished ones -void BattleGroundMgr::Update(time_t diff) +void BattleGroundMgr::Update(uint32 diff) { BattleGroundSet::iterator itr, next; for(itr = m_BattleGrounds.begin(); itr != m_BattleGrounds.end(); itr = next) @@ -1120,7 +1113,7 @@ void BattleGroundMgr::Update(time_t diff) } } // if rating difference counts, maybe force-update queues - if(m_MaxRatingDifference) + if(sWorld.getConfig(CONFIG_ARENA_MAX_RATING_DIFFERENCE)) { // it's time to force update if(m_NextRatingDiscardUpdate < diff) @@ -1129,12 +1122,12 @@ void BattleGroundMgr::Update(time_t diff) m_BattleGroundQueues[BATTLEGROUND_QUEUE_2v2].Update(BATTLEGROUND_AA,6,ARENA_TYPE_2v2,true,0); m_BattleGroundQueues[BATTLEGROUND_QUEUE_3v3].Update(BATTLEGROUND_AA,6,ARENA_TYPE_3v3,true,0); m_BattleGroundQueues[BATTLEGROUND_QUEUE_5v5].Update(BATTLEGROUND_AA,6,ARENA_TYPE_5v5,true,0); - m_NextRatingDiscardUpdate = m_RatingDiscardTimer; + m_NextRatingDiscardUpdate = sWorld.getConfig(CONFIG_ARENA_RATING_DISCARD_TIMER); } else m_NextRatingDiscardUpdate -= diff; } - if(m_AutoDistributePoints) + if(sWorld.getConfig(CONFIG_ARENA_AUTO_DISTRIBUTE_POINTS)) { if(m_AutoDistributionTimeChecker < diff) { @@ -1692,7 +1685,7 @@ void BattleGroundMgr::CreateInitialBattleGrounds() void BattleGroundMgr::InitAutomaticArenaPointDistribution() { - if(m_AutoDistributePoints) + if(sWorld.getConfig(CONFIG_ARENA_AUTO_DISTRIBUTE_POINTS)) { sLog.outDebug("Initializing Automatic Arena Point Distribution"); QueryResult * result = CharacterDatabase.Query("SELECT NextArenaPointDistributionTime FROM saved_variables"); @@ -1761,7 +1754,7 @@ void BattleGroundMgr::DistributeArenaPoints() sWorld.SendGlobalText("Done flushing Arena points.", NULL); } -void BattleGroundMgr::BuildBattleGroundListPacket(WorldPacket *data, uint64 guid, Player* plr, uint32 bgTypeId) +void BattleGroundMgr::BuildBattleGroundListPacket(WorldPacket *data, const uint64& guid, Player* plr, uint32 bgTypeId) { uint32 PlayerLevel = 10; @@ -1817,7 +1810,7 @@ void BattleGroundMgr::SendToBattleGround(Player *pl, uint32 instanceId) } } -void BattleGroundMgr::SendAreaSpiritHealerQueryOpcode(Player *pl, BattleGround *bg, uint64 guid) +void BattleGroundMgr::SendAreaSpiritHealerQueryOpcode(Player *pl, BattleGround *bg, const uint64& guid) { WorldPacket data(SMSG_AREA_SPIRIT_HEALER_TIME, 12); uint32 time_ = 30000 - bg->GetLastResurrectTime(); // resurrect every 30 seconds @@ -1827,14 +1820,7 @@ void BattleGroundMgr::SendAreaSpiritHealerQueryOpcode(Player *pl, BattleGround * pl->GetSession()->SendPacket(&data); } -void BattleGroundMgr::RemoveBattleGround(uint32 instanceID) -{ - BattleGroundSet::iterator itr = m_BattleGrounds.find(instanceID); - if(itr!=m_BattleGrounds.end()) - m_BattleGrounds.erase(itr); -} - -bool BattleGroundMgr::IsArenaType(uint32 bgTypeId) const +bool BattleGroundMgr::IsArenaType(uint32 bgTypeId) { return ( bgTypeId == BATTLEGROUND_AA || bgTypeId == BATTLEGROUND_BE || @@ -1842,82 +1828,77 @@ bool BattleGroundMgr::IsArenaType(uint32 bgTypeId) const bgTypeId == BATTLEGROUND_RL ); } -bool BattleGroundMgr::IsBattleGroundType(uint32 bgTypeId) const -{ - return !IsArenaType(bgTypeId); -} - -uint32 BattleGroundMgr::BGQueueTypeId(uint32 bgTypeId, uint8 arenaType) const +uint32 BattleGroundMgr::BGQueueTypeId(uint32 bgTypeId, uint8 arenaType) { switch(bgTypeId) { - case BATTLEGROUND_WS: - return BATTLEGROUND_QUEUE_WS; - case BATTLEGROUND_AB: - return BATTLEGROUND_QUEUE_AB; - case BATTLEGROUND_AV: - return BATTLEGROUND_QUEUE_AV; - case BATTLEGROUND_EY: - return BATTLEGROUND_QUEUE_EY; - case BATTLEGROUND_SA: - return BATTLEGROUND_QUEUE_SA; - case BATTLEGROUND_AA: - case BATTLEGROUND_NA: - case BATTLEGROUND_RL: - case BATTLEGROUND_BE: - case BATTLEGROUND_DS: - case BATTLEGROUND_RV: - switch(arenaType) - { - case ARENA_TYPE_2v2: - return BATTLEGROUND_QUEUE_2v2; - case ARENA_TYPE_3v3: - return BATTLEGROUND_QUEUE_3v3; - case ARENA_TYPE_5v5: - return BATTLEGROUND_QUEUE_5v5; + case BATTLEGROUND_WS: + return BATTLEGROUND_QUEUE_WS; + case BATTLEGROUND_AB: + return BATTLEGROUND_QUEUE_AB; + case BATTLEGROUND_AV: + return BATTLEGROUND_QUEUE_AV; + case BATTLEGROUND_EY: + return BATTLEGROUND_QUEUE_EY; + case BATTLEGROUND_SA: + return BATTLEGROUND_QUEUE_SA; + case BATTLEGROUND_AA: + case BATTLEGROUND_NA: + case BATTLEGROUND_RL: + case BATTLEGROUND_BE: + case BATTLEGROUND_DS: + case BATTLEGROUND_RV: + switch(arenaType) + { + case ARENA_TYPE_2v2: + return BATTLEGROUND_QUEUE_2v2; + case ARENA_TYPE_3v3: + return BATTLEGROUND_QUEUE_3v3; + case ARENA_TYPE_5v5: + return BATTLEGROUND_QUEUE_5v5; + default: + return 0; + } default: return 0; - } - default: - return 0; } } -uint32 BattleGroundMgr::BGTemplateId(uint32 bgQueueTypeId) const +uint32 BattleGroundMgr::BGTemplateId(uint32 bgQueueTypeId) { switch(bgQueueTypeId) { - case BATTLEGROUND_QUEUE_WS: - return BATTLEGROUND_WS; - case BATTLEGROUND_QUEUE_AB: - return BATTLEGROUND_AB; - case BATTLEGROUND_QUEUE_AV: - return BATTLEGROUND_AV; - case BATTLEGROUND_QUEUE_EY: - return BATTLEGROUND_EY; - case BATTLEGROUND_QUEUE_SA: - return BATTLEGROUND_SA; - case BATTLEGROUND_QUEUE_2v2: - case BATTLEGROUND_QUEUE_3v3: - case BATTLEGROUND_QUEUE_5v5: - return BATTLEGROUND_AA; - default: - return 0; + case BATTLEGROUND_QUEUE_WS: + return BATTLEGROUND_WS; + case BATTLEGROUND_QUEUE_AB: + return BATTLEGROUND_AB; + case BATTLEGROUND_QUEUE_AV: + return BATTLEGROUND_AV; + case BATTLEGROUND_QUEUE_EY: + return BATTLEGROUND_EY; + case BATTLEGROUND_QUEUE_SA: + return BATTLEGROUND_SA; + case BATTLEGROUND_QUEUE_2v2: + case BATTLEGROUND_QUEUE_3v3: + case BATTLEGROUND_QUEUE_5v5: + return BATTLEGROUND_AA; + default: + return 0; } } -uint8 BattleGroundMgr::BGArenaType(uint32 bgQueueTypeId) const +uint8 BattleGroundMgr::BGArenaType(uint32 bgQueueTypeId) { switch(bgQueueTypeId) { - case BATTLEGROUND_QUEUE_2v2: - return ARENA_TYPE_2v2; - case BATTLEGROUND_QUEUE_3v3: - return ARENA_TYPE_3v3; - case BATTLEGROUND_QUEUE_5v5: - return ARENA_TYPE_5v5; - default: - return 0; + case BATTLEGROUND_QUEUE_2v2: + return ARENA_TYPE_2v2; + case BATTLEGROUND_QUEUE_3v3: + return ARENA_TYPE_3v3; + case BATTLEGROUND_QUEUE_5v5: + return ARENA_TYPE_5v5; + default: + return 0; } } diff --git a/src/game/BattleGroundMgr.h b/src/game/BattleGroundMgr.h index ad11436fc..5b5a017ef 100644 --- a/src/game/BattleGroundMgr.h +++ b/src/game/BattleGroundMgr.h @@ -20,7 +20,7 @@ #define __BATTLEGROUNDMGR_H #include "BattleGround.h" -#include "Policies/Singleton.h" +#include "World.h" class BattleGround; @@ -72,10 +72,10 @@ class BattleGroundQueue GroupQueueInfo * AddGroup(Player * leader, uint32 BgTypeId, uint8 ArenaType, bool isRated, uint32 ArenaRating, uint32 ArenaTeamId = 0); void AddPlayer(Player *plr, GroupQueueInfo *ginfo); - void RemovePlayer(uint64 guid, bool decreaseInvitedCount); + void RemovePlayer(const uint64& guid, bool decreaseInvitedCount); void DecreaseGroupLength(uint32 queueId, uint32 AsGroup); void BGEndedRemoveInvites(BattleGround * bg); - void AnnounceWorld(GroupQueueInfo *ginfo, uint64 playerGUID, bool isAddedToQueue); + void AnnounceWorld(GroupQueueInfo *ginfo, const uint64& playerGUID, bool isAddedToQueue); typedef std::map QueuedPlayersMap; QueuedPlayersMap m_QueuedPlayers[MAX_BATTLEGROUND_QUEUES]; @@ -137,7 +137,7 @@ class BattleGroundQueue class BGQueueInviteEvent : public BasicEvent { public: - BGQueueInviteEvent(uint64 pl_guid, uint32 BgInstanceGUID) : m_PlayerGuid(pl_guid), m_BgInstanceGUID(BgInstanceGUID) {}; + BGQueueInviteEvent(const uint64& pl_guid, uint32 BgInstanceGUID) : m_PlayerGuid(pl_guid), m_BgInstanceGUID(BgInstanceGUID) {}; virtual ~BGQueueInviteEvent() {}; virtual bool Execute(uint64 e_time, uint32 p_time); @@ -153,7 +153,10 @@ class BGQueueInviteEvent : public BasicEvent class BGQueueRemoveEvent : public BasicEvent { public: - BGQueueRemoveEvent(uint64 pl_guid, uint32 bgInstanceGUID, uint32 playersTeam) : m_PlayerGuid(pl_guid), m_BgInstanceGUID(bgInstanceGUID), m_PlayersTeam(playersTeam) {}; + BGQueueRemoveEvent(const uint64& pl_guid, uint32 bgInstanceGUID, uint32 playersTeam) : + m_PlayerGuid(pl_guid), m_BgInstanceGUID(bgInstanceGUID), m_PlayersTeam(playersTeam) + { + }; virtual ~BGQueueRemoveEvent() {}; virtual bool Execute(uint64 e_time, uint32 p_time); @@ -170,33 +173,31 @@ class BattleGroundMgr /* Construction */ BattleGroundMgr(); ~BattleGroundMgr(); - void Update(time_t diff); + void Update(uint32 diff); /* Packet Building */ void BuildPlayerJoinedBattleGroundPacket(WorldPacket *data, Player *plr); void BuildPlayerLeftBattleGroundPacket(WorldPacket *data, Player *plr); - void BuildBattleGroundListPacket(WorldPacket *data, uint64 guid, Player *plr, uint32 bgTypeId); + void BuildBattleGroundListPacket(WorldPacket *data, const uint64& guid, Player *plr, uint32 bgTypeId); void BuildGroupJoinedBattlegroundPacket(WorldPacket *data, uint32 bgTypeId); void BuildUpdateWorldStatePacket(WorldPacket *data, uint32 field, uint32 value); void BuildPvpLogDataPacket(WorldPacket *data, BattleGround *bg); void BuildBattleGroundStatusPacket(WorldPacket *data, BattleGround *bg, uint32 team, uint8 QueueSlot, uint8 StatusID, uint32 Time1, uint32 Time2, uint32 arenatype = 0, uint8 israted = 0); void BuildPlaySoundPacket(WorldPacket *data, uint32 soundid); + void SendAreaSpiritHealerQueryOpcode(Player *pl, BattleGround *bg, const uint64& guid); /* Player invitation */ // called from Queue update, or from Addplayer to queue void InvitePlayer(Player* plr, uint32 bgInstanceGUID, uint32 team); /* Battlegrounds */ BattleGroundSet::iterator GetBattleGroundsBegin() { return m_BattleGrounds.begin(); }; - BattleGroundSet::iterator GetBattleGroundsEnd() { return m_BattleGrounds.end(); }; + BattleGroundSet::iterator GetBattleGroundsEnd() { return m_BattleGrounds.end(); }; BattleGround* GetBattleGround(uint32 ID) { BattleGroundSet::iterator i = m_BattleGrounds.find(ID); - if(i != m_BattleGrounds.end()) - return i->second; - else - return NULL; + return ( (i != m_BattleGrounds.end()) ? i->second : NULL ); }; BattleGround * GetBattleGroundTemplate(uint32 bgTypeId); @@ -204,8 +205,8 @@ class BattleGroundMgr uint32 CreateBattleGround(uint32 bgTypeId, uint32 MinPlayersPerTeam, uint32 MaxPlayersPerTeam, uint32 LevelMin, uint32 LevelMax, char* BattleGroundName, uint32 MapID, float Team1StartLocX, float Team1StartLocY, float Team1StartLocZ, float Team1StartLocO, float Team2StartLocX, float Team2StartLocY, float Team2StartLocZ, float Team2StartLocO); - inline void AddBattleGround(uint32 ID, BattleGround* BG) { m_BattleGrounds[ID] = BG; }; - void RemoveBattleGround(uint32 instanceID); + void AddBattleGround(uint32 ID, BattleGround* BG) { m_BattleGrounds[ID] = BG; }; + void RemoveBattleGround(uint32 instanceID) { m_BattleGrounds.erase(instanceID); } void CreateInitialBattleGrounds(); @@ -217,34 +218,28 @@ class BattleGroundMgr BGFreeSlotQueueType BGFreeSlotQueue[MAX_BATTLEGROUND_TYPES]; - void SendAreaSpiritHealerQueryOpcode(Player *pl, BattleGround *bg, uint64 guid); - - bool IsArenaType(uint32 bgTypeId) const; - bool IsBattleGroundType(uint32 bgTypeId) const; - uint32 BGQueueTypeId(uint32 bgTypeId, uint8 arenaType) const; - uint32 BGTemplateId(uint32 bgQueueTypeId) const; - uint8 BGArenaType(uint32 bgQueueTypeId) const; - - uint32 GetMaxRatingDifference() const {return m_MaxRatingDifference;} - uint32 GetRatingDiscardTimer() const {return m_RatingDiscardTimer;} + uint32 GetMaxRatingDifference() const { return sWorld.getConfig(CONFIG_ARENA_MAX_RATING_DIFFERENCE); } + uint32 GetRatingDiscardTimer() const { return sWorld.getConfig(CONFIG_ARENA_RATING_DISCARD_TIMER); } + uint32 GetPrematureFinishTime() const { return sWorld.getConfig(CONFIG_BATTLEGROUND_PREMATURE_FINISH_TIMER); } void InitAutomaticArenaPointDistribution(); void DistributeArenaPoints(); - uint32 GetPrematureFinishTime() const {return m_PrematureFinishTimer;} void ToggleArenaTesting(); - const bool isArenaTesting() const { return m_ArenaTesting; } + bool isArenaTesting() const { return m_ArenaTesting; } + + static bool IsArenaType(uint32 bgTypeId); + static bool IsBattleGroundType(uint32 bgTypeId) { return !BattleGroundMgr::IsArenaType(bgTypeId); } + static uint32 BGQueueTypeId(uint32 bgTypeId, uint8 arenaType); + static uint32 BGTemplateId(uint32 bgQueueTypeId); + static uint8 BGArenaType(uint32 bgQueueTypeId); private: /* Battlegrounds */ BattleGroundSet m_BattleGrounds; - uint32 m_MaxRatingDifference; - uint32 m_RatingDiscardTimer; uint32 m_NextRatingDiscardUpdate; - bool m_AutoDistributePoints; uint64 m_NextAutoDistributionTime; uint32 m_AutoDistributionTimeChecker; - uint32 m_PrematureFinishTimer; bool m_ArenaTesting; }; diff --git a/src/game/BattleGroundNA.cpp b/src/game/BattleGroundNA.cpp index 63bfed9e8..4321dd657 100644 --- a/src/game/BattleGroundNA.cpp +++ b/src/game/BattleGroundNA.cpp @@ -35,7 +35,7 @@ BattleGroundNA::~BattleGroundNA() } -void BattleGroundNA::Update(time_t diff) +void BattleGroundNA::Update(uint32 diff) { BattleGround::Update(diff); diff --git a/src/game/BattleGroundNA.h b/src/game/BattleGroundNA.h index 64ccf0a5a..866dbca42 100644 --- a/src/game/BattleGroundNA.h +++ b/src/game/BattleGroundNA.h @@ -56,7 +56,7 @@ class BattleGroundNA : public BattleGround public: BattleGroundNA(); ~BattleGroundNA(); - void Update(time_t diff); + void Update(uint32 diff); /* inherited from BattlegroundClass */ virtual void AddPlayer(Player *plr); diff --git a/src/game/BattleGroundRL.cpp b/src/game/BattleGroundRL.cpp index ee9beb181..281cdd706 100644 --- a/src/game/BattleGroundRL.cpp +++ b/src/game/BattleGroundRL.cpp @@ -35,7 +35,7 @@ BattleGroundRL::~BattleGroundRL() } -void BattleGroundRL::Update(time_t diff) +void BattleGroundRL::Update(uint32 diff) { BattleGround::Update(diff); diff --git a/src/game/BattleGroundRL.h b/src/game/BattleGroundRL.h index 2c0a67778..427ed9402 100644 --- a/src/game/BattleGroundRL.h +++ b/src/game/BattleGroundRL.h @@ -52,7 +52,7 @@ class BattleGroundRL : public BattleGround public: BattleGroundRL(); ~BattleGroundRL(); - void Update(time_t diff); + void Update(uint32 diff); /* inherited from BattlegroundClass */ virtual void AddPlayer(Player *plr); diff --git a/src/game/BattleGroundRV.cpp b/src/game/BattleGroundRV.cpp index 20c7d11f8..a66f0ce30 100644 --- a/src/game/BattleGroundRV.cpp +++ b/src/game/BattleGroundRV.cpp @@ -30,7 +30,7 @@ BattleGroundRV::~BattleGroundRV() } -void BattleGroundRV::Update(time_t diff) +void BattleGroundRV::Update(uint32 diff) { BattleGround::Update(diff); } diff --git a/src/game/BattleGroundRV.h b/src/game/BattleGroundRV.h index 9f515e35b..2d2ad12c9 100644 --- a/src/game/BattleGroundRV.h +++ b/src/game/BattleGroundRV.h @@ -35,7 +35,7 @@ class BattleGroundRV : public BattleGround public: BattleGroundRV(); ~BattleGroundRV(); - void Update(time_t diff); + void Update(uint32 diff); /* inherited from BattlegroundClass */ virtual void AddPlayer(Player *plr); diff --git a/src/game/BattleGroundSA.cpp b/src/game/BattleGroundSA.cpp index d7bc422ca..20a692976 100644 --- a/src/game/BattleGroundSA.cpp +++ b/src/game/BattleGroundSA.cpp @@ -29,7 +29,7 @@ BattleGroundSA::~BattleGroundSA() } -void BattleGroundSA::Update(time_t diff) +void BattleGroundSA::Update(uint32 diff) { BattleGround::Update(diff); } diff --git a/src/game/BattleGroundSA.h b/src/game/BattleGroundSA.h index 6727c7a1f..331a41455 100644 --- a/src/game/BattleGroundSA.h +++ b/src/game/BattleGroundSA.h @@ -35,7 +35,7 @@ class BattleGroundSA : public BattleGround public: BattleGroundSA(); ~BattleGroundSA(); - void Update(time_t diff); + void Update(uint32 diff); /* inherited from BattlegroundClass */ virtual void AddPlayer(Player *plr); diff --git a/src/game/BattleGroundWS.cpp b/src/game/BattleGroundWS.cpp index 6e70739fa..6071688f6 100644 --- a/src/game/BattleGroundWS.cpp +++ b/src/game/BattleGroundWS.cpp @@ -36,7 +36,7 @@ BattleGroundWS::~BattleGroundWS() { } -void BattleGroundWS::Update(time_t diff) +void BattleGroundWS::Update(uint32 diff) { BattleGround::Update(diff); diff --git a/src/game/BattleGroundWS.h b/src/game/BattleGroundWS.h index 56a7b3061..d5756d42e 100644 --- a/src/game/BattleGroundWS.h +++ b/src/game/BattleGroundWS.h @@ -134,7 +134,7 @@ class BattleGroundWS : public BattleGround /* Construction */ BattleGroundWS(); ~BattleGroundWS(); - void Update(time_t diff); + void Update(uint32 diff); /* inherited from BattlegroundClass */ virtual void AddPlayer(Player *plr); diff --git a/src/game/Cell.h b/src/game/Cell.h index f826b9e06..32dec557f 100644 --- a/src/game/Cell.h +++ b/src/game/Cell.h @@ -91,13 +91,13 @@ struct MANGOS_DLL_DECL Cell y = data.Part.grid_y*MAX_NUMBER_OF_CELLS + data.Part.cell_y; } - inline bool DiffCell(const Cell &cell) const + bool DiffCell(const Cell &cell) const { return( data.Part.cell_x != cell.data.Part.cell_x || data.Part.cell_y != cell.data.Part.cell_y ); } - inline bool DiffGrid(const Cell &cell) const + bool DiffGrid(const Cell &cell) const { return( data.Part.grid_x != cell.data.Part.grid_x || data.Part.grid_y != cell.data.Part.grid_y ); diff --git a/src/game/CharacterHandler.cpp b/src/game/CharacterHandler.cpp index 42132fea2..3d04c8a26 100644 --- a/src/game/CharacterHandler.cpp +++ b/src/game/CharacterHandler.cpp @@ -1206,7 +1206,7 @@ void WorldSession::HandleRemoveGlyph( WorldPacket & recv_data ) uint32 slot; recv_data >> slot; - if(slot > 5) + if(slot > MAX_GLYPH_SLOT_INDEX) { sLog.outDebug("Client sent wrong glyph slot number in opcode CMSG_REMOVE_GLYPH %u", slot); return; diff --git a/src/game/Chat.cpp b/src/game/Chat.cpp index 449267f87..06e3937c1 100644 --- a/src/game/Chat.cpp +++ b/src/game/Chat.cpp @@ -284,6 +284,7 @@ ChatCommand * ChatHandler::getCommandTable() { "spell_chain", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadSpellChainCommand, "", NULL }, { "spell_elixir", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadSpellElixirCommand, "", NULL }, { "spell_learn_spell", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadSpellLearnSpellCommand, "", NULL }, + { "spell_loot_template", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadLootTemplatesSpellCommand, "", NULL }, { "spell_pet_auras", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadSpellPetAurasCommand, "", NULL }, { "spell_proc_event", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadSpellProcEventCommand, "", NULL }, { "spell_script_target", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadSpellScriptTargetCommand, "", NULL }, diff --git a/src/game/Chat.h b/src/game/Chat.h index 12352f88a..13d044892 100644 --- a/src/game/Chat.h +++ b/src/game/Chat.h @@ -233,6 +233,7 @@ class ChatHandler bool HandleReloadLootTemplatesReferenceCommand(const char* args); bool HandleReloadLootTemplatesQuestMailCommand(const char* args); bool HandleReloadLootTemplatesSkinningCommand(const char* args); + bool HandleReloadLootTemplatesSpellCommand(const char* args); bool HandleReloadMangosStringCommand(const char* args); bool HandleReloadNpcGossipCommand(const char* args); bool HandleReloadNpcOptionCommand(const char* args); diff --git a/src/game/Creature.cpp b/src/game/Creature.cpp index 30195fa52..28cb26d94 100644 --- a/src/game/Creature.cpp +++ b/src/game/Creature.cpp @@ -813,10 +813,8 @@ void Creature::sendPreparedGossip(Player* player) if(!player) return; - GossipMenu& gossipmenu = player->PlayerTalkClass->GetGossipMenu(); - // in case empty gossip menu open quest menu if any - if (gossipmenu.Empty() && GetNpcTextId() == 0) + if (player->PlayerTalkClass->GetGossipMenu().Empty() && !player->PlayerTalkClass->GetQuestMenu().Empty()) { player->SendPreparedQuest(GetGUID()); return; @@ -1547,12 +1545,12 @@ bool Creature::IsImmunedToSpell(SpellEntry const* spellInfo) return Unit::IsImmunedToSpell(spellInfo); } -bool Creature::IsImmunedToSpellEffect(uint32 effect, uint32 mechanic) const +bool Creature::IsImmunedToSpellEffect(SpellEntry const* spellInfo, uint32 index) const { - if (GetCreatureInfo()->MechanicImmuneMask & (1 << (mechanic-1))) + if (GetCreatureInfo()->MechanicImmuneMask & (1 << (spellInfo->EffectMechanic[index] - 1))) return true; - return Unit::IsImmunedToSpellEffect(effect, mechanic); + return Unit::IsImmunedToSpellEffect(spellInfo, index); } SpellEntry const *Creature::reachWithSpellAttack(Unit *pVictim) diff --git a/src/game/Creature.h b/src/game/Creature.h index 8bb1f868d..cb444205e 100644 --- a/src/game/Creature.h +++ b/src/game/Creature.h @@ -364,6 +364,10 @@ struct TrainerSpell uint32 reqskill; uint32 reqskillvalue; uint32 reqlevel; + uint32 learned_spell; + + // helpers + bool IsCastable() const { return learned_spell != spell; } }; typedef std::vector TrainerSpellList; @@ -429,7 +433,7 @@ class MANGOS_DLL_SPEC Creature : public Unit bool IsOutOfThreatArea(Unit* pVictim) const; bool IsImmunedToSpell(SpellEntry const* spellInfo); // redefine Unit::IsImmunedToSpell - bool IsImmunedToSpellEffect(uint32 effect, uint32 mechanic) const; + bool IsImmunedToSpellEffect(SpellEntry const* spellInfo, uint32 index) const; // redefine Unit::IsImmunedToSpellEffect bool isElite() const { diff --git a/src/game/Formulas.h b/src/game/Formulas.h index a00e523d1..decad556f 100644 --- a/src/game/Formulas.h +++ b/src/game/Formulas.h @@ -78,8 +78,17 @@ namespace MaNGOS inline uint32 BaseGain(uint32 pl_level, uint32 mob_level, ContentLevels content) { - //TODO: need modifier for CONTENT_71_80 different from CONTENT_61_70? - const uint32 nBaseExp = content == CONTENT_1_60 ? 45 : 235; + uint32 nBaseExp; + switch(content) + { + case CONTENT_1_60: nBaseExp = 45; break; + case CONTENT_61_70: nBaseExp = 235; break; + case CONTENT_71_80: nBaseExp = 580; break; + default: + sLog.outError("BaseGain: Unsupported content level %u",content); + nBaseExp = 45; break; + } + if( mob_level >= pl_level ) { uint32 nLevelDiff = mob_level - pl_level; @@ -116,66 +125,6 @@ namespace MaNGOS return (uint32)(xp_gain*sWorld.getRate(RATE_XP_KILL)); } - inline uint32 xp_Diff(uint32 lvl) - { - if( lvl < 29 ) - return 0; - if( lvl == 29 ) - return 1; - if( lvl == 30 ) - return 3; - if( lvl == 31 ) - return 6; - else - return (5*(lvl-30)); - } - - inline uint32 mxp(uint32 lvl) - { - if (lvl < 60) - { - return (45 + (5*lvl)); - } - else - { - return (235 + (5*lvl)); - } - } - - inline uint32 xp_to_level(uint32 lvl) - { - uint32 xp = 0; - if (lvl < 60) - { - xp = (8*lvl + xp_Diff(lvl)) * mxp(lvl); - } - else if (lvl == 60) - { - xp = (155 + mxp(lvl) * (1344 - 70 - ((69 - lvl) * (7 + (69 - lvl) * 8 - 1)/2))); - } - else if (lvl < 70) - { - xp = (155 + mxp(lvl) * (1344 - ((69-lvl) * (7 + (69 - lvl) * 8 - 1)/2))); - }else - { - // level higher than 70 is not supported - xp = (uint32)(779700 * (pow(sWorld.getRate(RATE_XP_PAST_70), (int32)lvl - 69))); - return ((xp < 0x7fffffff) ? xp : 0x7fffffff); - } - - // The XP to Level is always rounded to the nearest 100 points (50 rounded to high). - xp = ((xp + 50) / 100) * 100; // use additional () for prevent free association operations in C++ - - if ((lvl > 10) && (lvl < 60)) // compute discount added in 2.3.x - { - uint32 discount = (lvl < 28) ? (lvl - 10) : 18; - xp = (xp * (100 - discount)) / 100; // apply discount - xp = (xp / 100) * 100; // floor to hundreds - } - - return xp; - } - inline float xp_in_group_rate(uint32 count, bool isRaid) { if(isRaid) diff --git a/src/game/GossipDef.cpp b/src/game/GossipDef.cpp index 63eeb5991..c7c770bfa 100644 --- a/src/game/GossipDef.cpp +++ b/src/game/GossipDef.cpp @@ -125,7 +125,7 @@ bool PlayerMenu::GossipOptionCoded( unsigned int Selection ) void PlayerMenu::SendGossipMenu( uint32 TitleTextId, uint64 npcGUID ) { WorldPacket data( SMSG_GOSSIP_MESSAGE, (100) ); // guess size - data << npcGUID; + data << uint64(npcGUID); data << uint32(0); // new 2.4.0 data << uint32( TitleTextId ); data << uint32( mGossipMenu.MenuItemCount() ); // max count 0x0F diff --git a/src/game/GridDefines.h b/src/game/GridDefines.h index 03e8cc100..54cdca7b6 100644 --- a/src/game/GridDefines.h +++ b/src/game/GridDefines.h @@ -41,10 +41,10 @@ class Player; #define MIN_GRID_DELAY MINUTE*1000 #define MIN_MAP_UPDATE_DELAY 50 -#define MAX_NUMBER_OF_CELLS 4 +#define MAX_NUMBER_OF_CELLS 8 #define SIZE_OF_GRID_CELL (SIZE_OF_GRIDS/MAX_NUMBER_OF_CELLS) -#define CENTER_GRID_CELL_ID 128 +#define CENTER_GRID_CELL_ID 256 #define CENTER_GRID_CELL_OFFSET (SIZE_OF_GRID_CELL/2) #define TOTAL_NUMBER_OF_CELLS_PER_MAP (MAX_NUMBER_OF_GRIDS*MAX_NUMBER_OF_CELLS) diff --git a/src/game/GridNotifiersImpl.h b/src/game/GridNotifiersImpl.h index 8244f6371..590fc68c9 100644 --- a/src/game/GridNotifiersImpl.h +++ b/src/game/GridNotifiersImpl.h @@ -170,7 +170,7 @@ inline void MaNGOS::DynamicObjectUpdater::VisitHelper(Unit* target) SpellEntry const *spellInfo = sSpellStore.LookupEntry(i_dynobject.GetSpellId()); uint32 eff_index = i_dynobject.GetEffIndex(); // Check target immune to spell or aura - if (target->IsImmunedToSpell(spellInfo) || target->IsImmunedToSpellEffect(spellInfo->Effect[eff_index], spellInfo->EffectMechanic[eff_index])) + if (target->IsImmunedToSpell(spellInfo) || target->IsImmunedToSpellEffect(spellInfo, eff_index)) return; // Apply PersistentAreaAura on target PersistentAreaAura* Aur = new PersistentAreaAura(spellInfo, eff_index, NULL, target, i_dynobject.GetCaster()); diff --git a/src/game/GroupHandler.cpp b/src/game/GroupHandler.cpp index 51fc8cb7c..9ec47103e 100644 --- a/src/game/GroupHandler.cpp +++ b/src/game/GroupHandler.cpp @@ -707,7 +707,7 @@ void WorldSession::BuildPartyMemberStatsChangedPacket(Player *player, WorldPacke if (mask & GROUP_UPDATE_FLAG_AURAS) { - uint64 auramask = player->GetAuraUpdateMask(); + const uint64& auramask = player->GetAuraUpdateMask(); *data << uint64(auramask); for(uint32 i = 0; i < MAX_AURAS; ++i) { @@ -788,7 +788,7 @@ void WorldSession::BuildPartyMemberStatsChangedPacket(Player *player, WorldPacke { if(pet) { - uint64 auramask = pet->GetAuraUpdateMask(); + const uint64& auramask = pet->GetAuraUpdateMask(); *data << uint64(auramask); for(uint32 i = 0; i < MAX_AURAS; ++i) { diff --git a/src/game/Item.h b/src/game/Item.h index a124d318a..2bd91d55e 100644 --- a/src/game/Item.h +++ b/src/game/Item.h @@ -152,7 +152,7 @@ enum EnchantmentSlot SOCK_ENCHANTMENT_SLOT_2 = 3, SOCK_ENCHANTMENT_SLOT_3 = 4, BONUS_ENCHANTMENT_SLOT = 5, - WOTLK_ENCHANTMENT_SLOT = 6, + PRISMATIC_ENCHANTMENT_SLOT = 6, // added at apply special permanent enchantment MAX_INSPECTED_ENCHANTMENT_SLOT = 7, PROP_ENCHANTMENT_SLOT_0 = 7, // used with RandomSuffix diff --git a/src/game/ItemHandler.cpp b/src/game/ItemHandler.cpp index eb4303b23..5715e319a 100644 --- a/src/game/ItemHandler.cpp +++ b/src/game/ItemHandler.cpp @@ -322,7 +322,7 @@ void WorldSession::HandleItemQuerySingleOpcode( WorldPacket & recv_data ) data << pProto->ItemId; data << pProto->Class; data << pProto->SubClass; - data << pProto->Unk0; // new 2.0.3, not exist in wdb cache? + data << int32(pProto->Unk0); // new 2.0.3, not exist in wdb cache? data << Name; data << uint8(0x00); //pProto->Name2; // blizz not send name there, just uint8(0x00); <-- \0 = empty string = empty name... data << uint8(0x00); //pProto->Name3; // blizz not send name there, just uint8(0x00); @@ -418,7 +418,7 @@ void WorldSession::HandleItemQuerySingleOpcode( WorldPacket & recv_data ) data << pProto->PageMaterial; data << pProto->StartQuest; data << pProto->LockID; - data << pProto->Material; + data << int32(pProto->Material); data << pProto->Sheath; data << pProto->RandomProperty; data << pProto->RandomSuffix; @@ -1112,10 +1112,6 @@ void WorldSession::HandleSocketOpcode(WorldPacket& recv_data) CHECK_PACKET_SIZE(recv_data,8*4); uint64 guids[4]; - uint32 GemEnchants[3], OldEnchants[3]; - Item *Gems[3]; - bool SocketBonusActivated, SocketBonusToBeActivated; - for(int i = 0; i < 4; i++) recv_data >> guids[i]; @@ -1133,6 +1129,7 @@ void WorldSession::HandleSocketOpcode(WorldPacket& recv_data) //this slot is excepted when applying / removing meta gem bonus uint8 slot = itemTarget->IsEquipped() ? itemTarget->GetSlot() : NULL_SLOT; + Item *Gems[3]; for(int i = 0; i < 3; i++) Gems[i] = guids[i + 1] ? _player->GetItemByGuid(guids[i + 1]) : NULL; @@ -1152,6 +1149,7 @@ void WorldSession::HandleSocketOpcode(WorldPacket& recv_data) return; } + uint32 GemEnchants[3], OldEnchants[3]; for(int i = 0; i < 3; ++i) //get new and old enchantments { GemEnchants[i] = (GemProps[i]) ? GemProps[i]->spellitemenchantement : 0; @@ -1200,7 +1198,7 @@ void WorldSession::HandleSocketOpcode(WorldPacket& recv_data) } } - SocketBonusActivated = itemTarget->GemsFitSockets(); //save state of socketbonus + bool SocketBonusActivated = itemTarget->GemsFitSockets(); //save state of socketbonus _player->ToggleMetaGemsActive(slot, false); //turn off all metagems (except for the target item) //if a meta gem is being equipped, all information has to be written to the item before testing if the conditions for the gem are met @@ -1222,7 +1220,7 @@ void WorldSession::HandleSocketOpcode(WorldPacket& recv_data) for(uint32 enchant_slot = SOCK_ENCHANTMENT_SLOT; enchant_slot < SOCK_ENCHANTMENT_SLOT+3; ++enchant_slot) _player->ApplyEnchantment(itemTarget,EnchantmentSlot(enchant_slot),true); - SocketBonusToBeActivated = itemTarget->GemsFitSockets();//current socketbonus state + bool SocketBonusToBeActivated = itemTarget->GemsFitSockets();//current socketbonus state if(SocketBonusActivated ^ SocketBonusToBeActivated) //if there was a change... { _player->ApplyEnchantment(itemTarget,BONUS_ENCHANTMENT_SLOT,false); diff --git a/src/game/ItemPrototype.h b/src/game/ItemPrototype.h index a4c0bb96e..28a57ec79 100644 --- a/src/game/ItemPrototype.h +++ b/src/game/ItemPrototype.h @@ -74,6 +74,12 @@ enum ItemSpelltriggerType ITEM_SPELLTRIGGER_ON_EQUIP = 1, ITEM_SPELLTRIGGER_CHANCE_ON_HIT = 2, ITEM_SPELLTRIGGER_SOULSTONE = 4, + /* + * ItemSpelltriggerType 5 might have changed on 2.4.3/3.0.3: Such auras + * will be applied on item pickup and removed on item loss - maybe on the + * other hand the item is destroyed if the aura is removed ("removed on + * death" of spell 57348 makes me think so) + */ ITEM_SPELLTRIGGER_ON_NO_DELAY_USE = 5, // no equip cooldown ITEM_SPELLTRIGGER_LEARN_SPELL_ID = 6 // used in item_template.spell_2 with spell_id with SPELL_GENERIC_LEARN in spell_1 }; @@ -489,7 +495,7 @@ struct ItemPrototype uint32 ItemId; uint32 Class; // id from ItemClass.dbc uint32 SubClass; // id from ItemSubClass.dbc - uint32 Unk0; + int32 Unk0; char* Name1; uint32 DisplayInfoID; // id from ItemDisplayInfo.dbc uint32 Quality; @@ -535,7 +541,7 @@ struct ItemPrototype uint32 PageMaterial; uint32 StartQuest; // id from QuestCache.wdb uint32 LockID; - uint32 Material; // id from Material.dbc + int32 Material; // id from Material.dbc uint32 Sheath; uint32 RandomProperty; // id from ItemRandomProperties.dbc uint32 RandomSuffix; // id from ItemRandomSuffix.dbc diff --git a/src/game/Language.h b/src/game/Language.h index 207361889..4bb924f89 100644 --- a/src/game/Language.h +++ b/src/game/Language.h @@ -723,7 +723,8 @@ enum MangosStrings LANG_MUST_MALE_OR_FEMALE = 1119, LANG_YOU_CHANGE_GENDER = 1120, LANG_YOUR_GENDER_CHANGED = 1121, - // Room for more level 3 1122-1199 not used + LANG_SKILL_VALUES = 1122, + // Room for more level 3 1123-1199 not used // FREE IDS 1200-9999 diff --git a/src/game/Level1.cpp b/src/game/Level1.cpp index 71888e8c0..04639eda8 100644 --- a/src/game/Level1.cpp +++ b/src/game/Level1.cpp @@ -1677,14 +1677,14 @@ bool ChatHandler::HandleModifyMoneyCommand(const char* args) return true; } -//Edit Player field +//Edit Unit field bool ChatHandler::HandleModifyBitCommand(const char* args) { if( !*args ) return false; - Player *chr = getSelectedPlayer(); - if (chr == NULL) + Unit *unit = getSelectedUnit(); + if (!unit) { SendSysMessage(LANG_NO_CHAR_SELECTED); SetSentErrorMessage(true); @@ -1692,7 +1692,7 @@ bool ChatHandler::HandleModifyBitCommand(const char* args) } // check online security - if (HasLowerSecurity(chr, 0)) + if (unit->GetTypeId() == TYPEID_PLAYER && HasLowerSecurity((Player *)unit, 0)) return false; char* pField = strtok((char*)args, " "); @@ -1706,13 +1706,12 @@ bool ChatHandler::HandleModifyBitCommand(const char* args) uint16 field = atoi(pField); uint32 bit = atoi(pBit); - if (field < 1 || field >= PLAYER_END) + if (field < OBJECT_END || field >= unit->GetValuesCount()) { SendSysMessage(LANG_BAD_VALUE); SetSentErrorMessage(true); return false; } - if (bit < 1 || bit > 32) { SendSysMessage(LANG_BAD_VALUE); @@ -1720,17 +1719,16 @@ bool ChatHandler::HandleModifyBitCommand(const char* args) return false; } - if ( chr->HasFlag( field, (1<<(bit-1)) ) ) + if ( unit->HasFlag( field, (1<<(bit-1)) ) ) { - chr->RemoveFlag( field, (1<<(bit-1)) ); + unit->RemoveFlag( field, (1<<(bit-1)) ); PSendSysMessage(LANG_REMOVE_BIT, bit, field); } else { - chr->SetFlag( field, (1<<(bit-1)) ); + unit->SetFlag( field, (1<<(bit-1)) ); PSendSysMessage(LANG_SET_BIT, bit, field); } - return true; } diff --git a/src/game/Level2.cpp b/src/game/Level2.cpp index 6ea8c6b6d..1e6172b74 100644 --- a/src/game/Level2.cpp +++ b/src/game/Level2.cpp @@ -854,8 +854,8 @@ bool ChatHandler::HandleNpcAddCommand(const char* args) { if(!*args) return false; - char* charID = strtok((char*)args, " "); - if (!charID) + char* charID = extractKeyFromLink((char*)args,"Hcreature_entry"); + if(!charID) return false; char* team = strtok(NULL, " "); diff --git a/src/game/Level3.cpp b/src/game/Level3.cpp index 44f626210..cd011e16a 100644 --- a/src/game/Level3.cpp +++ b/src/game/Level3.cpp @@ -339,6 +339,15 @@ bool ChatHandler::HandleReloadLootTemplatesSkinningCommand(const char*) return true; } +bool ChatHandler::HandleReloadLootTemplatesSpellCommand(const char*) +{ + sLog.outString( "Re-Loading Loot Tables... (`spell_loot_template`)" ); + LoadLootTemplates_Spell(); + LootTemplates_Spell.CheckLootRefs(); + SendGlobalSysMessage("DB table `spell_loot_template` reloaded."); + return true; +} + bool ChatHandler::HandleReloadMangosStringCommand(const char*) { sLog.outString( "Re-Loading mangos_string Table!" ); @@ -2632,15 +2641,25 @@ bool ChatHandler::HandleLookupSkillCommand(const char* args) if(loc < MAX_LOCALE) { + char valStr[50] = ""; char const* knownStr = ""; if(target && target->HasSkill(id)) + { knownStr = GetMangosString(LANG_KNOWN); + uint32 curValue = target->GetPureSkillValue(id); + uint32 maxValue = target->GetPureMaxSkillValue(id); + uint32 permValue = target->GetSkillPermBonusValue(id); + uint32 tempValue = target->GetSkillTempBonusValue(id); + + char const* valFormat = GetMangosString(LANG_SKILL_VALUES); + snprintf(valStr,50,valFormat,curValue,maxValue,permValue,tempValue); + } // send skill in "id - [namedlink locale]" format if (m_session) - PSendSysMessage(LANG_SKILL_LIST_CHAT,id,id,name.c_str(),localeNames[loc],knownStr); + PSendSysMessage(LANG_SKILL_LIST_CHAT,id,id,name.c_str(),localeNames[loc],knownStr,valStr); else - PSendSysMessage(LANG_SKILL_LIST_CONSOLE,id,name.c_str(),localeNames[loc],knownStr); + PSendSysMessage(LANG_SKILL_LIST_CONSOLE,id,name.c_str(),localeNames[loc],knownStr,valStr); ++counter; } @@ -3836,8 +3855,6 @@ bool ChatHandler::HandleShowAreaCommand(const char* args) if (!*args) return false; - int area = atoi((char*)args); - Player *chr = getSelectedPlayer(); if (chr == NULL) { @@ -3846,10 +3863,11 @@ bool ChatHandler::HandleShowAreaCommand(const char* args) return false; } + int area = GetAreaFlagByAreaID(atoi((char*)args)); int offset = area / 32; uint32 val = (uint32)(1 << (area % 32)); - if(offset >= 128) + if(area<0 || offset >= 128) { SendSysMessage(LANG_BAD_VALUE); SetSentErrorMessage(true); @@ -3868,8 +3886,6 @@ bool ChatHandler::HandleHideAreaCommand(const char* args) if (!*args) return false; - int area = atoi((char*)args); - Player *chr = getSelectedPlayer(); if (chr == NULL) { @@ -3878,10 +3894,11 @@ bool ChatHandler::HandleHideAreaCommand(const char* args) return false; } + int area = GetAreaFlagByAreaID(atoi((char*)args)); int offset = area / 32; uint32 val = (uint32)(1 << (area % 32)); - if(offset >= 128) + if(area<0 || offset >= 128) { SendSysMessage(LANG_BAD_VALUE); SetSentErrorMessage(true); @@ -4394,8 +4411,10 @@ bool ChatHandler::HandleResetLevelCommand(const char * args) // reset level to summoned pet Pet* pet = player->GetPet(); if(pet && pet->getPetType()==SUMMON_PET) + { pet->InitStatsForLevel(1); - + pet->InitTalentForLevel(); + } return true; } @@ -4507,13 +4526,6 @@ bool ChatHandler::HandleResetTalentsCommand(const char * args) else player = getSelectedPlayer(); - if(!player && !playerGUID) - { - SendSysMessage(LANG_NO_CHAR_SELECTED); - SetSentErrorMessage(true); - return false; - } - if(player) { player->resetTalents(true); @@ -4522,14 +4534,33 @@ bool ChatHandler::HandleResetTalentsCommand(const char * args) if(m_session->GetPlayer()!=player) PSendSysMessage(LANG_RESET_TALENTS_ONLINE,player->GetName()); + return true; } - else + else if (playerGUID) { CharacterDatabase.PExecute("UPDATE characters SET at_login = at_login | '%u' WHERE guid = '%u'",uint32(AT_LOGIN_RESET_TALENTS), GUID_LOPART(playerGUID) ); PSendSysMessage(LANG_RESET_TALENTS_OFFLINE,pName); + return true; + } + // Try reset talenents as Hunter Pet + Creature* creature = getSelectedCreature(); + if (creature && creature->isPet() && ((Pet *)creature)->getPetType() == HUNTER_PET) + { + ((Pet *)creature)->resetTalents(true); + Unit *owner = creature->GetOwner(); + if (owner && owner->GetTypeId() == TYPEID_PLAYER) + { + player = (Player *)owner; + ChatHandler(player).SendSysMessage(LANG_RESET_TALENTS); + if(m_session->GetPlayer()!=player) + PSendSysMessage(LANG_RESET_TALENTS_ONLINE,player->GetName()); + } + return true; } - return true; + SendSysMessage(LANG_NO_CHAR_SELECTED); + SetSentErrorMessage(true); + return false; } bool ChatHandler::HandleResetAllCommand(const char * args) diff --git a/src/game/LootMgr.cpp b/src/game/LootMgr.cpp index 030db9011..e5ffbbaec 100644 --- a/src/game/LootMgr.cpp +++ b/src/game/LootMgr.cpp @@ -23,6 +23,7 @@ #include "World.h" #include "Util.h" #include "SharedDefines.h" +#include "SpellMgr.h" static Rates const qualityToRate[MAX_ITEM_QUALITY] = { RATE_DROP_ITEM_POOR, // ITEM_QUALITY_POOR @@ -34,17 +35,18 @@ static Rates const qualityToRate[MAX_ITEM_QUALITY] = { RATE_DROP_ITEM_ARTIFACT, // ITEM_QUALITY_ARTIFACT }; -LootStore LootTemplates_Creature( "creature_loot_template", "creature entry"); -LootStore LootTemplates_Disenchant( "disenchant_loot_template", "item disenchant id"); -LootStore LootTemplates_Fishing( "fishing_loot_template", "area id"); -LootStore LootTemplates_Gameobject( "gameobject_loot_template", "gameobject entry"); -LootStore LootTemplates_Item( "item_loot_template", "item entry"); -LootStore LootTemplates_Milling( "milling_loot_template", "item entry"); -LootStore LootTemplates_Pickpocketing("pickpocketing_loot_template","creature pickpocket lootid"); -LootStore LootTemplates_Prospecting( "prospecting_loot_template", "item entry"); -LootStore LootTemplates_QuestMail( "quest_mail_loot_template", "quest id"); -LootStore LootTemplates_Reference( "reference_loot_template", "reference id"); -LootStore LootTemplates_Skinning( "skinning_loot_template", "creature skinning id"); +LootStore LootTemplates_Creature( "creature_loot_template", "creature entry", true); +LootStore LootTemplates_Disenchant( "disenchant_loot_template", "item disenchant id", true); +LootStore LootTemplates_Fishing( "fishing_loot_template", "area id", true); +LootStore LootTemplates_Gameobject( "gameobject_loot_template", "gameobject entry", true); +LootStore LootTemplates_Item( "item_loot_template", "item entry", true); +LootStore LootTemplates_Milling( "milling_loot_template", "item entry (herb)", true); +LootStore LootTemplates_Pickpocketing("pickpocketing_loot_template","creature pickpocket lootid", true); +LootStore LootTemplates_Prospecting( "prospecting_loot_template", "item entry (ore)", true); +LootStore LootTemplates_QuestMail( "quest_mail_loot_template", "quest id (with mail template)",false); +LootStore LootTemplates_Reference( "reference_loot_template", "reference id", false); +LootStore LootTemplates_Skinning( "skinning_loot_template", "creature skinning id", true); +LootStore LootTemplates_Spell( "spell_loot_template", "spell id (explicitly discovering ability)",false); class LootTemplate::LootGroup // A set of loot definitions for items (refs are not allowed) { @@ -53,7 +55,7 @@ class LootTemplate::LootGroup // A set of loot def bool HasQuestDrop() const; // True if group includes at least 1 quest drop entry bool HasQuestDropForPlayer(Player const * player) const; // The same for active quests of the player - void Process(Loot& loot) const; // Rolls an item from the group (if any) and adds the item to the loot + void Process(Loot& loot, bool rate) const; // Rolls an item from the group (if any) and adds the item to the loot float RawTotalChance() const; // Overall chance for the group (without equal chanced items) float TotalChance() const; // Overall chance for the group @@ -64,7 +66,7 @@ class LootTemplate::LootGroup // A set of loot def LootStoreItemList ExplicitlyChanced; // Entries with chances defined in DB LootStoreItemList EqualChanced; // Zero chances - every entry takes the same chance - LootStoreItem const * Roll() const; // Rolls an item from the group, returns NULL if all miss their chances + LootStoreItem const * Roll(bool rate) const; // Rolls an item from the group, returns NULL if all miss their chances }; //Remove all data and free all memory @@ -228,17 +230,17 @@ void LootStore::ReportNotExistedId(uint32 id) const // Checks if the entry (quest, non-quest, reference) takes it's chance (at loot generation) // RATE_DROP_ITEMS is no longer used for all types of entries -bool LootStoreItem::Roll() const +bool LootStoreItem::Roll(bool rate) const { if(chance>=100.f) return true; if(mincountOrRef < 0) // reference case - return roll_chance_f(chance*sWorld.getRate(RATE_DROP_ITEM_REFERENCED)); + return roll_chance_f(chance* (rate ? sWorld.getRate(RATE_DROP_ITEM_REFERENCED) : 1.0f)); ItemPrototype const *pProto = objmgr.GetItemPrototype(itemid); - float qualityModifier = pProto ? sWorld.getRate(qualityToRate[pProto->Quality]) : 1.0f; + float qualityModifier = pProto && rate ? sWorld.getRate(qualityToRate[pProto->Quality]) : 1.0f; return roll_chance_f(chance*qualityModifier); } @@ -377,7 +379,7 @@ void Loot::FillLoot(uint32 loot_id, LootStore const& store, Player* loot_owner) items.reserve(MAX_NR_LOOT_ITEMS); quest_items.reserve(MAX_NR_QUEST_ITEMS); - tab->Process(*this, store); // Processing is done there, callback via Loot::AddItem() + tab->Process(*this, store,store.IsRatesAllowed ()); // Processing is done there, callback via Loot::AddItem() // Setting access rights fow group-looting case if(!loot_owner) @@ -763,7 +765,7 @@ void LootTemplate::LootGroup::AddEntry(LootStoreItem& item) } // Rolls an item from the group, returns NULL if all miss their chances -LootStoreItem const * LootTemplate::LootGroup::Roll() const +LootStoreItem const * LootTemplate::LootGroup::Roll(bool rate) const { if (!ExplicitlyChanced.empty()) // First explicitly chanced entries are checked { @@ -775,7 +777,7 @@ LootStoreItem const * LootTemplate::LootGroup::Roll() const return &ExplicitlyChanced[i]; ItemPrototype const *pProto = objmgr.GetItemPrototype(ExplicitlyChanced[i].itemid); - float qualityMultiplier = pProto ? sWorld.getRate(qualityToRate[pProto->Quality]) : 1.0f; + float qualityMultiplier = pProto && rate ? sWorld.getRate(qualityToRate[pProto->Quality]) : 1.0f; Roll -= ExplicitlyChanced[i].chance * qualityMultiplier; if (Roll < 0) return &ExplicitlyChanced[i]; @@ -812,9 +814,9 @@ bool LootTemplate::LootGroup::HasQuestDropForPlayer(Player const * player) const } // Rolls an item from the group (if any takes its chance) and adds the item to the loot -void LootTemplate::LootGroup::Process(Loot& loot) const +void LootTemplate::LootGroup::Process(Loot& loot, bool rate) const { - LootStoreItem const * item = Roll(); + LootStoreItem const * item = Roll(rate); if (item != NULL) loot.AddItem(*item); } @@ -899,21 +901,21 @@ void LootTemplate::AddEntry(LootStoreItem& item) } // Rolls for every item in the template and adds the rolled items the the loot -void LootTemplate::Process(Loot& loot, LootStore const& store, uint8 groupId) const +void LootTemplate::Process(Loot& loot, LootStore const& store, bool rate, uint8 groupId) const { if (groupId) // Group reference uses own processing of the group { if (groupId > Groups.size()) return; // Error message already printed at loading stage - Groups[groupId-1].Process(loot); + Groups[groupId-1].Process(loot,rate); return; } // Rolling non-grouped items for (LootStoreItemList::const_iterator i = Entries.begin() ; i != Entries.end() ; ++i ) { - if ( !i->Roll() ) + if (!i->Roll(rate)) continue; // Bad luck for the entry if (i->mincountOrRef < 0) // References processing @@ -924,7 +926,7 @@ void LootTemplate::Process(Loot& loot, LootStore const& store, uint8 groupId) co continue; // Error message already printed at loading stage for (uint32 loop=0; loop < i->maxcount; ++loop )// Ref multiplicator - Referenced->Process(loot, store, i->group); // Ref processing + Referenced->Process(loot, store, rate, i->group); } else // Plain entries (not a reference, not grouped) loot.AddItem(*i); // Chance is already checked, just add @@ -932,7 +934,7 @@ void LootTemplate::Process(Loot& loot, LootStore const& store, uint8 groupId) co // Now processing groups for (LootGroups::const_iterator i = Groups.begin( ) ; i != Groups.end( ) ; ++i ) - i->Process(loot); + i->Process(loot,rate); } // True if template includes at least 1 quest drop entry @@ -1143,9 +1145,17 @@ void LoadLootTemplates_Milling() // remove real entries and check existence loot for(uint32 i = 1; i < sItemStorage.MaxEntry; ++i ) - if(ItemPrototype const* proto = sItemStorage.LookupEntry(i)) - if(ids_set.count(proto->ItemId)) - ids_set.erase(proto->ItemId); + { + ItemPrototype const* proto = sItemStorage.LookupEntry(i); + if(!proto) + continue; + + if((proto->BagFamily & BAG_FAMILY_MASK_HERBS)==0) + continue; + + if(ids_set.count(proto->ItemId)) + ids_set.erase(proto->ItemId); + } // output error for any still listed (not referenced from appropriate table) ids LootTemplates_Milling.ReportUnusedIds(ids_set); @@ -1184,9 +1194,17 @@ void LoadLootTemplates_Prospecting() // remove real entries and check existence loot for(uint32 i = 1; i < sItemStorage.MaxEntry; ++i ) - if(ItemPrototype const* proto = sItemStorage.LookupEntry(i)) - if(ids_set.count(proto->ItemId)) - ids_set.erase(proto->ItemId); + { + ItemPrototype const* proto = sItemStorage.LookupEntry(i); + if(!proto) + continue; + + if((proto->BagFamily & BAG_FAMILY_MASK_MINING_SUPP)==0) + continue; + + if(ids_set.count(proto->ItemId)) + ids_set.erase(proto->ItemId); + } // output error for any still listed (not referenced from appropriate table) ids LootTemplates_Prospecting.ReportUnusedIds(ids_set); @@ -1200,8 +1218,17 @@ void LoadLootTemplates_QuestMail() // remove real entries and check existence loot ObjectMgr::QuestMap const& questMap = objmgr.GetQuestTemplates(); for(ObjectMgr::QuestMap::const_iterator itr = questMap.begin(); itr != questMap.end(); ++itr ) + { + if(!itr->second->GetRewMailTemplateId()) + continue; + if(ids_set.count(itr->first)) ids_set.erase(itr->first); + /* disabled reporting: some quest mails not include items + else + LootTemplates_QuestMail.ReportNotExistedId(itr->first); + */ + } // output error for any still listed (not referenced from appropriate table) ids LootTemplates_QuestMail.ReportUnusedIds(ids_set); @@ -1233,6 +1260,32 @@ void LoadLootTemplates_Skinning() LootTemplates_Skinning.ReportUnusedIds(ids_set); } +void LoadLootTemplates_Spell() +{ + LootIdSet ids_set; + LootTemplates_Spell.LoadAndCollectLootIds(ids_set); + + // remove real entries and check existence loot + for(uint32 spell_id = 1; spell_id < sSpellStore.GetNumRows(); ++spell_id) + { + SpellEntry const* spellInfo = sSpellStore.LookupEntry (spell_id); + if(!spellInfo) + continue; + + // possible cases + if(!IsExplicitDiscoverySpell (spellInfo)) + continue; + + if(!ids_set.count(spell_id)) + LootTemplates_Spell.ReportNotExistedId(spell_id); + else + ids_set.erase(spell_id); + } + + // output error for any still listed (not referenced from appropriate table) ids + LootTemplates_QuestMail.ReportUnusedIds(ids_set); +} + void LoadLootTemplates_Reference() { LootIdSet ids_set; diff --git a/src/game/LootMgr.h b/src/game/LootMgr.h index 6f8289d31..9a7d31e09 100644 --- a/src/game/LootMgr.h +++ b/src/game/LootMgr.h @@ -75,7 +75,7 @@ struct LootStoreItem group(_group), maxcount(_maxcount), conditionId(_conditionId), needs_quest(_chanceOrQuestChance < 0) {} - bool Roll() const; // Checks if the entry takes it's chance (at loot generation) + bool Roll(bool rate) const; // Checks if the entry takes it's chance (at loot generation) bool IsValid(LootStore const& store, uint32 entry) const; // Checks correctness of values }; @@ -127,7 +127,8 @@ typedef std::set LootIdSet; class LootStore { public: - explicit LootStore(char const* name, char const* entryName) : m_name(name), m_entryName(entryName) {} + explicit LootStore(char const* name, char const* entryName, bool ratesAllowed) + : m_name(name), m_entryName(entryName), m_ratesAllowed(m_ratesAllowed) {} virtual ~LootStore() { Clear(); } void Verify() const; @@ -145,6 +146,7 @@ class LootStore char const* GetName() const { return m_name; } char const* GetEntryName() const { return m_entryName; } + bool IsRatesAllowed() const { return m_ratesAllowed; } protected: void LoadLootTable(); void Clear(); @@ -152,6 +154,7 @@ class LootStore LootTemplateMap m_LootTemplates; char const* m_name; char const* m_entryName; + bool m_ratesAllowed; }; class LootTemplate @@ -163,7 +166,7 @@ class LootTemplate // Adds an entry to the group (at loading stage) void AddEntry(LootStoreItem& item); // Rolls for every item in the template and adds the rolled items the the loot - void Process(Loot& loot, LootStore const& store, uint8 GroupId = 0) const; + void Process(Loot& loot, LootStore const& store, bool rate, uint8 GroupId = 0) const; // True if template includes at least 1 quest drop entry bool HasQuestDrop(LootTemplateMap const& store, uint8 GroupId = 0) const; @@ -301,6 +304,7 @@ extern LootStore LootTemplates_Skinning; extern LootStore LootTemplates_Disenchant; extern LootStore LootTemplates_Prospecting; extern LootStore LootTemplates_QuestMail; +extern LootStore LootTemplates_Spell; void LoadLootTemplates_Creature(); void LoadLootTemplates_Fishing(); @@ -312,6 +316,8 @@ void LoadLootTemplates_Skinning(); void LoadLootTemplates_Disenchant(); void LoadLootTemplates_Prospecting(); void LoadLootTemplates_QuestMail(); + +void LoadLootTemplates_Spell(); void LoadLootTemplates_Reference(); inline void LoadLootTables() @@ -326,6 +332,8 @@ inline void LoadLootTables() LoadLootTemplates_Disenchant(); LoadLootTemplates_Prospecting(); LoadLootTemplates_QuestMail(); + LoadLootTemplates_Spell(); + LoadLootTemplates_Reference(); } diff --git a/src/game/Map.cpp b/src/game/Map.cpp index bba8e945a..2a74d5ef4 100644 --- a/src/game/Map.cpp +++ b/src/game/Map.cpp @@ -1448,14 +1448,6 @@ void Map::RemoveAllObjectsInRemoveList() //sLog.outDebug("Object remover 2 check."); } -bool Map::CanUnload(const uint32 &diff) -{ - if(!m_unloadTimer) return false; - if(m_unloadTimer < diff) return true; - m_unloadTimer -= diff; - return false; -} - uint32 Map::GetPlayersCountExceptGMs() const { uint32 count = 0; diff --git a/src/game/Map.h b/src/game/Map.h index 5b9c3781a..664dc542a 100644 --- a/src/game/Map.h +++ b/src/game/Map.h @@ -131,7 +131,13 @@ class MANGOS_DLL_SPEC Map : public GridRefManager, public MaNGOS::Obj virtual ~Map(); // currently unused for normal maps - virtual bool CanUnload(const uint32& diff); + bool CanUnload(uint32 diff) + { + if(!m_unloadTimer) return false; + if(m_unloadTimer <= diff) return true; + m_unloadTimer -= diff; + return false; + } virtual bool Add(Player *); virtual void Remove(Player *, bool); @@ -150,7 +156,7 @@ class MANGOS_DLL_SPEC Map : public GridRefManager, public MaNGOS::Obj template void Visit(const CellLock &cell, TypeContainerVisitor &visitor); - inline bool IsRemovalGrid(float x, float y) const + bool IsRemovalGrid(float x, float y) const { GridPair p = MaNGOS::ComputeGridPair(x, y); return( !getNGrid(p.x_coord, p.y_coord) || getNGrid(p.x_coord, p.y_coord)->GetGridState() == GRID_STATE_REMOVAL ); @@ -291,7 +297,7 @@ class MANGOS_DLL_SPEC Map : public GridRefManager, public MaNGOS::Obj bool isGridObjectDataLoaded(uint32 x, uint32 y) const { return getNGrid(x,y)->isGridObjectDataLoaded(); } void setGridObjectDataLoaded(bool pLoaded, uint32 x, uint32 y) { getNGrid(x,y)->setGridObjectDataLoaded(pLoaded); } - inline void setNGrid(NGridType* grid, uint32 x, uint32 y); + void setNGrid(NGridType* grid, uint32 x, uint32 y); protected: typedef MaNGOS::ObjectLevelLockable::Lock Guard; diff --git a/src/game/MapManager.cpp b/src/game/MapManager.cpp index 9a7d1c20e..29e443507 100644 --- a/src/game/MapManager.cpp +++ b/src/game/MapManager.cpp @@ -239,7 +239,7 @@ void MapManager::RemoveBonesFromMap(uint32 mapid, uint64 guid, float x, float y) } void -MapManager::Update(time_t diff) +MapManager::Update(uint32 diff) { i_timer.Update(diff); if( !i_timer.Passed() ) diff --git a/src/game/MapManager.h b/src/game/MapManager.h index 30bfead45..cb4c469a6 100644 --- a/src/game/MapManager.h +++ b/src/game/MapManager.h @@ -45,18 +45,18 @@ class MANGOS_DLL_DECL MapManager : public MaNGOS::Singleton(this)->_GetBaseMap(id); } void DeleteInstance(uint32 mapid, uint32 instanceId); - inline uint16 GetAreaFlag(uint32 mapid, float x, float y, float z) const + uint16 GetAreaFlag(uint32 mapid, float x, float y, float z) const { Map const* m = GetBaseMap(mapid); return m->GetAreaFlag(x, y, z); } - inline uint32 GetAreaId(uint32 mapid, float x, float y, float z) { return Map::GetAreaId(GetAreaFlag(mapid, x, y, z),mapid); } - inline uint32 GetZoneId(uint32 mapid, float x, float y, float z) { return Map::GetZoneId(GetAreaFlag(mapid, x, y, z),mapid); } + uint32 GetAreaId(uint32 mapid, float x, float y, float z) const { return Map::GetAreaId(GetAreaFlag(mapid, x, y, z),mapid); } + uint32 GetZoneId(uint32 mapid, float x, float y, float z) const { return Map::GetZoneId(GetAreaFlag(mapid, x, y, z),mapid); } void Initialize(void); - void Update(time_t); + void Update(uint32); - inline void SetGridCleanUpDelay(uint32 t) + void SetGridCleanUpDelay(uint32 t) { if( t < MIN_GRID_DELAY ) i_gridCleanUpDelay = MIN_GRID_DELAY; @@ -64,7 +64,7 @@ class MANGOS_DLL_DECL MapManager : public MaNGOS::Singleton MIN_MAP_UPDATE_DELAY ) t = MIN_MAP_UPDATE_DELAY; @@ -106,7 +106,7 @@ class MANGOS_DLL_DECL MapManager : public MaNGOS::Singleton(dest.contents()), &destSize, (uint8*)adata->Data.c_str(), size) != Z_OK) + if(size && compress(const_cast(dest.contents()), &destSize, (uint8*)adata->Data.c_str(), size) != Z_OK) { sLog.outDebug("RAD: Failed to compress account data"); return; diff --git a/src/game/NPCHandler.cpp b/src/game/NPCHandler.cpp index 498902ebe..5e3580088 100644 --- a/src/game/NPCHandler.cpp +++ b/src/game/NPCHandler.cpp @@ -164,16 +164,16 @@ void WorldSession::SendTrainerList( uint64 guid, const std::string& strTitle ) { TrainerSpell const* tSpell = *itr; - if(!_player->IsSpellFitByClassAndRace(tSpell->spell)) + if(!_player->IsSpellFitByClassAndRace(tSpell->learned_spell)) continue; ++count; - bool primary_prof_first_rank = spellmgr.IsPrimaryProfessionFirstRankSpell(tSpell->spell); + bool primary_prof_first_rank = spellmgr.IsPrimaryProfessionFirstRankSpell(tSpell->learned_spell); - SpellChainNode const* chain_node = spellmgr.GetSpellChainNode(tSpell->spell); + SpellChainNode const* chain_node = spellmgr.GetSpellChainNode(tSpell->learned_spell); - data << uint32(tSpell->spell); + data << uint32(tSpell->spell); // learned spell (or cast-spell in profession case) data << uint8(_player->GetTrainerSpellState(tSpell)); data << uint32(floor(tSpell->spellcost * fDiscountMod)); @@ -238,21 +238,27 @@ void WorldSession::HandleTrainerBuySpellOpcode( WorldPacket & recv_data ) if(_player->GetMoney() < nSpellCost ) return; - WorldPacket data(SMSG_PLAY_SPELL_VISUAL, 12); // visual effect on trainer - data << uint64(guid) << uint32(0xB3); - SendPacket(&data); - - data.Initialize(SMSG_PLAY_SPELL_IMPACT, 12); // visual effect on player - data << uint64(_player->GetGUID()) << uint32(0x016A); - SendPacket(&data); - _player->ModifyMoney( -int32(nSpellCost) ); - // learn explicitly to prevent lost money at lags, learning spell will be only show spell animation - _player->learnSpell(trainer_spell->spell); + // learn explicitly or cast explicitly + if(trainer_spell->IsCastable ()) + //FIXME: prof. spell entry in trainer list not marked gray until list re-open. + unit->CastSpell(_player,trainer_spell->spell,true); + else + { + WorldPacket data(SMSG_PLAY_SPELL_VISUAL, 12); // visual effect on trainer + data << uint64(guid) << uint32(0xB3); + SendPacket(&data); - data.Initialize(SMSG_TRAINER_BUY_SUCCEEDED, 12); - data << uint64(guid) << uint32(spellId); + data.Initialize(SMSG_PLAY_SPELL_IMPACT, 12); // visual effect on player + data << uint64(_player->GetGUID()) << uint32(0x016A); + SendPacket(&data); + + _player->learnSpell(spellId); + } + + WorldPacket data(SMSG_TRAINER_BUY_SUCCEEDED, 12); + data << uint64(guid) << uint32(trainer_spell->spell); SendPacket(&data); } diff --git a/src/game/ObjectAccessor.cpp b/src/game/ObjectAccessor.cpp index 53b6c245f..447ec2059 100644 --- a/src/game/ObjectAccessor.cpp +++ b/src/game/ObjectAccessor.cpp @@ -274,22 +274,6 @@ ObjectAccessor::UpdateObject(Object* obj, Player* exceptPlayer) } } -void -ObjectAccessor::AddUpdateObject(Object *obj) -{ - Guard guard(i_updateGuard); - i_objects.insert(obj); -} - -void -ObjectAccessor::RemoveUpdateObject(Object *obj) -{ - Guard guard(i_updateGuard); - std::set::iterator iter = i_objects.find(obj); - if( iter != i_objects.end() ) - i_objects.erase( iter ); -} - void ObjectAccessor::_buildUpdateObject(Object *obj, UpdateDataMapType &update_players) { diff --git a/src/game/ObjectAccessor.h b/src/game/ObjectAccessor.h index eb09f6385..102da6984 100644 --- a/src/game/ObjectAccessor.h +++ b/src/game/ObjectAccessor.h @@ -57,9 +57,7 @@ class HashMapHolder static void Remove(T* o) { Guard guard(i_lock); - typename MapType::iterator itr = m_objectMap.find(o->GetGUID()); - if (itr != m_objectMap.end()) - m_objectMap.erase(itr); + m_objectMap.erase(o->GetGUID()); } static T* Find(uint64 guid) @@ -174,16 +172,22 @@ class MANGOS_DLL_DECL ObjectAccessor : public MaNGOS::Singleton::Remove(pl); Guard guard(i_updateGuard); - - std::set::iterator iter2 = std::find(i_objects.begin(), i_objects.end(), (Object *)pl); - if( iter2 != i_objects.end() ) - i_objects.erase(iter2); + i_objects.erase((Object *)pl); } void SaveAllPlayers(); - void AddUpdateObject(Object *obj); - void RemoveUpdateObject(Object *obj); + void AddUpdateObject(Object *obj) + { + Guard guard(i_updateGuard); + i_objects.insert(obj); + } + + void RemoveUpdateObject(Object *obj) + { + Guard guard(i_updateGuard); + i_objects.erase( obj ); + } void Update(uint32 diff); void UpdatePlayers(uint32 diff); diff --git a/src/game/ObjectMgr.cpp b/src/game/ObjectMgr.cpp index 4566bf2a6..3b86397a9 100644 --- a/src/game/ObjectMgr.cpp +++ b/src/game/ObjectMgr.cpp @@ -1598,6 +1598,32 @@ void ObjectMgr::LoadItemPrototypes() if(dbcitem) { + if(proto->Class != dbcitem->Class) + { + sLog.outErrorDb("Item (Entry: %u) not correct class %u, must be %u (still using DB value).",i,proto->Class,dbcitem->Class); + // It safe let use Class from DB + } + /* disabled: have some strange wrong cases for Subclass values. + for enable also uncomment Subclass field in ItemEntry structure and in Itemfmt[] + if(proto->SubClass != dbcitem->SubClass) + { + sLog.outErrorDb("Item (Entry: %u) not correct (Class: %u, Sub: %u) pair, must be (Class: %u, Sub: %u) (still using DB value).",i,proto->Class,proto->SubClass,dbcitem->Class,dbcitem->SubClass); + // It safe let use Subclass from DB + } + */ + + if(proto->Unk0 != dbcitem->Unk0) + { + sLog.outErrorDb("Item (Entry: %u) not correct %i Unk0, must be %i (still using DB value).",i,proto->Unk0,dbcitem->Unk0); + // It safe let use Unk0 from DB + } + + if(proto->Material != dbcitem->Material) + { + sLog.outErrorDb("Item (Entry: %u) not correct %i material, must be %i (still using DB value).",i,proto->Material,dbcitem->Material); + // It safe let use Material from DB + } + if(proto->InventoryType != dbcitem->InventoryType) { sLog.outErrorDb("Item (Entry: %u) not correct %u inventory type, must be %u (still using DB value).",i,proto->InventoryType,dbcitem->InventoryType); @@ -2533,6 +2559,67 @@ void ObjectMgr::LoadPlayerInfo() } } } + + // Loading xp per level data + { + mPlayerXPperLevel.resize(sWorld.getConfig(CONFIG_MAX_PLAYER_LEVEL)); + for (uint32 level = 0; level < sWorld.getConfig(CONFIG_MAX_PLAYER_LEVEL); ++level) + mPlayerXPperLevel[level] = 0; + + // 0 1 + QueryResult *result = WorldDatabase.Query("SELECT lvl, xp_for_next_level FROM player_xp_for_level"); + + uint32 count = 0; + + if (!result) + { + barGoLink bar( 1 ); + + sLog.outString(); + sLog.outString( ">> Loaded %u xp for level definitions", count ); + sLog.outErrorDb( "Error loading `player_xp_for_level` table or empty table."); + exit(1); + } + + barGoLink bar( result->GetRowCount() ); + + do + { + Field* fields = result->Fetch(); + + uint32 current_level = fields[0].GetUInt32(); + uint32 current_xp = fields[1].GetUInt32(); + + if(current_level >= sWorld.getConfig(CONFIG_MAX_PLAYER_LEVEL)) + { + if(current_level > STRONG_MAX_LEVEL) // hardcoded level maximum + sLog.outErrorDb("Wrong (> %u) level %u in `player_xp_for_level` table, ignoring.", STRONG_MAX_LEVEL,current_level); + else + sLog.outDetail("Unused (> MaxPlayerLevel in mangosd.conf) level %u in `player_xp_for_levels` table, ignoring.",current_level); + continue; + } + //PlayerXPperLevel + mPlayerXPperLevel[current_level] = current_xp; + bar.step(); + ++count; + } + while (result->NextRow()); + + delete result; + + sLog.outString(); + sLog.outString( ">> Loaded %u xp for level definitions", count ); + } + + // fill level gaps + for (uint32 level = 1; level < sWorld.getConfig(CONFIG_MAX_PLAYER_LEVEL); ++level) + { + if( mPlayerXPperLevel[level] == 0) + { + sLog.outErrorDb("Level %i does not have XP for level data. Using data of level [%i] + 100.",level+1, level); + mPlayerXPperLevel[level] = mPlayerXPperLevel[level-1]+100; + } + } } void ObjectMgr::GetPlayerClassLevelInfo(uint32 class_, uint32 level, PlayerClassLevelInfo* info) const @@ -5688,6 +5775,13 @@ uint32 ObjectMgr::GetBaseXP(uint32 level) return mBaseXPTable[level] ? mBaseXPTable[level] : 0; } +uint32 ObjectMgr::GetXPForLevel(uint32 level) +{ + if (level < mPlayerXPperLevel.size()) + return mPlayerXPperLevel[level]; + return 0; +} + void ObjectMgr::LoadPetNames() { uint32 count = 0; @@ -7040,6 +7134,19 @@ void ObjectMgr::LoadTrainerSpell() if(!pTrainerSpell->reqlevel) pTrainerSpell->reqlevel = spellinfo->spellLevel; + // calculate learned spell for profession case when stored cast-spell + pTrainerSpell->learned_spell = spell; + for(int i = 0; i <3; ++i) + { + if(spellinfo->Effect[i]!=SPELL_EFFECT_LEARN_SPELL) + continue; + + if(SpellMgr::IsProfessionOrRidingSpell(spellinfo->EffectTriggerSpell[i])) + { + pTrainerSpell->learned_spell = spellinfo->EffectTriggerSpell[i]; + break; + } + } TrainerSpellData& data = m_mCacheTrainerSpellMap[entry]; diff --git a/src/game/ObjectMgr.h b/src/game/ObjectMgr.h index eac5a6bf2..b8b75f0ba 100644 --- a/src/game/ObjectMgr.h +++ b/src/game/ObjectMgr.h @@ -568,6 +568,7 @@ class ObjectMgr std::string GeneratePetName(uint32 entry); uint32 GetBaseXP(uint32 level); + uint32 GetXPForLevel(uint32 level); int32 GetFishingBaseSkillLevel(uint32 entry) const { @@ -862,6 +863,9 @@ class ObjectMgr void BuildPlayerLevelInfo(uint8 race, uint8 class_, uint8 level, PlayerLevelInfo* plinfo) const; PlayerInfo playerInfo[MAX_RACES][MAX_CLASSES]; + typedef std::vector PlayerXPperLevel; // [level] + PlayerXPperLevel mPlayerXPperLevel; + typedef std::map BaseXPMap; // [area level][base xp] BaseXPMap mBaseXPTable; diff --git a/src/game/Pet.cpp b/src/game/Pet.cpp index 93894e4d3..8c92cd6ec 100644 --- a/src/game/Pet.cpp +++ b/src/game/Pet.cpp @@ -53,6 +53,7 @@ Pet::Pet(PetType type) : Creature() m_resetTalentsCost = 0; m_resetTalentsTime = 0; + m_usedTalentCount = 0; m_auraUpdateMask = 0; @@ -700,7 +701,7 @@ void Pet::GivePetXP(uint32 xp) newXP -= nextLvlXP; SetLevel( level + 1 ); - SetUInt32Value(UNIT_FIELD_PETNEXTLEVELEXP, uint32((MaNGOS::XP::xp_to_level(level+1))/4)); + SetUInt32Value(UNIT_FIELD_PETNEXTLEVELEXP, objmgr.GetXPForLevel(level+1)/4); level = getLevel(); nextLvlXP = GetUInt32Value(UNIT_FIELD_PETNEXTLEVELEXP); @@ -716,6 +717,7 @@ void Pet::GivePetLevel(uint32 level) return; InitStatsForLevel(level); + InitTalentForLevel(); } bool Pet::CreateBaseAtCreature(Creature* creature) @@ -763,7 +765,7 @@ bool Pet::CreateBaseAtCreature(Creature* creature) setPowerType(POWER_FOCUS); SetUInt32Value(UNIT_FIELD_PET_NAME_TIMESTAMP, 0); SetUInt32Value(UNIT_FIELD_PETEXPERIENCE, 0); - SetUInt32Value(UNIT_FIELD_PETNEXTLEVELEXP, uint32((MaNGOS::XP::xp_to_level(creature->getLevel()))/4)); + SetUInt32Value(UNIT_FIELD_PETNEXTLEVELEXP, objmgr.GetXPForLevel(creature->getLevel())/4); SetUInt32Value(UNIT_NPC_FLAGS, 0); CreatureFamilyEntry const* cFamily = sCreatureFamilyStore.LookupEntry(creature->GetCreatureInfo()->family); @@ -906,7 +908,7 @@ bool Pet::InitStatsForLevel(uint32 petlevel) } case HUNTER_PET: { - SetUInt32Value(UNIT_FIELD_PETNEXTLEVELEXP, uint32((MaNGOS::XP::xp_to_level(petlevel))/4)); + SetUInt32Value(UNIT_FIELD_PETNEXTLEVELEXP, objmgr.GetXPForLevel(petlevel)/4); learnLevelupSpells(); //these formula may not be correct; however, it is designed to be close to what it should be //this makes dps 0.5 of pets level @@ -1291,22 +1293,42 @@ bool Pet::addSpell(uint16 spell_id, uint16 active, PetSpellState state, PetSpell else newspell->active = active; - uint32 chainstart = spellmgr.GetFirstSpellInChain(spell_id); - - for (PetSpellMap::iterator itr = m_spells.begin(); itr != m_spells.end(); ++itr) + // talent: unlearn all other talent ranks (high and low) + if(TalentSpellPos const* talentPos = GetTalentSpellPos(spell_id)) { - if(itr->second->state == PETSPELL_REMOVED) continue; - - if(spellmgr.GetFirstSpellInChain(itr->first) == chainstart) + if(TalentEntry const *talentInfo = sTalentStore.LookupEntry( talentPos->talent_id )) { - newspell->active = itr->second->active; + for(int i=0; i <5; ++i) + { + // skip learning spell and no rank spell case + uint32 rankSpellId = talentInfo->RankID[i]; + if(!rankSpellId || rankSpellId==spell_id) + continue; - if(newspell->active == ACT_ENABLED) - ToggleAutocast(itr->first, false); + // skip unknown ranks + if(!HasSpell(rankSpellId)) + continue; + removeSpell(rankSpellId); + } + } + } + else if(uint32 chainstart = spellmgr.GetFirstSpellInChain(spell_id)) + { + for (PetSpellMap::iterator itr = m_spells.begin(); itr != m_spells.end(); ++itr) + { + if(itr->second->state == PETSPELL_REMOVED) continue; - oldspell_id = itr->first; - unlearnSpell(itr->first); - break; + if(spellmgr.GetFirstSpellInChain(itr->first) == chainstart) + { + newspell->active = itr->second->active; + + if(newspell->active == ACT_ENABLED) + ToggleAutocast(itr->first, false); + + oldspell_id = itr->first; + unlearnSpell(itr->first); + break; + } } } @@ -1320,6 +1342,15 @@ bool Pet::addSpell(uint16 spell_id, uint16 active, PetSpellState state, PetSpell if(newspell->active == ACT_ENABLED) ToggleAutocast(spell_id, true); + uint32 talentCost = GetTalentSpellCost(spell_id); + if (talentCost) + { + int32 free_points = GetMaxTalentPointsForLevel(getLevel()); + m_usedTalentCount+=talentCost; + // update free talent points + free_points-=m_usedTalentCount; + SetFreeTalentPoints(free_points > 0 ? free_points : 0); + } return true; } @@ -1329,19 +1360,17 @@ bool Pet::learnSpell(uint16 spell_id) if (!addSpell(spell_id)) return false; - if(GetOwner()->GetTypeId() == TYPEID_PLAYER) + Unit* owner = GetOwner(); + if(owner && owner->GetTypeId() == TYPEID_PLAYER) { if(!m_loading) { WorldPacket data(SMSG_PET_LEARNED_SPELL, 2); data << uint16(spell_id); - ((Player*)GetOwner())->GetSession()->SendPacket(&data); + ((Player*)owner)->GetSession()->SendPacket(&data); } - } - - Unit* owner = GetOwner(); - if(owner->GetTypeId() == TYPEID_PLAYER) ((Player*)owner)->PetSpellInitialize(); + } return true; } @@ -1399,6 +1428,18 @@ bool Pet::removeSpell(uint16 spell_id) RemoveAurasDueToSpell(spell_id); + uint32 talentCost = GetTalentSpellCost(spell_id); + if (talentCost > 0) + { + if (m_usedTalentCount > talentCost) + m_usedTalentCount-=talentCost; + else + m_usedTalentCount = 0; + // update free talent points + int32 free_points = GetMaxTalentPointsForLevel(getLevel()) - m_usedTalentCount; + SetFreeTalentPoints(free_points > 0 ? free_points : 0); + } + return true; } @@ -1478,6 +1519,110 @@ void Pet::CheckLearning(uint32 spellid) } } +bool Pet::resetTalents(bool no_cost) +{ + Unit *owner = GetOwner(); + if (!owner || owner->GetTypeId()!=TYPEID_PLAYER) + return false; + + CreatureInfo const * ci = GetCreatureInfo(); + if(!ci) + return false; + // Check pet talent type + CreatureFamilyEntry const *pet_family = sCreatureFamilyStore.LookupEntry(ci->family); + if(!pet_family || pet_family->petTalentType < 0) + return false; + + Player *player = (Player *)owner; + + uint32 level = getLevel(); + uint32 talentPointsForLevel = GetMaxTalentPointsForLevel(level); + + if (m_usedTalentCount == 0) + { + SetFreeTalentPoints(talentPointsForLevel); + return false; + } + + uint32 cost = 0; + + if(!no_cost) + { + cost = resetTalentsCost(); + + if (player->GetMoney() < cost) + { + player->SendBuyError( BUY_ERR_NOT_ENOUGHT_MONEY, 0, 0, 0); + return false; + } + } + + for (unsigned int i = 0; i < sTalentStore.GetNumRows(); i++) + { + TalentEntry const *talentInfo = sTalentStore.LookupEntry(i); + + if (!talentInfo) continue; + + TalentTabEntry const *talentTabInfo = sTalentTabStore.LookupEntry( talentInfo->TalentTab ); + + if(!talentTabInfo) + continue; + + // unlearn only talents for pets family talent type + if(!((1 << pet_family->petTalentType) & talentTabInfo->petTalentMask)) + continue; + + for (int j = 0; j < 5; j++) + { + for(PetSpellMap::iterator itr = m_spells.begin(); itr != m_spells.end();) + { + if(itr->second->state == PETSPELL_REMOVED) + { + ++itr; + continue; + } + // remove learned spells (all ranks) + uint32 itrFirstId = spellmgr.GetFirstSpellInChain(itr->first); + + // unlearn if first rank is talent or learned by talent + if (itrFirstId == talentInfo->RankID[j] || spellmgr.IsSpellLearnToSpell(talentInfo->RankID[j],itrFirstId)) + { + removeSpell(itr->first); + itr = m_spells.begin(); + continue; + } + else + ++itr; + } + } + } + + SetFreeTalentPoints(talentPointsForLevel); + + if(!no_cost) + { + player->ModifyMoney(-(int32)cost); + + m_resetTalentsCost = cost; + m_resetTalentsTime = time(NULL); + } + player->PetSpellInitialize(); + return true; +} + +void Pet::InitTalentForLevel() +{ + uint32 level = getLevel(); + uint32 talentPointsForLevel = GetMaxTalentPointsForLevel(level); + // Reset talents in case low level (on level down) or wrong points for level (hunter can unlearn TP increase talent) + if(talentPointsForLevel == 0 || m_usedTalentCount > talentPointsForLevel) + { + // Remove all talent points + resetTalents(true); + } + SetFreeTalentPoints(talentPointsForLevel - m_usedTalentCount); +} + uint32 Pet::resetTalentsCost() const { uint32 days = (sWorld.GetGameTime() - m_resetTalentsTime)/DAY; @@ -1496,6 +1641,15 @@ uint32 Pet::resetTalentsCost() const return (m_resetTalentsCost + 1*GOLD > 10*GOLD ? 10*GOLD : m_resetTalentsCost + 1*GOLD); } +uint8 Pet::GetMaxTalentPointsForLevel(uint32 level) +{ + uint8 points = (level >= 20) ? ((level - 16) / 4) : 0; + // Mod points from owner SPELL_AURA_MOD_PET_TALENT_POINTS + if (Unit *owner = GetOwner()) + points+=owner->GetTotalAuraModifier(SPELL_AURA_MOD_PET_TALENT_POINTS); + return points; +} + void Pet::ToggleAutocast(uint32 spellid, bool apply) { if(IsPassiveSpell(spellid)) @@ -1555,7 +1709,8 @@ bool Pet::Create(uint32 guidlow, Map *map, uint32 Entry, uint32 pet_number) bool Pet::HasSpell(uint32 spell) const { - return (m_spells.find(spell) != m_spells.end()); + PetSpellMap::const_iterator itr = m_spells.find((uint16)spell); + return (itr != m_spells.end() && itr->second->state != PETSPELL_REMOVED ); } // Get all passive spells in our skill line diff --git a/src/game/Pet.h b/src/game/Pet.h index 383089280..f309bc518 100644 --- a/src/game/Pet.h +++ b/src/game/Pet.h @@ -201,15 +201,20 @@ class Pet : public Creature void InitPetCreateSpells(); void CheckLearning(uint32 spellid); + + bool resetTalents(bool no_cost = false); uint32 resetTalentsCost() const; - uint8 GetMaxTalentPointsForLevel(uint32 level) { return (level >= 20) ? ((level - 16) / 4) : 0; } + void InitTalentForLevel(); + + uint8 GetMaxTalentPointsForLevel(uint32 level); uint8 GetFreeTalentPoints() { return GetByteValue(UNIT_FIELD_BYTES_1, 1); } void SetFreeTalentPoints(uint8 points) { SetByteValue(UNIT_FIELD_BYTES_1, 1, points); } uint32 m_resetTalentsCost; time_t m_resetTalentsTime; + uint32 m_usedTalentCount; - uint64 GetAuraUpdateMask() { return m_auraUpdateMask; } + const uint64& GetAuraUpdateMask() const { return m_auraUpdateMask; } void SetAuraUpdateMask(uint8 slot) { m_auraUpdateMask |= (uint64(1) << slot); } void ResetAuraUpdateMask() { m_auraUpdateMask = 0; } diff --git a/src/game/PetAI.cpp b/src/game/PetAI.cpp index 80613ae2f..ffc843235 100644 --- a/src/game/PetAI.cpp +++ b/src/game/PetAI.cpp @@ -139,11 +139,11 @@ void PetAI::UpdateAI(const uint32 diff) else m_updateAlliesTimer -= diff; - if (inCombat && i_pet.getVictim() == NULL) + if (inCombat && !i_pet.getVictim()) _stopAttack(); // i_pet.getVictim() can't be used for check in case stop fighting, i_pet.getVictim() clear at Unit death etc. - if( i_pet.getVictim() != NULL ) + if( i_pet.getVictim() ) { if( _needToStop() ) { diff --git a/src/game/PetHandler.cpp b/src/game/PetHandler.cpp index a79b6f1d5..274955d64 100644 --- a/src/game/PetHandler.cpp +++ b/src/game/PetHandler.cpp @@ -91,9 +91,7 @@ void WorldSession::HandlePetAction( WorldPacket & recv_data ) break; case COMMAND_ATTACK: //spellid=1792 //ATTACK { - // only place where pet can be player - pet->clearUnitState(UNIT_STAT_FOLLOW); - uint64 selguid = _player->GetSelection(); + const uint64& selguid = _player->GetSelection(); Unit *TargetUnit = ObjectAccessor::GetUnit(*_player, selguid); if(!TargetUnit) return; @@ -105,29 +103,33 @@ void WorldSession::HandlePetAction( WorldPacket & recv_data ) if(!pet->IsWithinLOSInMap(TargetUnit)) return; - if(pet->getVictim()) - pet->AttackStop(); - - if(pet->GetTypeId() != TYPEID_PLAYER) + // This is true if pet has no target or has target but targets differs. + if(pet->getVictim() != TargetUnit) { - pet->GetMotionMaster()->Clear(); - if (((Creature*)pet)->AI()) - ((Creature*)pet)->AI()->AttackStart(TargetUnit); + if (pet->getVictim()) + pet->AttackStop(); - //10% chance to play special pet attack talk, else growl - if(((Creature*)pet)->isPet() && ((Pet*)pet)->getPetType() == SUMMON_PET && pet != TargetUnit && urand(0, 100) < 10) - pet->SendPetTalk((uint32)PET_TALK_ATTACK); - else + if(pet->GetTypeId() != TYPEID_PLAYER) { - // 90% chance for pet and 100% chance for charmed creature + pet->GetMotionMaster()->Clear(); + if (((Creature*)pet)->AI()) + ((Creature*)pet)->AI()->AttackStart(TargetUnit); + + //10% chance to play special pet attack talk, else growl + if(((Creature*)pet)->isPet() && ((Pet*)pet)->getPetType() == SUMMON_PET && pet != TargetUnit && urand(0, 100) < 10) + pet->SendPetTalk((uint32)PET_TALK_ATTACK); + else + { + // 90% chance for pet and 100% chance for charmed creature + pet->SendPetAIReaction(guid1); + } + } + else // charmed player + { + pet->Attack(TargetUnit,true); pet->SendPetAIReaction(guid1); } } - else // charmed player - { - pet->Attack(TargetUnit,true); - pet->SendPetAIReaction(guid1); - } break; } case COMMAND_ABANDON: // abandon (hunter pet) or dismiss (summoned pet) @@ -161,15 +163,13 @@ void WorldSession::HandlePetAction( WorldPacket & recv_data ) case ACT_PASSIVE: // 0x0100 case ACT_ENABLED: // 0xC100 spell { - Unit* unit_target; - if(guid2) - unit_target = ObjectAccessor::GetUnit(*_player,guid2); - else - unit_target = NULL; - + Unit* unit_target = NULL; if (((Creature*)pet)->GetGlobalCooldown() > 0) return; + if(guid2) + unit_target = ObjectAccessor::GetUnit(*_player,guid2); + // do not cast unknown spells SpellEntry const *spellInfo = sSpellStore.LookupEntry(spellid ); if(!spellInfo) @@ -194,7 +194,7 @@ void WorldSession::HandlePetAction( WorldPacket & recv_data ) int16 result = spell->PetCanCast(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)) { pet->SetInFront(unit_target); @@ -225,12 +225,15 @@ void WorldSession::HandlePetAction( WorldPacket & recv_data ) if( unit_target && !GetPlayer()->IsFriendlyTo(unit_target) && !pet->HasAuraType(SPELL_AURA_MOD_POSSESS)) { - pet->clearUnitState(UNIT_STAT_FOLLOW); - if(pet->getVictim()) - pet->AttackStop(); - pet->GetMotionMaster()->Clear(); - if (((Creature*)pet)->AI()) - ((Creature*)pet)->AI()->AttackStart(unit_target); + // This is true if pet has no target or has target but targets differs. + if (pet->getVictim() != unit_target) + { + if (pet->getVictim()) + pet->AttackStop(); + pet->GetMotionMaster()->Clear(); + if (((Creature*)pet)->AI()) + ((Creature*)pet)->AI()->AttackStart(unit_target); + } } spell->prepare(&(spell->m_targets)); @@ -487,11 +490,11 @@ void WorldSession::HandlePetUnlearnOpcode(WorldPacket& recvPacket) sLog.outDetail("CMSG_PET_UNLEARN"); uint64 guid; - recvPacket >> guid; + recvPacket >> guid; // Pet guid Pet* pet = _player->GetPet(); - if(!pet || pet->getPetType() != HUNTER_PET || pet->m_spells.size() <= 1) + if(!pet || pet->getPetType() != HUNTER_PET || pet->m_usedTalentCount == 0) return; if(guid != pet->GetGUID()) @@ -506,37 +509,7 @@ void WorldSession::HandlePetUnlearnOpcode(WorldPacket& recvPacket) sLog.outError("WorldSession::HandlePetUnlearnOpcode: object "I64FMTD" is considered pet-like but doesn't have a charminfo!", pet->GetGUID()); return; } - - uint32 cost = pet->resetTalentsCost(); - - if (GetPlayer()->GetMoney() < cost) - { - GetPlayer()->SendBuyError( BUY_ERR_NOT_ENOUGHT_MONEY, 0, 0, 0); - return; - } - - for(PetSpellMap::iterator itr = pet->m_spells.begin(); itr != pet->m_spells.end();) - { - uint32 spell_id = itr->first; // Pet::removeSpell can invalidate iterator at erase NEW spell - ++itr; - //pet->removeSpell(spell_id); - pet->unlearnSpell(spell_id); - } - - for(uint8 i = 0; i < 10; i++) - { - if(charmInfo->GetActionBarEntry(i)->SpellOrAction && charmInfo->GetActionBarEntry(i)->Type == ACT_ENABLED || charmInfo->GetActionBarEntry(i)->Type == ACT_DISABLED) - charmInfo->GetActionBarEntry(i)->SpellOrAction = 0; - } - - // relearn pet passives - pet->LearnPetPassives(); - - pet->m_resetTalentsTime = time(NULL); - pet->m_resetTalentsCost = cost; - GetPlayer()->ModifyMoney(-(int32)cost); - - GetPlayer()->PetSpellInitialize(); + pet->resetTalents(); } void WorldSession::HandlePetSpellAutocastOpcode( WorldPacket& recvPacket ) @@ -605,10 +578,10 @@ void WorldSession::HandlePetCastSpellOpcode( WorldPacket& recvPacket ) if(!_player->GetPet() && !_player->GetCharm()) return; - if(ObjectAccessor::FindPlayer(guid)) + if (GUID_HIPART(guid) == HIGHGUID_PLAYER) return; - Creature* pet=ObjectAccessor::GetCreatureOrPet(*_player,guid); + Creature* pet = ObjectAccessor::GetCreatureOrPet(*_player,guid); if(!pet || (pet != _player->GetPet() && pet!= _player->GetCharm())) { @@ -809,7 +782,4 @@ void WorldSession::HandlePetLearnTalent( WorldPacket & recv_data ) // learn! (other talent ranks will unlearned at learning) pet->learnSpell(spellid); sLog.outDetail("TalentID: %u Rank: %u Spell: %u\n", talent_id, requested_rank, spellid); - - // update free talent points - pet->SetFreeTalentPoints(CurTalentPoints - 1); } diff --git a/src/game/Player.cpp b/src/game/Player.cpp index 5893d43ed..85de9fe8a 100644 --- a/src/game/Player.cpp +++ b/src/game/Player.cpp @@ -348,7 +348,7 @@ Player::Player (WorldSession *session): Unit(), m_achievementMgr(this) m_regenTimer = 0; m_weaponChangeTimer = 0; m_breathTimer = 0; - m_isunderwater = 0; + m_isunderwater = UNDERWATER_NONE; m_isInWater = false; m_drunkTimer = 0; m_drunk = 0; @@ -422,6 +422,11 @@ Player::Player (WorldSession *session): Unit(), m_achievementMgr(this) for (int i = 0; i < MAX_COMBAT_RATING; i++) m_baseRatingValue[i] = 0; + + m_baseSpellDamage = 0; + m_baseSpellHealing = 0; + m_baseFeralAP = 0; + m_baseManaRegen = 0; // Honor System m_lastHonorUpdateTime = time(NULL); @@ -868,14 +873,15 @@ void Player::EnvironmentalDamage(uint64 guid, EnviromentalDamage type, uint32 da void Player::HandleDrowning() { - if(!m_isunderwater) + if(!(m_isunderwater&~UNDERWATER_INLAVA)) return; //if player is GM, have waterbreath, is dead or if breathing is disabled then return - if(waterbreath || isGameMaster() || !isAlive() || GetSession()->GetSecurity() >= sWorld.getConfig(CONFIG_DISABLE_BREATHING)) + if(isGameMaster() || !isAlive() || HasAuraType(SPELL_AURA_WATER_BREATHING) || GetSession()->GetSecurity() >= sWorld.getConfig(CONFIG_DISABLE_BREATHING)) { StopMirrorTimer(BREATH_TIMER); - m_isunderwater = 0; + // drop every flag _except_ LAVA - otherwise waterbreathing will prevent lava damage + m_isunderwater &= UNDERWATER_INLAVA; return; } @@ -885,22 +891,22 @@ void Player::HandleDrowning() for(AuraList::const_iterator i = mModWaterBreathing.begin(); i != mModWaterBreathing.end(); ++i) UnderWaterTime = uint32(UnderWaterTime * (100.0f + (*i)->GetModifier()->m_amount) / 100.0f); - if ((m_isunderwater & 0x01) && !(m_isunderwater & 0x80) && isAlive()) + if ((m_isunderwater & UNDERWATER_INWATER) && !(m_isunderwater & UNDERWATER_INLAVA) && isAlive()) { //single trigger timer - if (!(m_isunderwater & 0x02)) + if (!(m_isunderwater & UNDERWATER_WATER_TRIGGER)) { - m_isunderwater|= 0x02; + m_isunderwater|= UNDERWATER_WATER_TRIGGER; m_breathTimer = UnderWaterTime + 1000; } - //single trigger "Breathbar" - if ( m_breathTimer <= UnderWaterTime && !(m_isunderwater & 0x04)) + //single trigger "show Breathbar" + if ( m_breathTimer <= UnderWaterTime && !(m_isunderwater & UNDERWATER_WATER_BREATHB)) { - m_isunderwater|= 0x04; + m_isunderwater|= UNDERWATER_WATER_BREATHB; StartMirrorTimer(BREATH_TIMER, UnderWaterTime); } //continuous trigger drowning "Damage" - if ((m_breathTimer == 0) && (m_isunderwater & 0x01)) + if ((m_breathTimer == 0) && (m_isunderwater & UNDERWATER_INWATER)) { //TODO: Check this formula uint64 guid = GetGUID(); @@ -911,33 +917,34 @@ void Player::HandleDrowning() } } //single trigger retract bar - else if (!(m_isunderwater & 0x01) && !(m_isunderwater & 0x08) && (m_isunderwater & 0x02) && (m_breathTimer > 0) && isAlive()) + else if (!(m_isunderwater & UNDERWATER_INWATER) && (m_isunderwater & UNDERWATER_WATER_TRIGGER) && (m_breathTimer > 0) && isAlive()) { - m_isunderwater = 0x08; - uint32 BreathRegen = 10; + // m_breathTimer will be reduced in ModifyMirrorTimer ModifyMirrorTimer(BREATH_TIMER, UnderWaterTime, m_breathTimer,BreathRegen); - m_isunderwater = 0x10; + m_isunderwater = UNDERWATER_WATER_BREATHB_RETRACTING; } //remove bar - else if ((m_breathTimer < 50) && !(m_isunderwater & 0x01) && (m_isunderwater == 0x10)) + else if ((m_breathTimer < 50) && !(m_isunderwater & UNDERWATER_INWATER) && (m_isunderwater == UNDERWATER_WATER_BREATHB_RETRACTING)) { StopMirrorTimer(BREATH_TIMER); - m_isunderwater = 0; + m_isunderwater = UNDERWATER_NONE; } } void Player::HandleLava() { - if ((m_isunderwater & 0x80) && isAlive()) + if ((m_isunderwater & UNDERWATER_INLAVA) && isAlive()) { + /* + * arrai: how is this supposed to work? UNDERWATER_INLAVA is always set in this scope! // Single trigger Set BreathTimer - if (!(m_isunderwater & 0x80)) + if (!(m_isunderwater & UNDERWATER_INLAVA)) { - m_isunderwater|= 0x04; + m_isunderwater|= UNDERWATER_WATER_BREATHB; m_breathTimer = 1000; } - + */ // Reset BreathTimer and still in the lava if (!m_breathTimer) { @@ -951,10 +958,10 @@ void Player::HandleLava() m_breathTimer = 1000; } } - else if (m_deathState == DEAD) // Disable breath timer and reset underwater flags + else if (!isAlive()) // Disable breath timer and reset underwater flags { m_breathTimer = 0; - m_isunderwater = 0; + m_isunderwater = UNDERWATER_NONE; } } @@ -2180,7 +2187,7 @@ void Player::GiveLevel(uint32 level) GetSession()->SendPacket(&data); - SetUInt32Value(PLAYER_NEXT_LEVEL_XP, MaNGOS::XP::xp_to_level(level)); + SetUInt32Value(PLAYER_NEXT_LEVEL_XP, objmgr.GetXPForLevel(level)); //update level, max level of skills if(getLevel()!= level) @@ -2259,7 +2266,7 @@ void Player::InitStatsForLevel(bool reapplyMods) objmgr.GetPlayerLevelInfo(getRace(),getClass(),getLevel(),&info); SetUInt32Value(PLAYER_FIELD_MAX_LEVEL, sWorld.getConfig(CONFIG_MAX_PLAYER_LEVEL) ); - SetUInt32Value(PLAYER_NEXT_LEVEL_XP, MaNGOS::XP::xp_to_level(getLevel())); + SetUInt32Value(PLAYER_NEXT_LEVEL_XP, objmgr.GetXPForLevel(getLevel())); UpdateSkillsForLevel (); @@ -2853,12 +2860,15 @@ void Player::learnSpell(uint32 spell_id) bool learning = addSpell(spell_id,active,true,false); // learn all disabled higher ranks (recursive) - SpellChainMapNext const& nextMap = spellmgr.GetSpellChainNext(); - for(SpellChainMapNext::const_iterator i = nextMap.lower_bound(spell_id); i != nextMap.upper_bound(spell_id); ++i) + if(disabled) { - PlayerSpellMap::iterator iter = m_spells.find(i->second); - if (disabled && iter != m_spells.end() && iter->second->disabled) - learnSpell(i->second); + SpellChainMapNext const& nextMap = spellmgr.GetSpellChainNext(); + for(SpellChainMapNext::const_iterator i = nextMap.lower_bound(spell_id); i != nextMap.upper_bound(spell_id); ++i) + { + PlayerSpellMap::iterator iter = m_spells.find(i->second); + if (iter != m_spells.end() && iter->second->disabled) + learnSpell(i->second); + } } // prevent duplicated entires in spell book, also not send if not in world (loading) @@ -3451,22 +3461,22 @@ TrainerSpellState Player::GetTrainerSpellState(TrainerSpell const* trainer_spell if (!trainer_spell) return TRAINER_SPELL_RED; - if (!trainer_spell->spell) + if (!trainer_spell->learned_spell) return TRAINER_SPELL_RED; // known spell - if(HasSpell(trainer_spell->spell)) + if(HasSpell(trainer_spell->learned_spell)) return TRAINER_SPELL_GRAY; // check race/class requirement - if(!IsSpellFitByClassAndRace(trainer_spell->spell)) + if(!IsSpellFitByClassAndRace(trainer_spell->learned_spell)) return TRAINER_SPELL_RED; // check level requirement if(getLevel() < trainer_spell->reqlevel) return TRAINER_SPELL_RED; - if(SpellChainNode const* spell_chain = spellmgr.GetSpellChainNode(trainer_spell->spell)) + if(SpellChainNode const* spell_chain = spellmgr.GetSpellChainNode(trainer_spell->learned_spell)) { // check prev.rank requirement if(spell_chain->prev && !HasSpell(spell_chain->prev)) @@ -3482,7 +3492,7 @@ TrainerSpellState Player::GetTrainerSpellState(TrainerSpell const* trainer_spell return TRAINER_SPELL_RED; // exist, already checked at loading - SpellEntry const* spell = sSpellStore.LookupEntry(trainer_spell->spell); + SpellEntry const* spell = sSpellStore.LookupEntry(trainer_spell->learned_spell); // secondary prof. or not prof. spell uint32 skill = spell->EffectMiscValue[1]; @@ -4527,7 +4537,7 @@ void Player::ApplyRatingMod(CombatRating cr, int32 value, bool apply) AuraList const& modRatingFromStat = GetAurasByType(SPELL_AURA_MOD_RATING_FROM_STAT); for(AuraList::const_iterator i = modRatingFromStat.begin();i != modRatingFromStat.end(); ++i) if ((*i)->GetMiscValue() & (1<GetMiscBValue())) * (*i)->GetModifier()->m_amount / 100.0f; + amount += int32(GetStat(Stats((*i)->GetMiscBValue())) * (*i)->GetModifier()->m_amount / 100.0f); if (amount < 0) amount = 0; SetUInt32Value(PLAYER_FIELD_COMBAT_RATING_1 + cr, uint32(amount)); @@ -4929,7 +4939,7 @@ void Player::UpdateSkillsToMaxSkillsForLevel() if (GetUInt32Value(PLAYER_SKILL_INDEX(i))) { uint32 pskill = GetUInt32Value(PLAYER_SKILL_INDEX(i)) & 0x0000FFFF; - if( IsProfessionSkill(pskill) || pskill == SKILL_RIDING ) + if( IsProfessionOrRidingSkill(pskill)) continue; uint32 data = GetUInt32Value(PLAYER_SKILL_VALUE_INDEX(i)); @@ -5124,6 +5134,22 @@ uint16 Player::GetPureSkillValue(uint32 skill) const return 0; } +int16 Player::GetSkillPermBonusValue(uint32 skill) const +{ + if(!skill) + return 0; + + for (int i = 0; i < PLAYER_MAX_SKILLS; i++) + { + if ((GetUInt32Value(PLAYER_SKILL_INDEX(i)) & 0x0000FFFF) == skill) + { + return SKILL_PERM_BONUS(GetUInt32Value(PLAYER_SKILL_BONUS_INDEX(i))); + } + } + + return 0; +} + int16 Player::GetSkillTempBonusValue(uint32 skill) const { if(!skill) @@ -5312,7 +5338,7 @@ void Player::CheckExploreSystem() if(offset >= 128) { - sLog.outError("ERROR: Wrong area flag %u in map data for (X: %f Y: %f) point to field PLAYER_EXPLORED_ZONES_1 + %u ( %u must be < 64 ).",areaFlag,GetPositionX(),GetPositionY(),offset,offset); + sLog.outError("ERROR: Wrong area flag %u in map data for (X: %f Y: %f) point to field PLAYER_EXPLORED_ZONES_1 + %u ( %u must be < 128 ).",areaFlag,GetPositionX(),GetPositionY(),offset,offset); return; } @@ -6477,7 +6503,7 @@ void Player::_ApplyItemBonuses(ItemPrototype const *proto, uint8 slot, bool appl uint32 level = ((getLevel() > ssd->MaxLevel) ? ssd->MaxLevel : getLevel()); if(ScalingStatValuesEntry const *ssv = sScalingStatValuesStore.LookupEntry(level)) { - int multiplier = ssv->Multiplier[proto->GetScalingStatValuesColumn()]; + uint32 multiplier = ssv->Multiplier[proto->GetScalingStatValuesColumn()]; val = (multiplier * modifier) / 10000; } } @@ -6486,7 +6512,7 @@ void Player::_ApplyItemBonuses(ItemPrototype const *proto, uint8 slot, bool appl else { statType = proto->ItemStat[i].ItemStatType; - val = float(proto->ItemStat[i].ItemStatValue); + val = proto->ItemStat[i].ItemStatValue; } if(val == 0) @@ -6610,9 +6636,31 @@ void Player::_ApplyItemBonuses(ItemPrototype const *proto, uint8 slot, bool appl case ITEM_MOD_EXPERTISE_RATING: ApplyRatingMod(CR_EXPERTISE, int32(val), apply); break; + case ITEM_MOD_ATTACK_POWER: + HandleStatModifier(UNIT_MOD_ATTACK_POWER, TOTAL_VALUE, float(val), apply); + break; + case ITEM_MOD_RANGED_ATTACK_POWER: + HandleStatModifier(UNIT_MOD_ATTACK_POWER_RANGED, TOTAL_VALUE, float(val), apply); + break; + case ITEM_MOD_FERAL_ATTACK_POWER: + ApplyFeralAPBonus(int32(val), apply); + break; + case ITEM_MOD_SPELL_HEALING_DONE: + ApplySpellHealingBonus(int32(val), apply); + break; + case ITEM_MOD_SPELL_DAMAGE_DONE: + ApplySpellDamageBonus(int32(val), apply); + break; + case ITEM_MOD_MANA_REGENERATION: + ApplyManaRegenBonus(int32(val), apply); + break; case ITEM_MOD_ARMOR_PENETRATION_RATING: ApplyRatingMod(CR_ARMOR_PENETRATION, int32(val), apply); break; + case ITEM_MOD_SPELL_POWER: + ApplySpellHealingBonus(int32(val), apply); + ApplySpellDamageBonus(int32(val), apply); + break; } } @@ -6945,6 +6993,92 @@ void Player::CastItemCombatSpell(Item *item,Unit* Target, WeaponAttackType attTy } } +void Player::CastItemUseSpell(Item *item,SpellCastTargets const& targets,uint8 cast_count, uint32 glyphIndex) +{ + ItemPrototype const* proto = item->GetProto(); + // special learning case + if(proto->Spells[0].SpellId==SPELL_ID_GENERIC_LEARN || proto->Spells[0].SpellId==SPELL_ID_GENERIC_LEARN_PET) + { + uint32 learn_spell_id = proto->Spells[0].SpellId; + uint32 learning_spell_id = proto->Spells[1].SpellId; + + SpellEntry const *spellInfo = sSpellStore.LookupEntry(learn_spell_id); + if(!spellInfo) + { + sLog.outError("Player::CastItemUseSpell: Item (Entry: %u) in have wrong spell id %u, ignoring ",proto->ItemId, learn_spell_id); + SendEquipError(EQUIP_ERR_NONE,item,NULL); + return; + } + + Spell *spell = new Spell(this, spellInfo, false); + spell->m_CastItem = item; + spell->m_cast_count = cast_count; //set count of casts + spell->m_currentBasePoints[0] = learning_spell_id; + spell->prepare(&targets); + return; + } + + // use triggered flag only for items with many spell casts and for not first cast + int count = 0; + + // item spells casted at use + for(int i = 0; i < 5; ++i) + { + _Spell const& spellData = proto->Spells[i]; + + // no spell + if(!spellData.SpellId) + continue; + + // wrong triggering type + if( spellData.SpellTrigger != ITEM_SPELLTRIGGER_ON_USE && spellData.SpellTrigger != ITEM_SPELLTRIGGER_ON_NO_DELAY_USE) + continue; + + SpellEntry const *spellInfo = sSpellStore.LookupEntry(spellData.SpellId); + if(!spellInfo) + { + sLog.outError("Player::CastItemUseSpell: Item (Entry: %u) in have wrong spell id %u, ignoring",proto->ItemId, spellData.SpellId); + continue; + } + + Spell *spell = new Spell(this, spellInfo, (count > 0)); + spell->m_CastItem = item; + spell->m_cast_count = cast_count; // set count of casts + spell->m_glyphIndex = glyphIndex; // glyph index + spell->prepare(&targets); + + ++count; + } + + // Item enchantments spells casted at use + for(int e_slot = 0; e_slot < MAX_ENCHANTMENT_SLOT; ++e_slot) + { + uint32 enchant_id = item->GetEnchantmentId(EnchantmentSlot(e_slot)); + SpellItemEnchantmentEntry const *pEnchant = sSpellItemEnchantmentStore.LookupEntry(enchant_id); + if(!pEnchant) continue; + for (int s=0;s<3;s++) + { + if(pEnchant->type[s]!=ITEM_ENCHANTMENT_TYPE_USE_SPELL) + continue; + + SpellEntry const *spellInfo = sSpellStore.LookupEntry(pEnchant->spellid[s]); + if (!spellInfo) + { + sLog.outError("Player::CastItemUseSpell Enchant %i, cast unknown spell %i", pEnchant->ID, pEnchant->spellid[s]); + continue; + } + + Spell *spell = new Spell(this, spellInfo, (count > 0)); + spell->m_CastItem = item; + spell->m_cast_count = cast_count; // set count of casts + spell->m_glyphIndex = glyphIndex; // glyph index + spell->prepare(&targets); + + ++count; + } + } +} + void Player::_RemoveAllItemMods() { sLog.outDebug("_RemoveAllItemMods start."); @@ -11847,10 +11981,39 @@ void Player::ApplyEnchantment(Item *item,EnchantmentSlot slot,bool apply, bool a ((Player*)this)->ApplyRatingMod(CR_EXPERTISE, enchant_amount, apply); sLog.outDebug("+ %u EXPERTISE", enchant_amount); break; + case ITEM_MOD_ATTACK_POWER: + HandleStatModifier(UNIT_MOD_ATTACK_POWER, TOTAL_VALUE, float(enchant_amount), apply); + sLog.outDebug("+ %u ATTACK_POWER", enchant_amount); + break; + case ITEM_MOD_RANGED_ATTACK_POWER: + HandleStatModifier(UNIT_MOD_ATTACK_POWER_RANGED, TOTAL_VALUE, float(enchant_amount), apply); + sLog.outDebug("+ %u RANGED_ATTACK_POWER", enchant_amount); + break; + case ITEM_MOD_FERAL_ATTACK_POWER: + ((Player*)this)->ApplyFeralAPBonus(enchant_amount, apply); + sLog.outDebug("+ %u FERAL_ATTACK_POWER", enchant_amount); + break; + case ITEM_MOD_SPELL_HEALING_DONE: + ((Player*)this)->ApplySpellHealingBonus(enchant_amount, apply); + sLog.outDebug("+ %u SPELL_HEALING_DONE", enchant_amount); + break; + case ITEM_MOD_SPELL_DAMAGE_DONE: + ((Player*)this)->ApplySpellDamageBonus(enchant_amount, apply); + sLog.outDebug("+ %u SPELL_DAMAGE_DONE", enchant_amount); + break; + case ITEM_MOD_MANA_REGENERATION: + ((Player*)this)->ApplyManaRegenBonus(enchant_amount, apply); + sLog.outDebug("+ %u MANA_REGENERATION", enchant_amount); + break; case ITEM_MOD_ARMOR_PENETRATION_RATING: ((Player*)this)->ApplyRatingMod(CR_ARMOR_PENETRATION, enchant_amount, apply); sLog.outDebug("+ %u ARMOR PENETRATION", enchant_amount); break; + case ITEM_MOD_SPELL_POWER: + ((Player*)this)->ApplySpellHealingBonus(enchant_amount, apply); + ((Player*)this)->ApplySpellDamageBonus(enchant_amount, apply); + sLog.outDebug("+ %u SPELL_POWER", enchant_amount); + break; default: break; } @@ -11874,6 +12037,9 @@ void Player::ApplyEnchantment(Item *item,EnchantmentSlot slot,bool apply, bool a } break; } + case ITEM_ENCHANTMENT_TYPE_USE_SPELL: + // processed in Player::CastItemUseSpell + break; default: sLog.outError("Unknown item enchantment display type: %d",enchant_display_type); break; @@ -14098,12 +14264,12 @@ bool Player::LoadFromDB( uint32 guid, SqlQueryHolder *holder ) // clear charm/summon related fields SetCharm(NULL); SetPet(NULL); - SetCharmerGUID(NULL); - SetOwnerGUID(NULL); - SetCreatorGUID(NULL); + SetCharmerGUID(0); + SetOwnerGUID(0); + SetCreatorGUID(0); // reset some aura modifiers before aura apply - SetFarSight(NULL); + SetFarSightGUID(0); SetUInt32Value(PLAYER_TRACK_CREATURES, 0 ); SetUInt32Value(PLAYER_TRACK_RESOURCES, 0 ); @@ -14151,6 +14317,7 @@ bool Player::LoadFromDB( uint32 guid, SqlQueryHolder *holder ) //_LoadMail(); _LoadAuras(holder->GetResult(PLAYER_LOGIN_QUERY_LOADAURAS), time_diff); + _LoadGlyphAuras(); // add ghost flag (must be after aura load: PLAYER_FLAGS_GHOST set in aura) if( HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_GHOST) ) @@ -14430,6 +14597,36 @@ void Player::_LoadAuras(QueryResult *result, uint32 timediff) CastSpell(this,SPELL_ID_PASSIVE_BATTLE_STANCE,true); } +void Player::_LoadGlyphAuras() +{ + for (uint8 i = 0; i <= MAX_GLYPH_SLOT_INDEX; ++i) + { + if (uint32 glyph = GetGlyph(i)) + { + if (GlyphPropertiesEntry const *gp = sGlyphPropertiesStore.LookupEntry(glyph)) + { + if (GlyphSlotEntry const *gs = sGlyphSlotStore.LookupEntry(GetGlyphSlot(i))) + { + if(gp->TypeFlags == gs->TypeFlags) + { + CastSpell(this, gp->SpellId, true); + continue; + } + else + sLog.outError("Player %s has glyph with typeflags %u in slot with typeflags %u, removing.", m_name.c_str(), gp->TypeFlags, gs->TypeFlags); + } + else + sLog.outError("Player %s has not existing glyph slot entry %u on index %u", m_name.c_str(), GetGlyphSlot(i), i); + } + else + sLog.outError("Player %s has not existing glyph entry %u on index %u", m_name.c_str(), glyph, i); + + // On any error remove glyph + SetGlyph(i, 0); + } + } +} + void Player::LoadCorpse() { if( isAlive() ) @@ -18206,18 +18403,23 @@ bool Player::IsSpellFitByClassAndRace( uint32 spell_id ) const SkillLineAbilityMap::const_iterator lower = spellmgr.GetBeginSkillLineAbilityMap(spell_id); SkillLineAbilityMap::const_iterator upper = spellmgr.GetEndSkillLineAbilityMap(spell_id); + if(lower==upper) + return true; for(SkillLineAbilityMap::const_iterator _spell_idx = lower; _spell_idx != upper; ++_spell_idx) { // skip wrong race skills if( _spell_idx->second->racemask && (_spell_idx->second->racemask & racemask) == 0) - return false; + continue; // skip wrong class skills if( _spell_idx->second->classmask && (_spell_idx->second->classmask & classmask) == 0) - return false; + continue; + + return true; } - return true; + + return false; } bool Player::HasQuestForGO(int32 GOId) @@ -18841,18 +19043,20 @@ PartyResult Player::CanUninviteFromGroup() const void Player::UpdateUnderwaterState( Map* m, float x, float y, float z ) { float water_z = m->GetWaterLevel(x,y); - float height_z = m->GetHeight(x,y,z, false); // use .map base surface height + float terrain_z = m->GetHeight(x,y,z, false); // use .map base surface height uint8 flag1 = m->GetTerrainType(x,y); - //!Underwater check, not in water if underground or above water level - if (height_z <= INVALID_HEIGHT || z < (height_z-2) || z > (water_z - 2) ) - m_isunderwater &= 0x7A; + //!Underwater check, not in water if underground or above water level - take UC royal quater for example + if (terrain_z <= INVALID_HEIGHT || z < (terrain_z-2) || z > (water_z - 2) ) + m_isunderwater &= ~UNDERWATER_INWATER; else if ((z < (water_z - 2)) && (flag1 & 0x01)) - m_isunderwater |= 0x01; + m_isunderwater |= UNDERWATER_INWATER; //!in lava check, anywhere under lava level - if ((height_z <= INVALID_HEIGHT || z < (height_z - 0)) && (flag1 == 0x00) && IsInWater()) - m_isunderwater |= 0x80; + if ((terrain_z <= INVALID_HEIGHT || z < (terrain_z - 0)) && (flag1 == 0x00) && IsInWater()) + m_isunderwater |= UNDERWATER_INLAVA; + else + m_isunderwater &= ~UNDERWATER_INLAVA; } void Player::SetCanParry( bool value ) @@ -18963,11 +19167,11 @@ void Player::EnterVehicle(Vehicle *vehicle) vehicle->SetCharmerGUID(GetGUID()); vehicle->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_SPELLCLICK); - vehicle->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_UNKNOWN5); + vehicle->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_UNK_24); vehicle->setFaction(getFaction()); SetCharm(vehicle); // charm - SetFarSight(vehicle->GetGUID()); // set view + SetFarSightGUID(vehicle->GetGUID()); // set view SetClientControl(vehicle, 1); // redirect controls to vehicle @@ -19014,11 +19218,11 @@ void Player::ExitVehicle(Vehicle *vehicle) { vehicle->SetCharmerGUID(0); vehicle->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_SPELLCLICK); - vehicle->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_UNKNOWN5); + vehicle->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_UNK_24); vehicle->setFaction((GetTeam() == ALLIANCE) ? vehicle->GetCreatureInfo()->faction_A : vehicle->GetCreatureInfo()->faction_H); SetCharm(NULL); - SetFarSight(NULL); + SetFarSightGUID(0); SetClientControl(vehicle, 0); @@ -19109,3 +19313,23 @@ void Player::InitRunes() for(uint32 i = 0; i < NUM_RUNE_TYPES; ++i) SetFloatValue(PLAYER_RUNE_REGEN_1 + i, 0.1f); } + +void Player::AutoStoreLootItem(uint8 bag, uint8 slot, uint32 loot_id, LootStore const& store) +{ + Loot loot; + loot.FillLoot (loot_id,store,this); + if(loot.items.empty ()) + return; + LootItem const* lootItem = &loot.items[0]; + + ItemPosCountVec dest; + uint8 msg = CanStoreNewItem (bag,slot,dest,lootItem->itemid,lootItem->count); + if(msg != EQUIP_ERR_OK && slot != NULL_SLOT) + msg = CanStoreNewItem( bag, NULL_SLOT,dest,lootItem->itemid,lootItem->count); + if( msg != EQUIP_ERR_OK && bag != NULL_BAG) + msg = CanStoreNewItem( NULL_BAG, NULL_SLOT,dest,lootItem->itemid,lootItem->count); + if(msg != EQUIP_ERR_OK) + return; + + StoreNewItem (dest,lootItem->itemid,true,lootItem->randomPropertyId); +} diff --git a/src/game/Player.h b/src/game/Player.h index 659f70bb8..acf2a1c1c 100644 --- a/src/game/Player.h +++ b/src/game/Player.h @@ -46,6 +46,7 @@ class Pet; class PlayerMenu; class Transport; class UpdateMask; +class SpellCastTargets; class PlayerSocial; class AchievementMgr; class Vehicle; @@ -62,6 +63,17 @@ enum SpellModType SPELLMOD_PCT = 108 // SPELL_AURA_ADD_PCT_MODIFIER }; +// 2^n values, Player::m_isunderwater is a bitmask. These are mangos internal values, they are never send to any client +enum PlayerUnderwaterState +{ + UNDERWATER_NONE = 0x00, + UNDERWATER_INWATER = 0x01, // terrain type is water and player is afflicted by it + UNDERWATER_WATER_TRIGGER = 0x02, // m_breathTimer has been initialized + UNDERWATER_WATER_BREATHB = 0x04, // breathbar has been send to client + UNDERWATER_WATER_BREATHB_RETRACTING = 0x10, // breathbar is currently refilling - the player is above water level + UNDERWATER_INLAVA = 0x80 // terrain type is lava and player is afflicted by it +}; + enum PlayerSpellState { PLAYERSPELL_UNCHANGED = 0, @@ -427,6 +439,13 @@ enum PlayerFlags PLAYER_FLAGS_UNK17 = 0x00010000, // pre-3.0.3 PLAYER_FLAGS_SANCTUARY flag for player entered sanctuary PLAYER_FLAGS_UNK18 = 0x00020000, // taxi benchmark mode (on/off) (2.0.1) PLAYER_FLAGS_PVP_TIMER = 0x00040000, // 3.0.2, pvp timer active (after you disable pvp manually) + PLAYER_FLAGS_UNK20 = 0x00080000, + PLAYER_FLAGS_UNK21 = 0x00100000, + PLAYER_FLAGS_UNK22 = 0x00200000, + PLAYER_FLAGS_UNK23 = 0x00400000, + PLAYER_FLAGS_UNK24 = 0x00800000, // disabled all abilitys on tab except autoattack + PLAYER_FLAGS_UNK25 = 0x01000000, // disabled all melee ability on tab include autoattack + }; // used for PLAYER__FIELD_KNOWN_TITLES field (uint64), (1<second; - - return NULL; + return itr != mMitems.end() ? itr->second : NULL; } void AddMItem(Item* it) @@ -1450,12 +1468,7 @@ class MANGOS_DLL_SPEC Player : public Unit bool RemoveMItem(uint32 id) { - ItemMap::iterator i = mMitems.find(id); - if (i == mMitems.end()) - return false; - - mMitems.erase(i); - return true; + return mMitems.erase(id) ? true : false; } void PetSpellInitialize(); @@ -1625,9 +1638,12 @@ class MANGOS_DLL_SPEC Player : public Unit void UpdateArmor(); void UpdateMaxHealth(); void UpdateMaxPower(Powers power); + void ApplyFeralAPBonus(int32 amount, bool apply); void UpdateAttackPowerAndDamage(bool ranged = false); void UpdateShieldBlockValue(); void UpdateDamagePhysical(WeaponAttackType attType); + void ApplySpellDamageBonus(int32 amount, bool apply); + void ApplySpellHealingBonus(int32 amount, bool apply); void UpdateSpellDamageAndHealingBonus(); void CalculateMinMaxDamage(WeaponAttackType attType, bool normalized, float& min_damage, float& max_damage); @@ -1645,6 +1661,8 @@ class MANGOS_DLL_SPEC Player : public Unit uint32 GetRangedCritDamageReduction(uint32 damage) const; uint32 GetSpellCritDamageReduction(uint32 damage) const; uint32 GetDotDamageReduction(uint32 damage) const; + uint32 GetBaseSpellDamageBonus() { return m_baseSpellDamage;} + uint32 GetBaseSpellHealingBonus() { return m_baseSpellHealing;} float GetExpertiseDodgeOrParryReduction(WeaponAttackType attType) const; void UpdateBlockPercentage(); @@ -1659,6 +1677,7 @@ class MANGOS_DLL_SPEC Player : public Unit void UpdateAllSpellCritChances(); void UpdateSpellCritChance(uint32 school); void UpdateExpertise(WeaponAttackType attType); + void ApplyManaRegenBonus(int32 amount, bool apply); void UpdateManaRegen(); const uint64& GetLootGUID() const { return m_lootGuid; } @@ -1739,11 +1758,12 @@ class MANGOS_DLL_SPEC Player : public Unit void UpdateCombatSkills(Unit *pVictim, WeaponAttackType attType, bool defence); void SetSkill(uint32 id, uint16 currVal, uint16 maxVal); - uint16 GetMaxSkillValue(uint32 skill) const; // max + perm. bonus + uint16 GetMaxSkillValue(uint32 skill) const; // max + perm. bonus + temp bonus uint16 GetPureMaxSkillValue(uint32 skill) const; // max uint16 GetSkillValue(uint32 skill) const; // skill value + perm. bonus + temp bonus uint16 GetBaseSkillValue(uint32 skill) const; // skill value + perm. bonus uint16 GetPureSkillValue(uint32 skill) const; // skill value + int16 GetSkillPermBonusValue(uint32 skill) const; int16 GetSkillTempBonusValue(uint32 skill) const; bool HasSkill(uint32 skill) const; void learnSkillRewardedSpells( uint32 id ); @@ -1860,6 +1880,7 @@ class MANGOS_DLL_SPEC Player : public Unit void ApplyEquipSpell(SpellEntry const* spellInfo, Item* item, bool apply, bool form_change = false); void UpdateEquipSpellsAtFormChange(); void CastItemCombatSpell(Item *item,Unit* Target, WeaponAttackType attType); + void CastItemUseSpell(Item *item,SpellCastTargets const& targets,uint8 cast_count, uint32 glyphIndex); void SendInitWorldStates(); void SendUpdateWorldState(uint32 Field, uint32 Value); @@ -2037,7 +2058,7 @@ class MANGOS_DLL_SPEC Player : public Unit void ExitVehicle(Vehicle *vehicle); uint64 GetFarSight() const { return GetUInt64Value(PLAYER_FARSIGHT); } - void SetFarSight(uint64 guid) { SetUInt64Value(PLAYER_FARSIGHT, guid); } + void SetFarSightGUID(uint64 guid) { SetUInt64Value(PLAYER_FARSIGHT, guid); } // Transports Transport * GetTransport() const { return m_transport; } @@ -2131,9 +2152,9 @@ class MANGOS_DLL_SPEC Player : public Unit GroupReference& GetGroupRef() { return m_group; } void SetGroup(Group *group, int8 subgroup = -1); uint8 GetSubGroup() const { return m_group.getSubGroup(); } - uint32 GetGroupUpdateFlag() { return m_groupUpdateMask; } + uint32 GetGroupUpdateFlag() const { return m_groupUpdateMask; } void SetGroupUpdateFlag(uint32 flag) { m_groupUpdateMask |= flag; } - uint64 GetAuraUpdateMask() { return m_auraUpdateMask; } + const uint64& GetAuraUpdateMask() const { return m_auraUpdateMask; } void SetAuraUpdateMask(uint8 slot) { m_auraUpdateMask |= (uint64(1) << slot); } Player* GetNextRandomRaidMember(float radius); PartyResult CanUninviteFromGroup() const; @@ -2207,6 +2228,7 @@ class MANGOS_DLL_SPEC Player : public Unit void _LoadActions(QueryResult *result); void _LoadAuras(QueryResult *result, uint32 timediff); + void _LoadGlyphAuras(); void _LoadBoundInstances(QueryResult *result); void _LoadInventory(QueryResult *result, uint32 timediff); void _LoadMailInit(QueryResult *resultUnread, QueryResult *resultDelivery); @@ -2295,6 +2317,10 @@ class MANGOS_DLL_SPEC Player : public Unit float m_auraBaseMod[BASEMOD_END][MOD_END]; int16 m_baseRatingValue[MAX_COMBAT_RATING]; + uint16 m_baseSpellDamage; + uint16 m_baseSpellHealing; + uint16 m_baseFeralAP; + uint16 m_baseManaRegen; SpellModList m_spellMods[MAX_SPELLMOD]; int32 m_SpellModRemoveCount; diff --git a/src/game/SharedDefines.h b/src/game/SharedDefines.h index 84b0899ce..08c9f8be6 100644 --- a/src/game/SharedDefines.h +++ b/src/game/SharedDefines.h @@ -252,7 +252,7 @@ enum ItemQualities #define SPELL_ATTR_EX_NEGATIVE 0x00000080 // 7 #define SPELL_ATTR_EX_NOT_IN_COMBAT_TARGET 0x00000100 // 8 Spell req target not to be in combat state #define SPELL_ATTR_EX_UNK9 0x00000200 // 9 -#define SPELL_ATTR_EX_UNK10 0x00000400 // 10 +#define SPELL_ATTR_EX_NO_INITIAL_AGGRO 0x00000400 // 10 no generates threat on cast 100% #define SPELL_ATTR_EX_UNK11 0x00000800 // 11 #define SPELL_ATTR_EX_UNK12 0x00001000 // 12 #define SPELL_ATTR_EX_UNK13 0x00002000 // 13 @@ -303,7 +303,7 @@ enum ItemQualities #define SPELL_ATTR_EX2_UNK25 0x02000000 // 25 #define SPELL_ATTR_EX2_UNK26 0x04000000 // 26 unaffected by school immunity #define SPELL_ATTR_EX2_UNK27 0x08000000 // 27 -#define SPELL_ATTR_EX2_UNK28 0x10000000 // 28 +#define SPELL_ATTR_EX2_UNK28 0x10000000 // 28 no breaks stealth if it fails?? #define SPELL_ATTR_EX2_CANT_CRIT 0x20000000 // 29 Spell can't crit #define SPELL_ATTR_EX2_UNK30 0x40000000 // 30 #define SPELL_ATTR_EX2_UNK31 0x80000000 // 31 @@ -324,8 +324,8 @@ enum ItemQualities #define SPELL_ATTR_EX3_UNK13 0x00002000 // 13 #define SPELL_ATTR_EX3_UNK14 0x00004000 // 14 "Honorless Target" only this spells have this flag #define SPELL_ATTR_EX3_UNK15 0x00008000 // 15 Auto Shoot, Shoot, Throw, - this is autoshot flag -#define SPELL_ATTR_EX3_UNK16 0x00010000 // 16 -#define SPELL_ATTR_EX3_NO_INITIAL_AGGRO 0x00020000 // 17 no initial aggro +#define SPELL_ATTR_EX3_UNK16 0x00010000 // 16 no triggers effects that trigger on casting a spell?? +#define SPELL_ATTR_EX3_UNK17 0x00020000 // 17 no triggers effects that trigger on casting a spell?? #define SPELL_ATTR_EX3_UNK18 0x00040000 // 18 #define SPELL_ATTR_EX3_UNK19 0x00080000 // 19 #define SPELL_ATTR_EX3_DEATH_PERSISTENT 0x00100000 // 20 Death persistent spells @@ -333,7 +333,7 @@ enum ItemQualities #define SPELL_ATTR_EX3_REQ_WAND 0x00400000 // 22 Req wand #define SPELL_ATTR_EX3_UNK23 0x00800000 // 23 #define SPELL_ATTR_EX3_REQ_OFFHAND 0x01000000 // 24 Req offhand weapon -#define SPELL_ATTR_EX3_UNK25 0x02000000 // 25 +#define SPELL_ATTR_EX3_UNK25 0x02000000 // 25 no cause spell pushback ? #define SPELL_ATTR_EX3_UNK26 0x04000000 // 26 #define SPELL_ATTR_EX3_UNK27 0x08000000 // 27 #define SPELL_ATTR_EX3_UNK28 0x10000000 // 28 @@ -345,7 +345,7 @@ enum ItemQualities #define SPELL_ATTR_EX4_UNK1 0x00000002 // 1 proc on finishing move? #define SPELL_ATTR_EX4_UNK2 0x00000004 // 2 #define SPELL_ATTR_EX4_UNK3 0x00000008 // 3 -#define SPELL_ATTR_EX4_UNK4 0x00000010 // 4 +#define SPELL_ATTR_EX4_UNK4 0x00000010 // 4 This will no longer cause guards to attack on use?? #define SPELL_ATTR_EX4_UNK5 0x00000020 // 5 #define SPELL_ATTR_EX4_UNK6 0x00000040 // 6 #define SPELL_ATTR_EX4_UNK7 0x00000080 // 7 @@ -440,6 +440,8 @@ enum ItemQualities #define SPELL_ATTR_EX6_UNK30 0x40000000 // 30 not set in 3.0.3 #define SPELL_ATTR_EX6_UNK31 0x80000000 // 31 not set in 3.0.3 +#define MAX_GLYPH_SLOT_INDEX 5 + enum SheathTypes { SHEATHETYPE_NONE = 0, @@ -673,7 +675,7 @@ enum SpellEffects SPELL_EFFECT_154 = 154, SPELL_EFFECT_TITAN_GRIP = 155, SPELL_EFFECT_ADD_SOCKET = 156, - SPELL_EFFECT_157 = 157, + SPELL_EFFECT_CREATE_ITEM_2 = 157, SPELL_EFFECT_MILLING = 158, SPELL_EFFECT_ALLOW_RENAME_PET = 159, TOTAL_SPELL_EFFECTS = 160 diff --git a/src/game/SkillDiscovery.cpp b/src/game/SkillDiscovery.cpp index 7a2281428..9e2ba8f6f 100644 --- a/src/game/SkillDiscovery.cpp +++ b/src/game/SkillDiscovery.cpp @@ -29,14 +29,15 @@ struct SkillDiscoveryEntry { - uint32 spellId; - float chance; + uint32 spellId; // discavered spell + uint32 reqSkillValue; // skill level limitation + float chance; // chance SkillDiscoveryEntry() - : spellId(0), chance(0) {} + : spellId(0), reqSkillValue(0), chance(0) {} - SkillDiscoveryEntry(uint16 _spellId, float _chance) - : spellId(_spellId), chance(_chance) {} + SkillDiscoveryEntry(uint16 _spellId, uint32 req_skill_val, float _chance) + : spellId(_spellId), reqSkillValue(req_skill_val), chance(_chance) {} }; typedef std::list SkillDiscoveryList; @@ -51,8 +52,8 @@ void LoadSkillDiscoveryTable() uint32 count = 0; - // 0 1 2 - QueryResult *result = WorldDatabase.Query("SELECT spellId, reqSpell, chance FROM skill_discovery_template"); + // 0 1 2 3 + QueryResult *result = WorldDatabase.Query("SELECT spellId, reqSpell, reqSkillValue, chance FROM skill_discovery_template"); if (result) { @@ -67,11 +68,13 @@ void LoadSkillDiscoveryTable() uint32 spellId = fields[0].GetUInt32(); int32 reqSkillOrSpell = fields[1].GetInt32(); - float chance = fields[2].GetFloat(); + uint32 reqSkillValue = fields[2].GetInt32(); + float chance = fields[3].GetFloat(); if( chance <= 0 ) // chance { - ssNonDiscoverableEntries << "spellId = " << spellId << " reqSkillOrSpell = " << reqSkillOrSpell << " chance = " << chance << "\n"; + ssNonDiscoverableEntries << "spellId = " << spellId << " reqSkillOrSpell = " << reqSkillOrSpell + << " reqSkillValue = " << reqSkillValue << " chance = " << chance << "(chance problem)\n"; continue; } @@ -84,13 +87,16 @@ void LoadSkillDiscoveryTable() continue; } - if( spellEntry->Mechanic != MECHANIC_DISCOVERY ) + // mechanic discovery + if (spellEntry->Mechanic != MECHANIC_DISCOVERY && + // explicit discovery ability + !IsExplicitDiscoverySpell(spellEntry)) { - sLog.outErrorDb("Spell (ID: %u) not have have MECHANIC_DISCOVERY (28) value in Mechanic field in spell.dbc but listed in `skill_discovery_template` table",spellId); + sLog.outErrorDb("Spell (ID: %u) not have have MECHANIC_DISCOVERY (28) value in Mechanic field in spell.dbc and not 100% chance random discovery ability but listed in `skill_discovery_template` table",spellId); continue; } - SkillDiscoveryStore[reqSkillOrSpell].push_back( SkillDiscoveryEntry(spellId, chance) ); + SkillDiscoveryStore[reqSkillOrSpell].push_back( SkillDiscoveryEntry(spellId, reqSkillValue, chance) ); } else if( reqSkillOrSpell == 0 ) // skill case { @@ -105,7 +111,7 @@ void LoadSkillDiscoveryTable() for(SkillLineAbilityMap::const_iterator _spell_idx = lower; _spell_idx != upper; ++_spell_idx) { - SkillDiscoveryStore[-int32(_spell_idx->second->skillId)].push_back( SkillDiscoveryEntry(spellId, chance) ); + SkillDiscoveryStore[-int32(_spell_idx->second->skillId)].push_back( SkillDiscoveryEntry(spellId, reqSkillValue, chance) ); } } else @@ -113,6 +119,7 @@ void LoadSkillDiscoveryTable() sLog.outErrorDb("Spell (ID: %u) have negative value in `reqSpell` field in `skill_discovery_template` table",spellId); continue; } + ++count; } while (result->NextRow()); @@ -130,8 +137,48 @@ void LoadSkillDiscoveryTable() } } +uint32 GetExplicitDiscoverySpell(uint32 spellId, Player* player) +{ + // explicit discovery spell chances (always success if case exist) + // in this case we have both skill and spell + SkillDiscoveryMap::iterator tab = SkillDiscoveryStore.find(spellId); + if(tab == SkillDiscoveryStore.end()) + return 0; + + SkillLineAbilityMap::const_iterator lower = spellmgr.GetBeginSkillLineAbilityMap(spellId); + SkillLineAbilityMap::const_iterator upper = spellmgr.GetEndSkillLineAbilityMap(spellId); + uint32 skillvalue = lower != upper ? player->GetSkillValue(lower->second->skillId) : 0; + + float full_chance = 0; + for(SkillDiscoveryList::iterator item_iter = tab->second.begin(); item_iter != tab->second.end(); ++item_iter) + if(item_iter->reqSkillValue <= skillvalue) + if(!player->HasSpell(item_iter->spellId)) + full_chance += item_iter->chance; + + float rate = full_chance / 100.0f; + float roll = rand_chance() * rate; // roll now in range 0..full_chance + + for(SkillDiscoveryList::iterator item_iter = tab->second.begin(); item_iter != tab->second.end(); ++item_iter) + { + if(item_iter->reqSkillValue > skillvalue) + continue; + + if(player->HasSpell(item_iter->spellId)) + continue; + + if(item_iter->chance > roll) + return item_iter->spellId; + + roll -= item_iter->chance; + } + + return 0; +} + uint32 GetSkillDiscoverySpell(uint32 skillId, uint32 spellId, Player* player) { + uint32 skillvalue = skillId ? player->GetSkillValue(skillId) : 0; + // check spell case SkillDiscoveryMap::iterator tab = SkillDiscoveryStore.find(spellId); @@ -140,6 +187,7 @@ uint32 GetSkillDiscoverySpell(uint32 skillId, uint32 spellId, Player* player) for(SkillDiscoveryList::iterator item_iter = tab->second.begin(); item_iter != tab->second.end(); ++item_iter) { if( roll_chance_f(item_iter->chance * sWorld.getRate(RATE_SKILL_DISCOVERY)) + && item_iter->reqSkillValue <= skillvalue && !player->HasSpell(item_iter->spellId) ) return item_iter->spellId; } @@ -147,6 +195,9 @@ uint32 GetSkillDiscoverySpell(uint32 skillId, uint32 spellId, Player* player) return 0; } + if(!skillId) + return 0; + // check skill line case tab = SkillDiscoveryStore.find(-(int32)skillId); if(tab != SkillDiscoveryStore.end()) @@ -154,6 +205,7 @@ uint32 GetSkillDiscoverySpell(uint32 skillId, uint32 spellId, Player* player) for(SkillDiscoveryList::iterator item_iter = tab->second.begin(); item_iter != tab->second.end(); ++item_iter) { if( roll_chance_f(item_iter->chance * sWorld.getRate(RATE_SKILL_DISCOVERY)) + && item_iter->reqSkillValue <= skillvalue && !player->HasSpell(item_iter->spellId) ) return item_iter->spellId; } diff --git a/src/game/SkillDiscovery.h b/src/game/SkillDiscovery.h index 781712662..2d4f1bded 100644 --- a/src/game/SkillDiscovery.h +++ b/src/game/SkillDiscovery.h @@ -25,4 +25,5 @@ class Player; void LoadSkillDiscoveryTable(); uint32 GetSkillDiscoverySpell(uint32 skillId, uint32 spellId, Player* player); +uint32 GetExplicitDiscoverySpell(uint32 spellId, Player* player); #endif diff --git a/src/game/SocialMgr.cpp b/src/game/SocialMgr.cpp index b7dba46a9..e620e8881 100644 --- a/src/game/SocialMgr.cpp +++ b/src/game/SocialMgr.cpp @@ -180,13 +180,6 @@ SocialMgr::~SocialMgr() } -void SocialMgr::RemovePlayerSocial(uint32 guid) -{ - SocialMap::iterator itr = m_socialMap.find(guid); - if(itr != m_socialMap.end()) - m_socialMap.erase(itr); -} - void SocialMgr::GetFriendInfo(Player *player, uint32 friendGUID, FriendInfo &friendInfo) { if(!player) diff --git a/src/game/SocialMgr.h b/src/game/SocialMgr.h index a06cde39a..d76d44625 100644 --- a/src/game/SocialMgr.h +++ b/src/game/SocialMgr.h @@ -141,7 +141,8 @@ class SocialMgr SocialMgr(); ~SocialMgr(); // Misc - void RemovePlayerSocial(uint32 guid); + void RemovePlayerSocial(uint32 guid) { m_socialMap.erase(guid); } + void GetFriendInfo(Player *player, uint32 friendGUID, FriendInfo &friendInfo); // Packet management void MakeFriendStatusPacket(FriendsResult result, uint32 friend_guid, WorldPacket *data); diff --git a/src/game/Spell.cpp b/src/game/Spell.cpp index a80590bdb..1a672c2ab 100644 --- a/src/game/Spell.cpp +++ b/src/game/Spell.cpp @@ -682,19 +682,23 @@ void Spell::prepareDataForTriggerSystem() // Ñan spell trigger another or not ( m_canTrigger ) // Create base triggers flags for Attacker and Victim ( m_procAttacker and m_procVictim) //========================================================================================== - // Fill flag can spell trigger or not - if (!m_IsTriggeredSpell) + // TODO: possible exist spell attribute for this + m_canTrigger = false; + + if (m_CastItem) + m_canTrigger = false; // Do not trigger from item cast spell + else if (!m_IsTriggeredSpell) m_canTrigger = true; // Normal cast - can trigger else if (!m_triggeredByAuraSpell) m_canTrigger = true; // Triggered from SPELL_EFFECT_TRIGGER_SPELL - can trigger - else // Exceptions (some periodic triggers) + + if (!m_canTrigger) // Exceptions (some periodic triggers) { - m_canTrigger = false; // Triggered spells can`t trigger another switch (m_spellInfo->SpellFamilyName) { - case SPELLFAMILY_MAGE: // Arcane Missles triggers need do it - if (m_spellInfo->SpellFamilyFlags & 0x0000000000200000LL) m_canTrigger = true; + case SPELLFAMILY_MAGE: // Arcane Missles / Blizzard triggers need do it + if (m_spellInfo->SpellFamilyFlags & 0x0000000000200080LL) m_canTrigger = true; break; case SPELLFAMILY_WARLOCK: // For Hellfire Effect / Rain of Fire / Seed of Corruption triggers need do it if (m_spellInfo->SpellFamilyFlags & 0x0000800000000060LL) m_canTrigger = true; @@ -702,17 +706,17 @@ void Spell::prepareDataForTriggerSystem() case SPELLFAMILY_PRIEST: // For Penance heal/damage triggers need do it if (m_spellInfo->SpellFamilyFlags & 0x0001800000000000LL) m_canTrigger = true; break; - case SPELLFAMILY_HUNTER: // Hunter Explosive Trap Effect/Immolation Trap Effect/Frost Trap Aura/Snake Trap Effect - if (m_spellInfo->SpellFamilyFlags & 0x0000200000000014LL) m_canTrigger = true; + case SPELLFAMILY_ROGUE: // For poisons need do it + if (m_spellInfo->SpellFamilyFlags & 0x000000101001E000LL) m_canTrigger = true; + break; + case SPELLFAMILY_HUNTER: // Hunter Rapid Killing/Explosive Trap Effect/Immolation Trap Effect/Frost Trap Aura/Snake Trap Effect + if (m_spellInfo->SpellFamilyFlags & 0x0100200000000014LL) m_canTrigger = true; break; case SPELLFAMILY_PALADIN: // For Holy Shock triggers need do it if (m_spellInfo->SpellFamilyFlags & 0x0001000000200000LL) m_canTrigger = true; break; } } - // Do not trigger from item cast spell - if (m_CastItem) - m_canTrigger = false; // Get data for type of attack and fill base info for trigger switch (m_spellInfo->DmgClass) @@ -763,8 +767,6 @@ void Spell::CleanupTargetList() m_UniqueTargetInfo.clear(); m_UniqueGOTargetInfo.clear(); m_UniqueItemInfo.clear(); - m_countOfHit = 0; - m_countOfMiss = 0; m_delayMoment = 0; } @@ -773,6 +775,9 @@ void Spell::AddUnitTarget(Unit* pVictim, uint32 effIndex) if( m_spellInfo->Effect[effIndex]==0 ) return; + // Check for effect immune skip if immuned + bool immuned = pVictim->IsImmunedToSpellEffect(m_spellInfo, effIndex); + uint64 targetGUID = pVictim->GetGUID(); // Lookup target in already in list @@ -780,7 +785,8 @@ void Spell::AddUnitTarget(Unit* pVictim, uint32 effIndex) { if (targetGUID == ihit->targetGUID) // Found in list { - ihit->effectMask |= 1<effectMask |= 1<SpellHitResult(pVictim, m_spellInfo, m_canReflect); - if (target.missCondition == SPELL_MISS_NONE) - ++m_countOfHit; - else - ++m_countOfMiss; // Spell have speed - need calculate incoming time if (m_spellInfo->speed > 0.0f) @@ -878,8 +880,6 @@ void Spell::AddGOTarget(GameObject* pVictim, uint32 effIndex) else target.timeDelay = 0LL; - ++m_countOfHit; - // Add target to list m_UniqueGOTargetInfo.push_back(target); } @@ -922,8 +922,6 @@ void Spell::DoAllEffectOnTarget(TargetInfo *target) // Get mask of effects for target uint32 mask = target->effectMask; - if (mask == 0) // No effects - return; Unit* unit = m_caster->GetGUID()==target->targetGUID ? m_caster : ObjectAccessor::GetUnit(*m_caster,target->targetGUID); if (!unit) @@ -1101,30 +1099,24 @@ void Spell::DoSpellHitOnUnit(Unit *unit, const uint32 effectMask) return; } - // exclude Arcane Missiles Dummy Aura aura for now (attack on hit) - // TODO: find way to not need this? - if(!(m_spellInfo->SpellFamilyName == SPELLFAMILY_MAGE && - m_spellInfo->SpellFamilyFlags & 0x800LL)) + unit->RemoveSpellsCausingAura(SPELL_AURA_MOD_STEALTH); + + if( !(m_spellInfo->AttributesEx & SPELL_ATTR_EX_NO_INITIAL_AGGRO) ) { - unit->RemoveSpellsCausingAura(SPELL_AURA_MOD_STEALTH); + if(!unit->IsStandState() && !unit->hasUnitState(UNIT_STAT_STUNNED)) + unit->SetStandState(PLAYER_STATE_NONE); - if( !(m_spellInfo->AttributesEx3 & SPELL_ATTR_EX3_NO_INITIAL_AGGRO) ) + if(!unit->isInCombat() && unit->GetTypeId() != TYPEID_PLAYER && ((Creature*)unit)->AI()) + ((Creature*)unit)->AI()->AttackStart(m_caster); + + unit->SetInCombatWith(m_caster); + m_caster->SetInCombatWith(unit); + + if(Player *attackedPlayer = unit->GetCharmerOrOwnerPlayerOrPlayerItself()) { - if(!unit->IsStandState() && !unit->hasUnitState(UNIT_STAT_STUNNED)) - unit->SetStandState(PLAYER_STATE_NONE); - - if(!unit->isInCombat() && unit->GetTypeId() != TYPEID_PLAYER && ((Creature*)unit)->AI()) - ((Creature*)unit)->AI()->AttackStart(m_caster); - - unit->SetInCombatWith(m_caster); - m_caster->SetInCombatWith(unit); - - if(Player *attackedPlayer = unit->GetCharmerOrOwnerPlayerOrPlayerItself()) - { - m_caster->SetContestedPvP(attackedPlayer); - } - unit->AddThreat(m_caster, 0.0f); + m_caster->SetContestedPvP(attackedPlayer); } + unit->AddThreat(m_caster, 0.0f); } } else @@ -1139,7 +1131,7 @@ void Spell::DoSpellHitOnUnit(Unit *unit, const uint32 effectMask) // assisting case, healing and resurrection if(unit->hasUnitState(UNIT_STAT_ATTACK_PLAYER)) m_caster->SetContestedPvP(); - if( unit->isInCombat() && !(m_spellInfo->AttributesEx3 & SPELL_ATTR_EX3_NO_INITIAL_AGGRO) ) + if( unit->isInCombat() && !(m_spellInfo->AttributesEx & SPELL_ATTR_EX_NO_INITIAL_AGGRO) ) { m_caster->SetInCombatState(unit->GetCombatTimer() > 0); unit->getHostilRefManager().threatAssist(m_caster, 0.0f); @@ -2046,7 +2038,7 @@ void Spell::SetTargetMap(uint32 i,uint32 cur,std::list &TagUnitMap) } } -void Spell::prepare(SpellCastTargets * targets, Aura* triggeredByAura) +void Spell::prepare(SpellCastTargets const* targets, Aura* triggeredByAura) { m_targets = *targets; @@ -2997,7 +2989,23 @@ void Spell::WriteAmmoToPacket( WorldPacket * data ) void Spell::WriteSpellGoTargets( WorldPacket * data ) { - *data << (uint8)m_countOfHit; + uint32 hit = m_UniqueGOTargetInfo.size(); // Always hits on GO + uint32 miss = 0; + for(std::list::iterator ihit= m_UniqueTargetInfo.begin();ihit != m_UniqueTargetInfo.end();++ihit) + { + if ((*ihit).effectMask == 0) // No effect apply - all immuned add state + { + // possibly SPELL_MISS_IMMUNE2 for this?? + ihit->missCondition = SPELL_MISS_IMMUNE2; + miss++; + } + else if ((*ihit).missCondition == SPELL_MISS_NONE) + hit++; + else + miss++; + } + + *data << (uint8)hit; for(std::list::iterator ihit= m_UniqueTargetInfo.begin();ihit != m_UniqueTargetInfo.end();++ihit) if ((*ihit).missCondition == SPELL_MISS_NONE) // Add only hits *data << uint64(ihit->targetGUID); @@ -3005,7 +3013,7 @@ void Spell::WriteSpellGoTargets( WorldPacket * data ) for(std::list::iterator ighit= m_UniqueGOTargetInfo.begin();ighit != m_UniqueGOTargetInfo.end();++ighit) *data << uint64(ighit->targetGUID); // Always hits - *data << (uint8)m_countOfMiss; + *data << (uint8)miss; for(std::list::iterator ihit= m_UniqueTargetInfo.begin();ihit != m_UniqueTargetInfo.end();++ihit) { if( ihit->missCondition != SPELL_MISS_NONE ) // Add only miss @@ -3080,7 +3088,7 @@ void Spell::SendLogExecute() data << uint8(0); break; case SPELL_EFFECT_CREATE_ITEM: - case SPELL_EFFECT_157: + case SPELL_EFFECT_CREATE_ITEM_2: data << uint32(m_spellInfo->EffectItemType[0]); break; case SPELL_EFFECT_SUMMON: @@ -3513,16 +3521,11 @@ void Spell::HandleEffects(Unit *pUnitTarget,Item *pItemTarget,GameObject *pGOTar gameObjTarget = pGOTarget; uint8 eff = m_spellInfo->Effect[i]; - uint32 mechanic = m_spellInfo->EffectMechanic[i]; damage = int32(CalculateDamage((uint8)i,unitTarget)*DamageMultiplier); sLog.outDebug( "Spell: Effect : %u", eff); - //Simply return. Do not display "immune" in red text on client - if(unitTarget && unitTarget->IsImmunedToSpellEffect(eff, mechanic)) - return; - if(effGetTypeId()==TYPEID_PLAYER) // Target - is player caster + { + // Additional check for some spells + // If 0 spell effect empty - client not send target data (need use selection) + // TODO: check it on next client version + if (m_targets.m_targetMask == TARGET_FLAG_SELF && + m_spellInfo->Effect[0] == 0 && m_spellInfo->EffectImplicitTargetA[1] != TARGET_SELF) + { + if (target = m_caster->GetUnit(*m_caster, ((Player *)m_caster)->GetSelection())) + m_targets.setUnitTarget(target); + else + return SPELL_FAILED_BAD_TARGETS; + } + } // check pet presents for(int j=0;j<3;j++) diff --git a/src/game/Spell.h b/src/game/Spell.h index e32e32d1f..bbe50f5c0 100644 --- a/src/game/Spell.h +++ b/src/game/Spell.h @@ -321,7 +321,7 @@ class Spell Spell( Unit* Caster, SpellEntry const *info, bool triggered, uint64 originalCasterGUID = 0, Spell** triggeringContainer = NULL ); ~Spell(); - void prepare(SpellCastTargets * targets, Aura* triggeredByAura = NULL); + void prepare(SpellCastTargets const* targets, Aura* triggeredByAura = NULL); void cancel(); void update(uint32 difftime); void cast(bool skipCheck = false); @@ -354,11 +354,10 @@ class Spell bool HaveTargetsForEffect(uint8 effect) const; void Delayed(); void DelayedChannel(); - inline uint32 getState() const { return m_spellState; } + uint32 getState() const { return m_spellState; } void setState(uint32 state) { m_spellState = state; } void DoCreateItem(uint32 i, uint32 itemtype); - void WriteSpellGoTargets( WorldPacket * data ); void WriteAmmoToPacket( WorldPacket * data ); void FillTargetMap(); @@ -497,8 +496,6 @@ class Spell // Spell target subsystem //***************************************** // Targets store structures and data - uint32 m_countOfHit; - uint32 m_countOfMiss; struct TargetInfo { uint64 targetGUID; diff --git a/src/game/SpellAuraDefines.h b/src/game/SpellAuraDefines.h index 5d401b2f2..31c331458 100644 --- a/src/game/SpellAuraDefines.h +++ b/src/game/SpellAuraDefines.h @@ -187,8 +187,8 @@ enum AuraType SPELL_AURA_MOD_BASE_RESISTANCE_PCT = 142, SPELL_AURA_MOD_RESISTANCE_EXCLUSIVE = 143, SPELL_AURA_SAFE_FALL = 144, - SPELL_AURA_CHARISMA = 145, - SPELL_AURA_PERSUADED = 146, + SPELL_AURA_MOD_PET_TALENT_POINTS = 145, + SPELL_AURA_ALLOW_TAME_PET_TYPE = 146, SPELL_AURA_ADD_CREATURE_IMMUNITY = 147, SPELL_AURA_RETAIN_COMBO_POINTS = 148, SPELL_AURA_RESIST_PUSHBACK = 149, // Resist Pushback @@ -313,7 +313,7 @@ enum AuraType SPELL_AURA_MOD_ATTACK_POWER_OF_STAT_PERCENT = 268, SPELL_AURA_269 = 269, SPELL_AURA_270 = 270, - SPELL_AURA_271 = 271, + SPELL_AURA_MOD_DAMAGE_FROM_CASTER = 271, SPELL_AURA_272 = 272, SPELL_AURA_273 = 273, SPELL_AURA_274 = 274, diff --git a/src/game/SpellAuras.cpp b/src/game/SpellAuras.cpp index 79358118c..42b008a63 100644 --- a/src/game/SpellAuras.cpp +++ b/src/game/SpellAuras.cpp @@ -195,8 +195,8 @@ pAuraHandler AuraHandler[TOTAL_AURAS]= &Aura::HandleAuraModBaseResistancePCT, //142 SPELL_AURA_MOD_BASE_RESISTANCE_PCT &Aura::HandleAuraModResistanceExclusive, //143 SPELL_AURA_MOD_RESISTANCE_EXCLUSIVE &Aura::HandleNoImmediateEffect, //144 SPELL_AURA_SAFE_FALL implemented in WorldSession::HandleMovementOpcodes - &Aura::HandleUnused, //145 SPELL_AURA_CHARISMA obsolete? - &Aura::HandleUnused, //146 SPELL_AURA_PERSUADED obsolete? + &Aura::HandleAuraModPetTalentsPoints, //145 SPELL_AURA_MOD_PET_TALENT_POINTS + &Aura::HandleNoImmediateEffect, //146 SPELL_AURA_ALLOW_TAME_PET_TYPE &Aura::HandleNULL, //147 SPELL_AURA_ADD_CREATURE_IMMUNITY &Aura::HandleAuraRetainComboPoints, //148 SPELL_AURA_RETAIN_COMBO_POINTS &Aura::HandleNoImmediateEffect, //149 SPELL_AURA_RESIST_PUSHBACK @@ -321,7 +321,7 @@ pAuraHandler AuraHandler[TOTAL_AURAS]= &Aura::HandleAuraModAttackPowerOfStatPercent, //268 SPELL_AURA_MOD_ATTACK_POWER_OF_STAT_PERCENT &Aura::HandleNULL, //269 ignore DR effects? &Aura::HandleNULL, //270 - &Aura::HandleNULL, //271 increase damage done? + &Aura::HandleNoImmediateEffect, //271 SPELL_AURA_MOD_DAMAGE_FROM_CASTER implemented in Unit::SpellDamageBonus &Aura::HandleNULL, //272 reduce spell cast time? &Aura::HandleNULL, //273 &Aura::HandleNULL, //274 proc free shot? @@ -941,10 +941,6 @@ void Aura::_AddAura() break; } - // register aura - if (getDiminishGroup() != DIMINISHING_NONE ) - m_target->ApplyDiminishingAura(getDiminishGroup(),true); - Unit* caster = GetCaster(); // passive auras (except totem auras) do not get placed in the slots @@ -967,8 +963,12 @@ void Aura::_AddAura() //***************************************************** if (!secondaura) { + // register aura diminishing on apply + if (getDiminishGroup() != DIMINISHING_NONE ) + m_target->ApplyDiminishingAura(getDiminishGroup(),true); + // Update Seals information - if( IsSealSpell(GetSpellProto()) ) + if (IsSealSpell(m_spellProto)) m_target->ModifyAuraState(AURA_STATE_JUDGEMENT, true); // Conflagrate aura state on Immolate @@ -976,15 +976,15 @@ void Aura::_AddAura() m_target->ModifyAuraState(AURA_STATE_IMMOLATE, true); // Faerie Fire (druid versions) - if( m_spellProto->SpellFamilyName == SPELLFAMILY_DRUID && m_spellProto->SpellFamilyFlags & 0x0000000000000400LL) + if (m_spellProto->SpellFamilyName == SPELLFAMILY_DRUID && m_spellProto->SpellFamilyFlags & 0x0000000000000400LL) m_target->ModifyAuraState(AURA_STATE_FAERIE_FIRE, true); // Victorious - if( m_spellProto->SpellFamilyName == SPELLFAMILY_WARRIOR && m_spellProto->SpellFamilyFlags & 0x0004000000000000LL) + if (m_spellProto->SpellFamilyName == SPELLFAMILY_WARRIOR && m_spellProto->SpellFamilyFlags & 0x0004000000000000LL) m_target->ModifyAuraState(AURA_STATE_WARRIOR_VICTORY_RUSH, true); // Swiftmend state on Regrowth & Rejuvenation - if(m_spellProto->SpellFamilyName == SPELLFAMILY_DRUID && m_spellProto->SpellFamilyFlags & 0x50 ) + if (m_spellProto->SpellFamilyName == SPELLFAMILY_DRUID && m_spellProto->SpellFamilyFlags & 0x50 ) m_target->ModifyAuraState(AURA_STATE_SWIFTMEND, true); // Deadly poison aura state @@ -1010,10 +1010,6 @@ void Aura::_RemoveAura() dynObj->RemoveAffected(m_target); } - // unregister aura - if (getDiminishGroup() != DIMINISHING_NONE ) - m_target->ApplyDiminishingAura(getDiminishGroup(),false); - //passive auras do not get put in slots // Note: but totem can be not accessible for aura target in time remove (to far for find in grid) //if(m_isPassive && !(caster && caster->GetTypeId() == TYPEID_UNIT && ((Creature*)caster)->isTotem())) @@ -1048,6 +1044,10 @@ void Aura::_RemoveAura() // only remove icon when the last aura of the spell is removed (current aura already removed from list) if (lastaura) { + // unregister aura diminishing (and store last time) + if (getDiminishGroup() != DIMINISHING_NONE ) + m_target->ApplyDiminishingAura(getDiminishGroup(),false); + SetAura(true); SetAuraFlags(AFLAG_NONE); SetAuraLevel(0); @@ -1058,59 +1058,55 @@ void Aura::_RemoveAura() //***************************************************** // Update target aura state flag (at last aura remove) - // TODO: Make it easer //***************************************************** - // Update Seals information - if( IsSealSpell(GetSpellProto()) ) - m_target->ModifyAuraState(AURA_STATE_JUDGEMENT,false); - - // Conflagrate aura state - if (GetSpellProto()->SpellFamilyName == SPELLFAMILY_WARLOCK && (GetSpellProto()->SpellFamilyFlags & 4)) - m_target->ModifyAuraState(AURA_STATE_IMMOLATE, false); - - // Faerie Fire (druid versions) - if( m_spellProto->SpellFamilyName == SPELLFAMILY_DRUID && m_spellProto->SpellFamilyFlags & 0x0000000000000400LL) - m_target->ModifyAuraState(AURA_STATE_FAERIE_FIRE, false); - - // Victorious - if( m_spellProto->SpellFamilyName == SPELLFAMILY_WARRIOR && m_spellProto->SpellFamilyFlags & 0x0004000000000000LL) - m_target->ModifyAuraState(AURA_STATE_WARRIOR_VICTORY_RUSH, false); - - // Swiftmend aura state - if(GetSpellProto()->SpellFamilyName == SPELLFAMILY_DRUID && GetSpellProto()->SpellFamilyFlags & 0x50) + uint32 removeState = 0; + switch(m_spellProto->SpellFamilyName) { - bool found = false; - Unit::AuraList const& RejorRegr = m_target->GetAurasByType(SPELL_AURA_PERIODIC_HEAL); - for(Unit::AuraList::const_iterator i = RejorRegr.begin(); i != RejorRegr.end(); ++i) - { - if((*i)->GetSpellProto()->SpellFamilyName == SPELLFAMILY_DRUID && (*i)->GetSpellProto()->SpellFamilyFlags & 0x50 ) - { - found = true; - break; - } - } - if(!found) - m_target->ModifyAuraState(AURA_STATE_SWIFTMEND, false); + case SPELLFAMILY_PALADIN: + if (IsSealSpell(m_spellProto)) + removeState = AURA_STATE_JUDGEMENT; // Update Seals information + break; + case SPELLFAMILY_WARLOCK: + if(m_spellProto->SpellFamilyFlags & 4) + removeState = AURA_STATE_IMMOLATE; // Conflagrate aura state + break; + case SPELLFAMILY_DRUID: + if(m_spellProto->SpellFamilyFlags & 0x0000000000000400LL) + removeState = AURA_STATE_FAERIE_FIRE; // Faerie Fire (druid versions) + else if(m_spellProto->SpellFamilyFlags & 0x50) + removeState = AURA_STATE_SWIFTMEND; // Swiftmend aura state + break; + case SPELLFAMILY_WARRIOR: + if(m_spellProto->SpellFamilyFlags & 0x0004000000000000LL) + removeState = AURA_STATE_WARRIOR_VICTORY_RUSH; // Victorious + break; + case SPELLFAMILY_ROGUE: + if(m_spellProto->SpellFamilyFlags & 0x10000) + removeState = AURA_STATE_DEADLY_POISON; // Deadly poison aura state + break; + case SPELLFAMILY_HUNTER: + if(m_spellProto->SpellFamilyFlags & 0x1000000000000000LL) + removeState = AURA_STATE_FAERIE_FIRE; // Sting (hunter versions) + } - - // Deadly poison aura state - if(m_spellProto->SpellFamilyName == SPELLFAMILY_ROGUE && m_spellProto->SpellFamilyFlags & 0x10000) + // Remove state (but need check other auras for it) + if (removeState) { - // current aura already removed, search present of another bool found = false; - Unit::AuraList const& auras = m_target->GetAurasByType(SPELL_AURA_PERIODIC_DAMAGE); - for(Unit::AuraList::const_iterator itr = auras.begin(); itr != auras.end(); ++itr) + Unit::AuraMap& Auras = m_target->GetAuras(); + for(Unit::AuraMap::iterator i = Auras.begin(); i != Auras.end(); ++i) { - SpellEntry const* itr_spell = (*itr)->GetSpellProto(); - if(itr_spell && itr_spell->SpellFamilyName==SPELLFAMILY_ROGUE && itr_spell->SpellFamilyFlags & 0x10000) + SpellEntry const *auraSpellInfo = (*i).second->GetSpellProto(); + if(auraSpellInfo->SpellFamilyName == m_spellProto->SpellFamilyName && + auraSpellInfo->SpellFamilyFlags == m_spellProto->SpellFamilyFlags ) { found = true; break; } } - // this has been last deadly poison aura + // this has been last aura if(!found) - m_target->ModifyAuraState(AURA_STATE_DEADLY_POISON,false); + m_target->ModifyAuraState(AuraState(removeState), false); } // reset cooldown state for spells @@ -2085,7 +2081,7 @@ void Aura::HandleAuraDummy(bool apply, bool Real) ( GetSpellProto()->EffectApplyAuraName[0]==1 || GetSpellProto()->EffectApplyAuraName[0]==128 ) ) ) { // spells with SpellEffect=72 and aura=4: 6196, 6197, 21171, 21425 - ((Player*)m_target)->SetFarSight(NULL); + ((Player*)m_target)->SetFarSightGUID(0); WorldPacket data(SMSG_CLEAR_FAR_SIGHT_IMMEDIATE, 0); ((Player*)m_target)->GetSession()->SendPacket(&data); return; @@ -2499,12 +2495,8 @@ void Aura::HandleAuraHover(bool apply, bool Real) void Aura::HandleWaterBreathing(bool apply, bool Real) { - if(apply) - m_target->waterbreath = true; - else if(m_target->GetAurasByType(SPELL_AURA_WATER_BREATHING).empty()) + if(!apply && !m_target->HasAuraType(SPELL_AURA_WATER_BREATHING)) { - m_target->waterbreath = false; - // update for enable timer in case not moving target if(m_target->GetTypeId()==TYPEID_PLAYER && m_target->IsInWorld()) { @@ -2975,7 +2967,7 @@ void Aura::HandleBindSight(bool apply, bool Real) if(!caster || caster->GetTypeId() != TYPEID_PLAYER) return; - ((Player*)caster)->SetFarSight(apply ? m_target->GetGUID() : NULL); + ((Player*)caster)->SetFarSightGUID(apply ? m_target->GetGUID() : 0); } void Aura::HandleFarSight(bool apply, bool Real) @@ -2984,7 +2976,7 @@ void Aura::HandleFarSight(bool apply, bool Real) if(!caster || caster->GetTypeId() != TYPEID_PLAYER) return; - ((Player*)caster)->SetFarSight(apply ? m_target->GetGUID() : NULL); + ((Player*)caster)->SetFarSightGUID(apply ? m_target->GetGUID() : 0); } void Aura::HandleAuraTrackCreatures(bool apply, bool Real) @@ -3091,7 +3083,7 @@ void Aura::HandleModPossess(bool apply, bool Real) } } if(caster->GetTypeId() == TYPEID_PLAYER) - ((Player*)caster)->SetFarSight(apply ? m_target->GetGUID() : NULL); + ((Player*)caster)->SetFarSightGUID(apply ? m_target->GetGUID() : 0); } void Aura::HandleModPossessPet(bool apply, bool Real) @@ -3108,11 +3100,11 @@ void Aura::HandleModPossessPet(bool apply, bool Real) return; if(apply) - pet->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_UNKNOWN5); + pet->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_UNK_24); else - pet->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_UNKNOWN5); + pet->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_UNK_24); - ((Player*)caster)->SetFarSight(apply ? pet->GetGUID() : NULL); + ((Player*)caster)->SetFarSightGUID(apply ? pet->GetGUID() : NULL); ((Player*)caster)->SetCharm(apply ? pet : NULL); ((Player*)caster)->SetClientControl(pet, apply ? 1 : 0); @@ -3130,6 +3122,16 @@ void Aura::HandleModPossessPet(bool apply, bool Real) } } +void Aura::HandleAuraModPetTalentsPoints(bool Apply, bool Real) +{ + if(!Real) + return; + + // Recalculate pet tlaent points + if (Pet *pet=m_target->GetPet()) + pet->InitTalentForLevel(); +} + void Aura::HandleModCharm(bool apply, bool Real) { if(!Real) @@ -3271,7 +3273,7 @@ void Aura::HandleFeignDeath(bool apply, bool Real) m_target->SendMessageToSet(&data,true); */ // blizz like 2.0.x - m_target->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_UNKNOWN6); + m_target->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_UNK_29); // blizz like 2.0.x m_target->SetFlag(UNIT_FIELD_FLAGS_2, UNIT_FLAG2_FEIGN_DEATH); // blizz like 2.0.x @@ -3295,7 +3297,7 @@ void Aura::HandleFeignDeath(bool apply, bool Real) m_target->SendMessageToSet(&data,true); */ // blizz like 2.0.x - m_target->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_UNKNOWN6); + m_target->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_UNK_29); // blizz like 2.0.x m_target->RemoveFlag(UNIT_FIELD_FLAGS_2, UNIT_FLAG2_FEIGN_DEATH); // blizz like 2.0.x @@ -3433,10 +3435,6 @@ void Aura::HandleModStealth(bool apply, bool Real) m_target->SetVisibility(VISIBILITY_GROUP_NO_DETECT); m_target->SetVisibility(VISIBILITY_GROUP_STEALTH); } - - // for RACE_NIGHTELF stealth - if(m_target->GetTypeId()==TYPEID_PLAYER && GetId()==20580) - m_target->CastSpell(m_target, 21009, true, NULL, this); } } else @@ -3444,10 +3442,6 @@ void Aura::HandleModStealth(bool apply, bool Real) // only at real aura remove if(Real) { - // for RACE_NIGHTELF stealth - if(m_target->GetTypeId()==TYPEID_PLAYER && GetId()==20580) - m_target->RemoveAurasDueToSpell(21009); - // if last SPELL_AURA_MOD_STEALTH and no GM invisibility if(!m_target->HasAuraType(SPELL_AURA_MOD_STEALTH) && m_target->GetVisibility()!=VISIBILITY_OFF) { @@ -6559,7 +6553,7 @@ void Aura::PeriodicDummyTick() if (!caster) return; // Skip 0 tick - if (m_duration < m_modifier.periodictime) + if (m_duration > m_modifier.periodictime) return; int32 damage = caster->CalculateSpellDamage(spell, GetEffIndex(), GetBasePoints(), m_target); damage+=caster->GetTotalAttackPowerValue(RANGED_ATTACK) * 8 / 100; diff --git a/src/game/SpellAuras.h b/src/game/SpellAuras.h index 66ca5bc77..b3718e3eb 100644 --- a/src/game/SpellAuras.h +++ b/src/game/SpellAuras.h @@ -112,6 +112,7 @@ class MANGOS_DLL_SPEC Aura void HandlePeriodicTriggerSpell(bool Apply, bool Real); void HandlePeriodicEnergize(bool Apply, bool Real); void HandleAuraModResistanceExclusive(bool Apply, bool Real); + void HandleAuraModPetTalentsPoints(bool Apply, bool Real); void HandleModStealth(bool Apply, bool Real); void HandleInvisibility(bool Apply, bool Real); void HandleInvisibilityDetect(bool Apply, bool Real); diff --git a/src/game/SpellEffects.cpp b/src/game/SpellEffects.cpp index 5dfdbb9d3..d009e299a 100644 --- a/src/game/SpellEffects.cpp +++ b/src/game/SpellEffects.cpp @@ -54,6 +54,7 @@ #include "Util.h" #include "TemporarySummon.h" #include "ScriptCalls.h" +#include "SkillDiscovery.h" pEffect SpellEffects[TOTAL_SPELL_EFFECTS]= { @@ -214,7 +215,7 @@ pEffect SpellEffects[TOTAL_SPELL_EFFECTS]= &Spell::EffectNULL, //154 unused &Spell::EffectTitanGrip, //155 SPELL_EFFECT_TITAN_GRIP Allows you to equip two-handed axes, maces and swords in one hand, but you attack $49152s1% slower than normal. &Spell::EffectNULL, //156 Add Socket - &Spell::EffectNULL, //157 create/learn random item/spell for profession + &Spell::EffectCreateItem, //157 SPELL_EFFECT_CREATE_ITEM_2 create/learn item/spell for profession &Spell::EffectMilling, //158 milling &Spell::EffectNULL //159 allow rename pet once again }; @@ -491,7 +492,7 @@ void Spell::EffectSchoolDMG(uint32 effect_idx) Aura *poison = 0; // Lookup for Deadly poison (only attacker applied) Unit::AuraList const& auras = unitTarget->GetAurasByType(SPELL_AURA_PERIODIC_DAMAGE); - for(Unit::AuraList::const_iterator itr = auras.begin(); itr!=auras.end() && combo;) + for(Unit::AuraList::const_iterator itr = auras.begin(); itr!=auras.end(); ++itr) if( (*itr)->GetSpellProto()->SpellFamilyName==SPELLFAMILY_ROGUE && (*itr)->GetSpellProto()->SpellFamilyFlags & 0x10000 && (*itr)->GetCasterGUID()==m_caster->GetGUID() ) @@ -721,12 +722,6 @@ void Spell::EffectDummy(uint32 i) m_caster->CastCustomSpell(unitTarget, 12721, &deepWoundsDotBasePoints0, NULL, NULL, true, NULL); return; } - case 12975: //Last Stand - { - int32 healthModSpellBasePoints0 = int32(m_caster->GetMaxHealth()*0.3); - m_caster->CastCustomSpell(m_caster, 12976, &healthModSpellBasePoints0, NULL, NULL, true, NULL); - return; - } case 13120: // net-o-matic { if(!unitTarget) @@ -763,30 +758,6 @@ void Spell::EffectDummy(uint32 i) } return; } - case 14185: // Preparation Rogue - { - if(m_caster->GetTypeId()!=TYPEID_PLAYER) - return; - - //immediately finishes the cooldown on certain Rogue abilities - const PlayerSpellMap& sp_list = ((Player *)m_caster)->GetSpellMap(); - for (PlayerSpellMap::const_iterator itr = sp_list.begin(); itr != sp_list.end(); ++itr) - { - uint32 classspell = itr->first; - SpellEntry const *spellInfo = sSpellStore.LookupEntry(classspell); - - if (spellInfo->SpellFamilyName == SPELLFAMILY_ROGUE && (spellInfo->SpellFamilyFlags & 0x26000000860LL)) - { - ((Player*)m_caster)->RemoveSpellCooldown(classspell); - - WorldPacket data(SMSG_CLEAR_COOLDOWN, (4+8)); - data << uint32(classspell); - data << uint64(m_caster->GetGUID()); - ((Player*)m_caster)->GetSession()->SendPacket(&data); - } - } - return; - } case 15998: // Capture Worg Pup case 29435: // Capture Female Kaliri Hatchling { @@ -881,7 +852,7 @@ void Spell::EffectDummy(uint32 i) return; } - case 23074: // Arc. Dragonling + case 23074: // Arcanite Dragonling if (!m_CastItem) return; m_caster->CastSpell(m_caster,19804,true,m_CastItem); return; @@ -1289,18 +1260,34 @@ void Spell::EffectDummy(uint32 i) if(!unitTarget) return; - int32 basePoints0 = damage+int32(m_caster->GetPower(POWER_RAGE) * m_spellInfo->DmgMultiplier[i]); + uint32 rage = m_caster->GetPower(POWER_RAGE); + // Glyph of Execution bonus + if (Aura *aura = m_caster->GetDummyAura(58367)) + rage+=aura->GetModifier()->m_amount; + + int32 basePoints0 = damage+int32(rage * m_spellInfo->DmgMultiplier[i] + + m_caster->GetTotalAttackPowerValue(BASE_ATTACK)*0.2f); m_caster->CastCustomSpell(unitTarget, 20647, &basePoints0, NULL, NULL, true, 0); m_caster->SetPower(POWER_RAGE,0); return; } - if(m_spellInfo->Id==21977) //Warrior's Wrath + switch(m_spellInfo->Id) { - if(!unitTarget) + // Warrior's Wrath + case 21977: + { + if(!unitTarget) + return; + m_caster->CastSpell(unitTarget,21887,true); // spell mod return; - - m_caster->CastSpell(unitTarget,21887,true); // spell mod - return; + } + // Last Stand + case 12975: + { + int32 healthModSpellBasePoints0 = int32(m_caster->GetMaxHealth()*0.3); + m_caster->CastCustomSpell(m_caster, 12976, &healthModSpellBasePoints0, NULL, NULL, true, NULL); + return; + } } break; case SPELLFAMILY_WARLOCK: @@ -1425,11 +1412,6 @@ void Spell::EffectDummy(uint32 i) case SPELLFAMILY_ROGUE: switch(m_spellInfo->Id ) { - case 31231: // Cheat Death - { - m_caster->CastSpell(m_caster,45182,true); - return; - } case 5938: // Shiv { if(m_caster->GetTypeId() != TYPEID_PLAYER) @@ -1465,6 +1447,35 @@ void Spell::EffectDummy(uint32 i) m_caster->CastSpell(unitTarget, 5940, true); return; } + case 14185: // Preparation Rogue + { + if(m_caster->GetTypeId()!=TYPEID_PLAYER) + return; + + //immediately finishes the cooldown on certain Rogue abilities + const PlayerSpellMap& sp_list = ((Player *)m_caster)->GetSpellMap(); + for (PlayerSpellMap::const_iterator itr = sp_list.begin(); itr != sp_list.end(); ++itr) + { + uint32 classspell = itr->first; + SpellEntry const *spellInfo = sSpellStore.LookupEntry(classspell); + + if (spellInfo->SpellFamilyName == SPELLFAMILY_ROGUE && (spellInfo->SpellFamilyFlags & 0x0000024000000860LL)) + { + ((Player*)m_caster)->RemoveSpellCooldown(classspell); + + WorldPacket data(SMSG_CLEAR_COOLDOWN, (4+8)); + data << uint32(classspell); + data << uint64(m_caster->GetGUID()); + ((Player*)m_caster)->GetSession()->SendPacket(&data); + } + } + return; + } + case 31231: // Cheat Death + { + m_caster->CastSpell(m_caster,45182,true); + return; + } } break; case SPELLFAMILY_HUNTER: @@ -1598,6 +1609,14 @@ void Spell::EffectDummy(uint32 i) switch(m_spellInfo->Id) { + // Judgement of Righteousness (0.2*$AP+0.32*$SPH) holy added in spellDamagBonus + case 20187: + { + if (!unitTarget) + return; + m_damage+=int32(0.2f*m_caster->GetTotalAttackPowerValue(BASE_ATTACK)); + return; + } case 31789: // Righteous Defense (step 1) { // 31989 -> dummy effect (step 1) + dummy effect (step 2) -> 31709 (taunt like spell for each target) @@ -2194,11 +2213,6 @@ void Spell::EffectApplyAura(uint32 i) if(!unitTarget) return; - SpellImmuneList const& list = unitTarget->m_spellImmune[IMMUNITY_STATE]; - for(SpellImmuneList::const_iterator itr = list.begin(); itr != list.end(); ++itr) - if(itr->type == m_spellInfo->EffectApplyAuraName[i]) - return; - // ghost spell check, allow apply any auras at player loading in ghost mode (will be cleanup after load) if( !unitTarget->isAlive() && m_spellInfo->Id != 20584 && m_spellInfo->Id != 8326 && (unitTarget->GetTypeId()!=TYPEID_PLAYER || !((Player*)unitTarget)->GetSession()->PlayerLoading()) ) @@ -2815,7 +2829,7 @@ void Spell::EffectEnergisePct(uint32 i) uint32 gain = damage * maxPower / 100; unitTarget->ModifyPower(power, gain); - m_caster->SendEnergizeSpellLog(unitTarget, m_spellInfo->Id, damage, power); + m_caster->SendEnergizeSpellLog(unitTarget, m_spellInfo->Id, gain, power); } void Spell::SendLoot(uint64 guid, LootType loottype) @@ -3551,7 +3565,7 @@ void Spell::EffectAddFarsight(uint32 i) m_caster->AddDynObject(dynObj); dynObj->GetMap()->Add(dynObj); if(m_caster->GetTypeId() == TYPEID_PLAYER) - ((Player*)m_caster)->SetFarSight(dynObj->GetGUID()); + ((Player*)m_caster)->SetFarSightGUID(dynObj->GetGUID()); } void Spell::EffectSummonWild(uint32 i) @@ -3797,35 +3811,34 @@ void Spell::EffectEnchantItemPerm(uint32 i) p_caster->UpdateCraftSkill(m_spellInfo->Id); - if (m_spellInfo->EffectMiscValue[i]) + uint32 enchant_id = m_spellInfo->EffectMiscValue[i]; + if (!enchant_id) + return; + + SpellItemEnchantmentEntry const *pEnchant = sSpellItemEnchantmentStore.LookupEntry(enchant_id); + if(!pEnchant) + return; + + // item can be in trade slot and have owner diff. from caster + Player* item_owner = itemTarget->GetOwner(); + if(!item_owner) + return; + + if(item_owner!=p_caster && p_caster->GetSession()->GetSecurity() > SEC_PLAYER && sWorld.getConfig(CONFIG_GM_LOG_TRADE) ) { - uint32 enchant_id = m_spellInfo->EffectMiscValue[i]; - - SpellItemEnchantmentEntry const *pEnchant = sSpellItemEnchantmentStore.LookupEntry(enchant_id); - if(!pEnchant) - return; - - // item can be in trade slot and have owner diff. from caster - Player* item_owner = itemTarget->GetOwner(); - if(!item_owner) - return; - - if(item_owner!=p_caster && p_caster->GetSession()->GetSecurity() > SEC_PLAYER && sWorld.getConfig(CONFIG_GM_LOG_TRADE) ) - { - sLog.outCommand(p_caster->GetSession()->GetAccountId(),"GM %s (Account: %u) enchanting(perm): %s (Entry: %d) for player: %s (Account: %u)", - p_caster->GetName(),p_caster->GetSession()->GetAccountId(), - itemTarget->GetProto()->Name1,itemTarget->GetEntry(), - item_owner->GetName(),item_owner->GetSession()->GetAccountId()); - } - - // remove old enchanting before applying new if equipped - item_owner->ApplyEnchantment(itemTarget,PERM_ENCHANTMENT_SLOT,false); - - itemTarget->SetEnchantment(PERM_ENCHANTMENT_SLOT, enchant_id, 0, 0); - - // add new enchanting if equipped - item_owner->ApplyEnchantment(itemTarget,PERM_ENCHANTMENT_SLOT,true); + sLog.outCommand(p_caster->GetSession()->GetAccountId(),"GM %s (Account: %u) enchanting(perm): %s (Entry: %d) for player: %s (Account: %u)", + p_caster->GetName(),p_caster->GetSession()->GetAccountId(), + itemTarget->GetProto()->Name1,itemTarget->GetEntry(), + item_owner->GetName(),item_owner->GetSession()->GetAccountId()); } + + // remove old enchanting before applying new if equipped + item_owner->ApplyEnchantment(itemTarget,PERM_ENCHANTMENT_SLOT,false); + + itemTarget->SetEnchantment(PERM_ENCHANTMENT_SLOT, enchant_id, 0, 0); + + // add new enchanting if equipped + item_owner->ApplyEnchantment(itemTarget,PERM_ENCHANTMENT_SLOT,true); } void Spell::EffectEnchantItemTmp(uint32 i) @@ -4139,6 +4152,7 @@ void Spell::EffectSummonPet(uint32 i) NewSummon->InitStatsForLevel(petlevel); NewSummon->InitPetCreateSpells(); + NewSummon->InitTalentForLevel(); if(NewSummon->getPetType()==SUMMON_PET) { @@ -4587,456 +4601,488 @@ void Spell::EffectScriptEffect(uint32 effIndex) { // TODO: we must implement hunter pet summon at login there (spell 6962) - // by spell id - switch(m_spellInfo->Id) + switch(m_spellInfo->SpellFamilyName) { - // PX-238 Winter Wondervolt TRAP - case 26275: + case SPELLFAMILY_GENERIC: { - if( unitTarget->HasAura(26272,0) - || unitTarget->HasAura(26157,0) - || unitTarget->HasAura(26273,0) - || unitTarget->HasAura(26274,0)) - return; - - uint32 iTmpSpellId; - - switch(urand(0,3)) - { - case 0: - iTmpSpellId = 26272; - break; - case 1: - iTmpSpellId = 26157; - break; - case 2: - iTmpSpellId = 26273; - break; - case 3: - iTmpSpellId = 26274; - break; - } - - unitTarget->CastSpell(unitTarget, iTmpSpellId, true); - - return; - } - - // Bending Shinbone - case 8856: - { - if(!itemTarget && m_caster->GetTypeId()!=TYPEID_PLAYER) - return; - - uint32 spell_id = 0; - switch(urand(1,5)) - { - case 1: spell_id = 8854; break; - default: spell_id = 8855; break; - } - - m_caster->CastSpell(m_caster,spell_id,true,NULL); - return; - } - - // Healthstone creating spells - case 6201: - case 6202: - case 5699: - case 11729: - case 11730: - case 27230: - case 47871: - case 47878: - { - uint32 itemtype; - uint32 rank = 0; - Unit::AuraList const& mDummyAuras = unitTarget->GetAurasByType(SPELL_AURA_DUMMY); - for(Unit::AuraList::const_iterator i = mDummyAuras.begin();i != mDummyAuras.end(); ++i) - { - if((*i)->GetId() == 18692) - { - rank = 1; - break; - } - else if((*i)->GetId() == 18693) - { - rank = 2; - break; - } - } - - static uint32 const itypes[8][3] = { - { 5512,19004,19005}, // Minor Healthstone - { 5511,19006,19007}, // Lesser Healthstone - { 5509,19008,19009}, // Healthstone - { 5510,19010,19011}, // Greater Healthstone - { 9421,19012,19013}, // Major Healthstone - {22103,22104,22105}, // Master Healthstone - {36889,36890,36891}, // Demonic Healthstone - {36892,36893,36894} // Fel Healthstone - }; - switch(m_spellInfo->Id) { - case 6201: itemtype=itypes[0][rank];break; // Minor Healthstone - case 6202: itemtype=itypes[1][rank];break; // Lesser Healthstone - case 5699: itemtype=itypes[2][rank];break; // Healthstone - case 11729: itemtype=itypes[3][rank];break; // Greater Healthstone - case 11730: itemtype=itypes[4][rank];break; // Major Healthstone - case 27230: itemtype=itypes[5][rank];break; // Master Healthstone - case 47871: itemtype=itypes[6][rank];break; // Demonic Healthstone - case 47878: itemtype=itypes[7][rank];break; // Fel Healthstone - default: - return; - } - DoCreateItem( effIndex, itemtype ); - return; - } - // Brittle Armor - need remove one 24575 Brittle Armor aura - case 24590: - unitTarget->RemoveSingleSpellAurasFromStack(24575); - return; - // Mercurial Shield - need remove one 26464 Mercurial Shield aura - case 26465: - unitTarget->RemoveSingleSpellAurasFromStack(26464); - return; - // Orb teleport spells - case 25140: - case 25143: - case 25650: - case 25652: - case 29128: - case 29129: - case 35376: - case 35727: - { - if(!unitTarget) - return; - - uint32 spellid; - switch(m_spellInfo->Id) - { - case 25140: spellid = 32571; break; - case 25143: spellid = 32572; break; - case 25650: spellid = 30140; break; - case 25652: spellid = 30141; break; - case 29128: spellid = 32568; break; - case 29129: spellid = 32569; break; - case 35376: spellid = 25649; break; - case 35727: spellid = 35730; break; - default: - return; - } - - unitTarget->CastSpell(unitTarget,spellid,false); - return; - } - - // Shadow Flame (All script effects, not just end ones to prevent player from dodging the last triggered spell) - case 22539: - case 22972: - case 22975: - case 22976: - case 22977: - case 22978: - case 22979: - case 22980: - case 22981: - case 22982: - case 22983: - case 22984: - case 22985: - { - if(!unitTarget || !unitTarget->isAlive()) - return; - - // Onyxia Scale Cloak - if(unitTarget->GetDummyAura(22683)) - return; - - // Shadow Flame - m_caster->CastSpell(unitTarget, 22682, true); - return; - } - break; - - // Summon Black Qiraji Battle Tank - case 26656: - { - if(!unitTarget) - return; - - // Prevent stacking of mounts - unitTarget->RemoveSpellsCausingAura(SPELL_AURA_MOUNTED); - - // Two separate mounts depending on area id (allows use both in and out of specific instance) - if (unitTarget->GetAreaId() == 3428) - unitTarget->CastSpell(unitTarget, 25863, false); - else - unitTarget->CastSpell(unitTarget, 26655, false); - break; - } - // Piccolo of the Flaming Fire - case 17512: - { - if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER) - return; - unitTarget->HandleEmoteCommand(EMOTE_STATE_DANCE); - break; - } - - // Dreaming Glory - case 28698: - { - if(!unitTarget) - return; - unitTarget->CastSpell(unitTarget, 28694, true); - break; - } - - // Netherbloom - case 28702: - { - if(!unitTarget) - return; - // 25% chance of casting a random buff - if(roll_chance_i(75)) - return; - - // triggered spells are 28703 to 28707 - // Note: some sources say, that there was the possibility of - // receiving a debuff. However, this seems to be removed by a patch. - const uint32 spellid = 28703; - - // don't overwrite an existing aura - for(uint8 i=0; i<5; i++) - if(unitTarget->HasAura(spellid+i, 0)) - return; - unitTarget->CastSpell(unitTarget, spellid+urand(0, 4), true); - break; - } - - // Nightmare Vine - case 28720: - { - if(!unitTarget) - return; - // 25% chance of casting Nightmare Pollen - if(roll_chance_i(75)) - return; - unitTarget->CastSpell(unitTarget, 28721, true); - break; - } - - // Mirren's Drinking Hat - case 29830: - { - uint32 item = 0; - switch ( urand(1,6) ) - { - case 1: case 2: case 3: item = 23584; break;// Loch Modan Lager - case 4: case 5: item = 23585; break;// Stouthammer Lite - case 6: item = 23586; break;// Aerie Peak Pale Ale - } - if (item) - DoCreateItem(effIndex,item); - break; - } - // Improved Sprint - case 30918: - { - // Removes snares and roots. - uint32 mechanic_mask = (1<GetAuras(); - for(Unit::AuraMap::iterator iter = Auras.begin(), next; iter != Auras.end(); iter = next) - { - next = iter; - ++next; - Aura *aur = iter->second; - if (!aur->IsPositive()) //only remove negative spells + // PX-238 Winter Wondervolt TRAP + case 26275: { - // check for mechanic mask - if(GetSpellMechanicMask(aur->GetSpellProto(), aur->GetEffIndex()) & mechanic_mask) - { - unitTarget->RemoveAurasDueToSpell(aur->GetId()); - if(Auras.empty()) - break; - else - next = Auras.begin(); - } + uint32 spells[4] = { 26272, 26157, 26273, 26274 }; + + // check presence + for(int j = 0; j < 4; ++j) + if(unitTarget->HasAura(spells[j],0)) + return; + + // select spell + uint32 iTmpSpellId = spells[urand(0,3)]; + + // cast + unitTarget->CastSpell(unitTarget, iTmpSpellId, true); + return; } - } - break; - } - case 41126: // Flame Crash - { - if(!unitTarget) - return; - - unitTarget->CastSpell(unitTarget, 41131, true); - break; - } - case 44876: // Force Cast - Portal Effect: Sunwell Isle - { - if(!unitTarget) - return; - - unitTarget->CastSpell(unitTarget, 44870, true); - break; - } - - // Goblin Weather Machine - case 46203: - { - if(!unitTarget) - return; - - uint32 spellId; - switch(rand()%4) - { - case 0: - spellId=46740; - break; - case 1: - spellId=46739; - break; - case 2: - spellId=46738; - break; - case 3: - spellId=46736; - break; - } - unitTarget->CastSpell(unitTarget, spellId, true); - break; - } - //5,000 Gold - case 46642: - { - if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER) - return; - - ((Player*)unitTarget)->ModifyMoney(50000000); - - break; - } - case 51770: - { - if(!unitTarget) - return; - - unitTarget->CastSpell(unitTarget,51771,false); - break; - } - } - if( m_spellInfo->SpellFamilyName == SPELLFAMILY_HUNTER ) - { - switch(m_spellInfo->Id) - { - // Chimera Shot - case 53209: - { - uint32 spellId = 0; - int32 basePoint = 0; - Unit::AuraMap& Auras = unitTarget->GetAuras(); - for(Unit::AuraMap::iterator i = Auras.begin(); i != Auras.end(); ++i) + // Bending Shinbone + case 8856: { - Aura *aura = (*i).second; - if (aura->GetCasterGUID() != m_caster->GetGUID()) - continue; - // Search only Serpent Sting, Viper Sting, Scorpid Sting auras - uint64 familyFlag = aura->GetSpellProto()->SpellFamilyFlags; - if (!(familyFlag & 0x000000800000C000LL)) - continue; - // Refresh aura duration - aura->RefreshAura(); + if(!itemTarget && m_caster->GetTypeId()!=TYPEID_PLAYER) + return; - // Serpent Sting - Instantly deals 40% of the damage done by your Serpent Sting. - if (familyFlag & 0x0000000000004000LL && aura->GetEffIndex() == 0) + uint32 spell_id = 0; + switch(urand(1,5)) { - spellId = 53353; // 53353 Chimera Shot - Serpent - basePoint = aura->GetModifier()->m_amount * 5 * 40 / 100; + case 1: spell_id = 8854; break; + default: spell_id = 8855; break; } - // Viper Sting - Instantly restores mana to you equal to 60% of the total amount drained by your Viper Sting. - if (familyFlag & 0x0000008000000000LL && aura->GetEffIndex() == 0) - { - spellId = 53358; // 53358 Chimera Shot - Viper - basePoint = aura->GetModifier()->m_amount * 4 * 60 / 100; - } - // Scorpid Sting - Attempts to Disarm the target for 10 sec. This effect cannot occur more than once per 1 minute. - if (familyFlag & 0x0000000000008000LL) - spellId = 53359; // 53359 Chimera Shot - Scorpid - // ?? nothing say in spell desc (possibly need addition check) - //if (familyFlag & 0x0000010000000000LL || // dot - // familyFlag & 0x0000100000000000LL) // stun - //{ - // spellId = 53366; // 53366 Chimera Shot - Wyvern - //} - } - if (spellId) - m_caster->CastCustomSpell(unitTarget, spellId, &basePoint, 0, 0, false); - return; - } - default: - break; - } - } - else if( m_spellInfo->SpellFamilyName == SPELLFAMILY_PALADIN ) - { - switch(m_spellInfo->SpellFamilyFlags) - { - // Judgement - case 0x800000: - { - if(!unitTarget || !unitTarget->isAlive()) + + m_caster->CastSpell(m_caster,spell_id,true,NULL); return; - uint32 spellId2 = 0; - - // all seals have aura dummy - Unit::AuraList const& m_dummyAuras = m_caster->GetAurasByType(SPELL_AURA_DUMMY); - for(Unit::AuraList::const_iterator itr = m_dummyAuras.begin(); itr != m_dummyAuras.end(); ++itr) + } + // Brittle Armor - need remove one 24575 Brittle Armor aura + case 24590: + unitTarget->RemoveSingleSpellAurasFromStack(24575); + return; + // Mercurial Shield - need remove one 26464 Mercurial Shield aura + case 26465: + unitTarget->RemoveSingleSpellAurasFromStack(26464); + return; + // Orb teleport spells + case 25140: + case 25143: + case 25650: + case 25652: + case 29128: + case 29129: + case 35376: + case 35727: { - SpellEntry const *spellInfo = (*itr)->GetSpellProto(); + if(!unitTarget) + return; - // search seal (all seals have judgement's aura dummy spell id in 2 effect - if ( !spellInfo || !IsSealSpell((*itr)->GetSpellProto()) || (*itr)->GetEffIndex() != 2 ) - continue; - - // must be calculated base at raw base points in spell proto, GetModifier()->m_value for S.Righteousness modified by SPELLMOD_DAMAGE - spellId2 = (*itr)->GetSpellProto()->EffectBasePoints[2]+1; - - if(spellId2 <= 1) - continue; - - // found, remove seal - m_caster->RemoveAurasDueToSpell((*itr)->GetId()); - - // Sanctified Judgement - Unit::AuraList const& m_auras = m_caster->GetAurasByType(SPELL_AURA_DUMMY); - for(Unit::AuraList::const_iterator i = m_auras.begin(); i != m_auras.end(); ++i) + uint32 spellid; + switch(m_spellInfo->Id) { - if ((*i)->GetSpellProto()->SpellIconID == 205 && (*i)->GetSpellProto()->Attributes == 0x01D0LL) + case 25140: spellid = 32571; break; + case 25143: spellid = 32572; break; + case 25650: spellid = 30140; break; + case 25652: spellid = 30141; break; + case 29128: spellid = 32568; break; + case 29129: spellid = 32569; break; + case 35376: spellid = 25649; break; + case 35727: spellid = 35730; break; + default: + return; + } + + unitTarget->CastSpell(unitTarget,spellid,false); + return; + } + // Shadow Flame (All script effects, not just end ones to prevent player from dodging the last triggered spell) + case 22539: + case 22972: + case 22975: + case 22976: + case 22977: + case 22978: + case 22979: + case 22980: + case 22981: + case 22982: + case 22983: + case 22984: + case 22985: + { + if(!unitTarget || !unitTarget->isAlive()) + return; + + // Onyxia Scale Cloak + if(unitTarget->GetDummyAura(22683)) + return; + + // Shadow Flame + m_caster->CastSpell(unitTarget, 22682, true); + return; + } + // Summon Black Qiraji Battle Tank + case 26656: + { + if(!unitTarget) + return; + + // Prevent stacking of mounts + unitTarget->RemoveSpellsCausingAura(SPELL_AURA_MOUNTED); + + // Two separate mounts depending on area id (allows use both in and out of specific instance) + if (unitTarget->GetAreaId() == 3428) + unitTarget->CastSpell(unitTarget, 25863, false); + else + unitTarget->CastSpell(unitTarget, 26655, false); + break; + } + // Piccolo of the Flaming Fire + case 17512: + { + if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER) + return; + unitTarget->HandleEmoteCommand(EMOTE_STATE_DANCE); + break; + } + // Mirren's Drinking Hat + case 29830: + { + uint32 item = 0; + switch ( urand(1,6) ) + { + case 1:case 2:case 3: + item = 23584;break; // Loch Modan Lager + case 4:case 5: + item = 23585;break; // Stouthammer Lite + case 6: + item = 23586;break; // Aerie Peak Pale Ale + } + if (item) + DoCreateItem(effIndex,item); + break; + } + // Improved Sprint + case 30918: + { + // Removes snares and roots. + uint32 mechanic_mask = (1<GetAuras(); + for(Unit::AuraMap::iterator iter = Auras.begin(), next; iter != Auras.end(); iter = next) + { + next = iter; + ++next; + Aura *aur = iter->second; + if (!aur->IsPositive()) //only remove negative spells { - int32 chance = (*i)->GetModifier()->m_amount; - if ( roll_chance_i(chance) ) + // check for mechanic mask + if(GetSpellMechanicMask(aur->GetSpellProto(), aur->GetEffIndex()) & mechanic_mask) { - int32 mana = spellInfo->manaCost; - if ( Player* modOwner = m_caster->GetSpellModOwner() ) - modOwner->ApplySpellMod(spellInfo->Id, SPELLMOD_COST, mana); - mana = int32(mana* 0.8f); - m_caster->CastCustomSpell(m_caster,31930,&mana,NULL,NULL,true,NULL,*i); + unitTarget->RemoveAurasDueToSpell(aur->GetId()); + if(Auras.empty()) + break; + else + next = Auras.begin(); } + } + } + break; + } + // Flame Crash + case 41126: + { + if(!unitTarget) + return; + + unitTarget->CastSpell(unitTarget, 41131, true); + break; + } + // Force Cast - Portal Effect: Sunwell Isle + case 44876: + { + if(!unitTarget) + return; + + unitTarget->CastSpell(unitTarget, 44870, true); + break; + } + // Goblin Weather Machine + case 46203: + { + if(!unitTarget) + return; + + uint32 spellId; + switch(rand()%4) + { + case 0: spellId = 46740; break; + case 1: spellId = 46739; break; + case 2: spellId = 46738; break; + case 3: spellId = 46736; break; + } + unitTarget->CastSpell(unitTarget, spellId, true); + break; + } + //5,000 Gold + case 46642: + { + if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER) + return; + + ((Player*)unitTarget)->ModifyMoney(50000000); + + break; + } + // Emblazon Runeblade + case 51770: + { + if(!unitTarget) + return; + + unitTarget->CastSpell(unitTarget,51771,false); + break; + } + // Death Gate + case 52751: + { + if(!unitTarget || unitTarget->getClass() != CLASS_DEATH_KNIGHT) + return; + // triggered spell is stored in m_spellInfo->EffectBasePoints[0] + unitTarget->CastSpell(unitTarget, damage, false); + break; + } + // random spell learn instead placeholder + case 60893: // Northrend Alchemy Research + case 61177: // Northrend Inscription Research + case 61288: // Minor Inscription Research + case 61756: // Northrend Inscription Research (FAST QA VERSION) + { + if(!IsExplicitDiscoverySpell(m_spellInfo)) + { + sLog.outError("Wrong explicit discowry spell %u structure, or outdated...",m_spellInfo->Id); + return; + } + + if(m_caster->GetTypeId()!=TYPEID_PLAYER) + return; + Player* player = (Player*)m_caster; + + // need replace effect 0 item by loot + uint32 reagent_id = m_spellInfo->EffectItemType[0]; + + if(!player->HasItemCount(reagent_id,1)) + return; + + // remove reagent + uint32 count = 1; + player->DestroyItemCount (reagent_id,count,true); + + // create some random items + player->AutoStoreLootItem(m_spellInfo->Id,LootTemplates_Spell); + + // learn random explicit discovery recipe (if any) + if(uint32 discoveredSpell = GetExplicitDiscoverySpell(m_spellInfo->Id, player)) + player->learnSpell(discoveredSpell); + return; + } + } + break; + } + case SPELLFAMILY_WARLOCK: + { + switch(m_spellInfo->Id) + { + // Healthstone creating spells + case 6201: + case 6202: + case 5699: + case 11729: + case 11730: + case 27230: + case 47871: + case 47878: + { + uint32 itemtype; + uint32 rank = 0; + Unit::AuraList const& mDummyAuras = unitTarget->GetAurasByType(SPELL_AURA_DUMMY); + for(Unit::AuraList::const_iterator i = mDummyAuras.begin();i != mDummyAuras.end(); ++i) + { + if((*i)->GetId() == 18692) + { + rank = 1; + break; + } + else if((*i)->GetId() == 18693) + { + rank = 2; break; } } + static uint32 const itypes[8][3] = { + { 5512,19004,19005}, // Minor Healthstone + { 5511,19006,19007}, // Lesser Healthstone + { 5509,19008,19009}, // Healthstone + { 5510,19010,19011}, // Greater Healthstone + { 9421,19012,19013}, // Major Healthstone + {22103,22104,22105}, // Master Healthstone + {36889,36890,36891}, // Demonic Healthstone + {36892,36893,36894} // Fel Healthstone + }; + + switch(m_spellInfo->Id) + { + case 6201: + itemtype=itypes[0][rank];break; // Minor Healthstone + case 6202: + itemtype=itypes[1][rank];break; // Lesser Healthstone + case 5699: + itemtype=itypes[2][rank];break; // Healthstone + case 11729: + itemtype=itypes[3][rank];break; // Greater Healthstone + case 11730: + itemtype=itypes[4][rank];break; // Major Healthstone + case 27230: + itemtype=itypes[5][rank];break; // Master Healthstone + case 47871: + itemtype=itypes[6][rank];break; // Demonic Healthstone + case 47878: + itemtype=itypes[7][rank];break; // Fel Healthstone + default: + return; + } + DoCreateItem( effIndex, itemtype ); + return; + } + } + break; + } + case SPELLFAMILY_HUNTER: + { + switch(m_spellInfo->Id) + { + // Chimera Shot + case 53209: + { + uint32 spellId = 0; + int32 basePoint = 0; + Unit::AuraMap& Auras = unitTarget->GetAuras(); + for(Unit::AuraMap::iterator i = Auras.begin(); i != Auras.end(); ++i) + { + Aura *aura = (*i).second; + if (aura->GetCasterGUID() != m_caster->GetGUID()) + continue; + // Search only Serpent Sting, Viper Sting, Scorpid Sting auras + uint64 familyFlag = aura->GetSpellProto()->SpellFamilyFlags; + if (!(familyFlag & 0x000000800000C000LL)) + continue; + // Refresh aura duration + aura->RefreshAura(); + + // Serpent Sting - Instantly deals 40% of the damage done by your Serpent Sting. + if (familyFlag & 0x0000000000004000LL && aura->GetEffIndex() == 0) + { + spellId = 53353; // 53353 Chimera Shot - Serpent + basePoint = aura->GetModifier()->m_amount * 5 * 40 / 100; + } + // Viper Sting - Instantly restores mana to you equal to 60% of the total amount drained by your Viper Sting. + if (familyFlag & 0x0000008000000000LL && aura->GetEffIndex() == 0) + { + spellId = 53358; // 53358 Chimera Shot - Viper + basePoint = aura->GetModifier()->m_amount * 4 * 60 / 100; + } + // Scorpid Sting - Attempts to Disarm the target for 10 sec. This effect cannot occur more than once per 1 minute. + if (familyFlag & 0x0000000000008000LL) + spellId = 53359; // 53359 Chimera Shot - Scorpid + // ?? nothing say in spell desc (possibly need addition check) + //if (familyFlag & 0x0000010000000000LL || // dot + // familyFlag & 0x0000100000000000LL) // stun + //{ + // spellId = 53366; // 53366 Chimera Shot - Wyvern + //} + } + if (spellId) + m_caster->CastCustomSpell(unitTarget, spellId, &basePoint, 0, 0, false); + return; + } + default: + break; + } + break; + } + case SPELLFAMILY_PALADIN: + { + // Judgement + if (m_spellInfo->SpellFamilyFlags & 0x0000000000800000LL) + { + if(!unitTarget || !unitTarget->isAlive()) + return; + uint32 spellId1 = 0; + uint32 spellId2 = 0; + + // Judgement self add switch + switch (m_spellInfo->Id) + { + case 41467: break; // Judgement + case 53407: spellId1 = 20184; break; // Judgement of Justice + case 20271: // Judgement of Light + case 57774: spellId1 = 20185; break; // Judgement of Light + case 53408: spellId1 = 20186; break; // Judgement of Wisdom + default: + return; + } + // all seals have aura dummy in 2 effect + Unit::AuraList const& m_dummyAuras = m_caster->GetAurasByType(SPELL_AURA_DUMMY); + for(Unit::AuraList::const_iterator itr = m_dummyAuras.begin(); itr != m_dummyAuras.end(); ++itr) + { + SpellEntry const *spellInfo = (*itr)->GetSpellProto(); + // search seal (all seals have judgement's aura dummy spell id in 2 effect + if ((*itr)->GetEffIndex() != 2 || !spellInfo || !IsSealSpell(spellInfo)) + continue; + spellId2 = (*itr)->GetModifier()->m_amount; + SpellEntry const *judge = sSpellStore.LookupEntry(spellId2); + if (!judge) + continue; + break; + } + if (spellId1) + m_caster->CastSpell(unitTarget, spellId1, true); + if (spellId2) + m_caster->CastSpell(unitTarget, spellId2, true); + return; + } + } + case SPELLFAMILY_POTION: + { + switch(m_spellInfo->Id) + { + // Dreaming Glory + case 28698: + { + if(!unitTarget) + return; + unitTarget->CastSpell(unitTarget, 28694, true); + break; + } + // Netherbloom + case 28702: + { + if(!unitTarget) + return; + // 25% chance of casting a random buff + if(roll_chance_i(75)) + return; + + // triggered spells are 28703 to 28707 + // Note: some sources say, that there was the possibility of + // receiving a debuff. However, this seems to be removed by a patch. + const uint32 spellid = 28703; + + // don't overwrite an existing aura + for(uint8 i=0; i<5; i++) + if(unitTarget->HasAura(spellid+i, 0)) + return; + unitTarget->CastSpell(unitTarget, spellid+urand(0, 4), true); break; } - m_caster->CastSpell(unitTarget,spellId2,true); - return; + // Nightmare Vine + case 28720: + { + if(!unitTarget) + return; + // 25% chance of casting Nightmare Pollen + if(roll_chance_i(75)) + return; + unitTarget->CastSpell(unitTarget, 28721, true); + break; + } } + break; } } @@ -5340,9 +5386,6 @@ void Spell::EffectSummonTotem(uint32 i) if(m_caster->GetTypeId() == TYPEID_PLAYER) pTotem->SetFlag(UNIT_FIELD_FLAGS,UNIT_FLAG_PVP_ATTACKABLE); - pTotem->ApplySpellImmune(m_spellInfo->Id,IMMUNITY_STATE,SPELL_AURA_MOD_FEAR,true); - pTotem->ApplySpellImmune(m_spellInfo->Id,IMMUNITY_STATE,SPELL_AURA_TRANSFORM,true); - pTotem->Summon(m_caster); if(slot < MAX_TOTEM && m_caster->GetTypeId() == TYPEID_PLAYER) diff --git a/src/game/SpellHandler.cpp b/src/game/SpellHandler.cpp index 2063fa34b..ab9b75917 100644 --- a/src/game/SpellHandler.cpp +++ b/src/game/SpellHandler.cpp @@ -125,59 +125,7 @@ void WorldSession::HandleUseItemOpcode(WorldPacket& recvPacket) if(!Script->ItemUse(pUser,pItem,targets)) { // no script or script not process request by self - - // special learning case - if((pItem->GetProto()->Spells[0].SpellId==SPELL_ID_GENERIC_LEARN) || (pItem->GetProto()->Spells[0].SpellId==SPELL_ID_GENERIC_LEARN_PET)) - { - uint32 learn_spell_id = pItem->GetProto()->Spells[0].SpellId; - uint32 learning_spell_id = pItem->GetProto()->Spells[1].SpellId; - - SpellEntry const *spellInfo = sSpellStore.LookupEntry(learn_spell_id); - if(!spellInfo) - { - sLog.outError("Item (Entry: %u) in have wrong spell id %u, ignoring ",proto->ItemId, learn_spell_id); - pUser->SendEquipError(EQUIP_ERR_NONE,pItem,NULL); - return; - } - - Spell *spell = new Spell(pUser, spellInfo, false); - spell->m_CastItem = pItem; - spell->m_cast_count = cast_count; //set count of casts - spell->m_currentBasePoints[0] = learning_spell_id; - spell->prepare(&targets); - return; - } - - // use triggered flag only for items with many spell casts and for not first cast - int count = 0; - - for(int i = 0; i < 5; ++i) - { - _Spell const& spellData = pItem->GetProto()->Spells[i]; - - // no spell - if(!spellData.SpellId) - continue; - - // wrong triggering type - if( spellData.SpellTrigger != ITEM_SPELLTRIGGER_ON_USE && spellData.SpellTrigger != ITEM_SPELLTRIGGER_ON_NO_DELAY_USE) - continue; - - SpellEntry const *spellInfo = sSpellStore.LookupEntry(spellData.SpellId); - if(!spellInfo) - { - sLog.outError("Item (Entry: %u) in have wrong spell id %u, ignoring ",proto->ItemId, spellData.SpellId); - continue; - } - - Spell *spell = new Spell(pUser, spellInfo, (count > 0)); - spell->m_CastItem = pItem; - spell->m_cast_count = cast_count; // set count of casts - spell->m_glyphIndex = glyphIndex; // glyph index - spell->prepare(&targets); - - ++count; - } + pUser->CastItemUseSpell(pItem,targets,cast_count,glyphIndex); } } diff --git a/src/game/SpellMgr.cpp b/src/game/SpellMgr.cpp index 0a136f4fd..47b96539e 100644 --- a/src/game/SpellMgr.cpp +++ b/src/game/SpellMgr.cpp @@ -1018,7 +1018,7 @@ bool SpellMgr::canStackSpellRanks(SpellEntry const *spellInfo) { if(spellInfo->powerType != POWER_MANA && spellInfo->powerType != POWER_HEALTH) return false; - if(IsProfessionSpell(spellInfo->Id)) + if(IsProfessionOrRidingSpell(spellInfo->Id)) return false; // All stance spells. if any better way, change it. @@ -1062,6 +1062,10 @@ bool SpellMgr::IsNoStackSpellDueToSpell(uint32 spellId_1, uint32 spellId_2) cons if((spellInfo_1->Id == SPELL_ID_PASSIVE_RESURRECTION_SICKNESS) != (spellInfo_2->Id==SPELL_ID_PASSIVE_RESURRECTION_SICKNESS)) return false; + // Allow stack passive and not passive spells + if ((spellInfo_1->Attributes & SPELL_ATTR_PASSIVE)!=(spellInfo_2->Attributes & SPELL_ATTR_PASSIVE)) + return false; + // Specific spell family spells switch(spellInfo_1->SpellFamilyName) { @@ -1399,6 +1403,20 @@ bool SpellMgr::IsNoStackSpellDueToSpell(uint32 spellId_1, uint32 spellId_2) cons return true; } +bool SpellMgr::IsProfessionOrRidingSpell(uint32 spellId) +{ + SpellEntry const *spellInfo = sSpellStore.LookupEntry(spellId); + if(!spellInfo) + return false; + + if(spellInfo->Effect[1] != SPELL_EFFECT_SKILL) + return false; + + uint32 skill = spellInfo->EffectMiscValue[1]; + + return IsProfessionOrRidingSkill(skill); +} + bool SpellMgr::IsProfessionSpell(uint32 spellId) { SpellEntry const *spellInfo = sSpellStore.LookupEntry(spellId); @@ -2361,13 +2379,6 @@ DiminishingGroup GetDiminishingReturnsGroupForSpell(SpellEntry const* spellproto // Explicit Diminishing Groups switch(spellproto->SpellFamilyName) { - case SPELLFAMILY_MAGE: - { - // Polymorph - if ((spellproto->SpellFamilyFlags & 0x00001000000LL) && spellproto->EffectApplyAuraName[0]==SPELL_AURA_MOD_CONFUSE) - return DIMINISHING_POLYMORPH; - break; - } case SPELLFAMILY_ROGUE: { // Kidney Shot @@ -2380,11 +2391,8 @@ DiminishingGroup GetDiminishingReturnsGroupForSpell(SpellEntry const* spellproto } case SPELLFAMILY_WARLOCK: { - // Death Coil - if (spellproto->SpellFamilyFlags & 0x00000080000LL) - return DIMINISHING_DEATHCOIL; // Fear - else if (spellproto->SpellFamilyFlags & 0x40840000000LL) + if (spellproto->SpellFamilyFlags & 0x40840000000LL) return DIMINISHING_WARLOCK_FEAR; // Curses/etc else if (spellproto->SpellFamilyFlags & 0x00080000000LL) @@ -2410,30 +2418,21 @@ DiminishingGroup GetDiminishingReturnsGroupForSpell(SpellEntry const* spellproto } // Get by mechanic - for (uint8 i=0;i<3;++i) - { - if (spellproto->Mechanic == MECHANIC_STUN || spellproto->EffectMechanic[i] == MECHANIC_STUN) - return triggered ? DIMINISHING_TRIGGER_STUN : DIMINISHING_CONTROL_STUN; - else if (spellproto->Mechanic == MECHANIC_SLEEP || spellproto->EffectMechanic[i] == MECHANIC_SLEEP) - return DIMINISHING_SLEEP; - else if (spellproto->Mechanic == MECHANIC_ROOT || spellproto->EffectMechanic[i] == MECHANIC_ROOT) - return triggered ? DIMINISHING_TRIGGER_ROOT : DIMINISHING_CONTROL_ROOT; - else if (spellproto->Mechanic == MECHANIC_FEAR || spellproto->EffectMechanic[i] == MECHANIC_FEAR) - return DIMINISHING_FEAR; - else if (spellproto->Mechanic == MECHANIC_CHARM || spellproto->EffectMechanic[i] == MECHANIC_CHARM) - return DIMINISHING_CHARM; - else if (spellproto->Mechanic == MECHANIC_SILENCE || spellproto->EffectMechanic[i] == MECHANIC_SILENCE) - return DIMINISHING_SILENCE; - else if (spellproto->Mechanic == MECHANIC_DISARM || spellproto->EffectMechanic[i] == MECHANIC_DISARM) - return DIMINISHING_DISARM; - else if (spellproto->Mechanic == MECHANIC_FREEZE || spellproto->EffectMechanic[i] == MECHANIC_FREEZE) - return DIMINISHING_FREEZE; - else if (spellproto->Mechanic == MECHANIC_KNOCKOUT|| spellproto->EffectMechanic[i] == MECHANIC_KNOCKOUT || - spellproto->Mechanic == MECHANIC_SAPPED || spellproto->EffectMechanic[i] == MECHANIC_SAPPED) - return DIMINISHING_KNOCKOUT; - else if (spellproto->Mechanic == MECHANIC_BANISH || spellproto->EffectMechanic[i] == MECHANIC_BANISH) - return DIMINISHING_BANISH; - } + uint32 mechanic = GetAllSpellMechanicMask(spellproto); + if (mechanic == MECHANIC_NONE) return DIMINISHING_NONE; + if (mechanic & (1<SpellFamilyName == SPELLFAMILY_PALADIN && - ( spellInfo->SpellFamilyFlags & 0x26000C000A000000LL ); + ( spellInfo->SpellFamilyFlags & SPELLFAMILYFLAG_PALADIN_SEALS ); } inline bool IsElementalShield(SpellEntry const *spellInfo) @@ -311,6 +312,11 @@ inline bool IsElementalShield(SpellEntry const *spellInfo) return (spellInfo->SpellFamilyFlags & 0x42000000400LL) || spellInfo->Id == 23552; } +inline bool IsExplicitDiscoverySpell(SpellEntry const *spellInfo) +{ + return spellInfo->Effect[0]==SPELL_EFFECT_CREATE_ITEM_2 && spellInfo->Effect[1]==SPELL_EFFECT_SCRIPT_EFFECT; +} + int32 CompareAuraRanks(uint32 spellId_1, uint32 effIndex_1, uint32 spellId_2, uint32 effIndex_2); bool IsSingleFromSpellSpecificPerCaster(uint32 spellSpec1,uint32 spellSpec2); bool IsPassiveSpell(uint32 spellId); @@ -721,6 +727,11 @@ inline bool IsProfessionSkill(uint32 skill) return IsPrimaryProfessionSkill(skill) || skill == SKILL_FISHING || skill == SKILL_COOKING || skill == SKILL_FIRST_AID; } +inline bool IsProfessionOrRidingSkill(uint32 skill) +{ + return IsProfessionSkill(skill) || skill == SKILL_RIDING; +} + class SpellMgr { // Constructors @@ -882,6 +893,7 @@ class SpellMgr return false; } + static bool IsProfessionOrRidingSpell(uint32 spellId); static bool IsProfessionSpell(uint32 spellId); static bool IsPrimaryProfessionSpell(uint32 spellId); bool IsPrimaryProfessionFirstRankSpell(uint32 spellId) const; diff --git a/src/game/StatSystem.cpp b/src/game/StatSystem.cpp index a369bc3ec..a6f42c014 100644 --- a/src/game/StatSystem.cpp +++ b/src/game/StatSystem.cpp @@ -91,6 +91,21 @@ bool Player::UpdateStats(Stats stat) return true; } +void Player::ApplySpellDamageBonus(int32 amount, bool apply) +{ + m_baseSpellDamage+=apply?amount:-amount; + // For speed just update for client + ApplyModUInt32Value(PLAYER_FIELD_MOD_HEALING_DONE_POS, amount, apply); +} + +void Player::ApplySpellHealingBonus(int32 amount, bool apply) +{ + m_baseSpellHealing+=apply?amount:-amount; + // For speed just update for client + for(int i = SPELL_SCHOOL_HOLY; i < MAX_SPELL_SCHOOL; i++) + ApplyModUInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_POS+i, amount, apply);; +} + void Player::UpdateSpellDamageAndHealingBonus() { // Magic damage modifiers implemented in Unit::SpellDamageBonus @@ -221,6 +236,12 @@ void Player::UpdateMaxPower(Powers power) SetMaxPower(power, uint32(value)); } +void Player::ApplyFeralAPBonus(int32 amount, bool apply) +{ + m_baseFeralAP+= apply ? amount:-amount; + UpdateAttackPowerAndDamage(); +} + void Player::UpdateAttackPowerAndDamage(bool ranged ) { float val2 = 0.0f; @@ -295,12 +316,12 @@ void Player::UpdateAttackPowerAndDamage(bool ranged ) switch(m_form) { case FORM_CAT: - val2 = getLevel()*(mLevelMult+2.0f) + GetStat(STAT_STRENGTH)*2.0f + GetStat(STAT_AGILITY) - 20.0f; break; + val2 = getLevel()*(mLevelMult+2.0f) + GetStat(STAT_STRENGTH)*2.0f + GetStat(STAT_AGILITY) - 20.0f + m_baseFeralAP; break; case FORM_BEAR: case FORM_DIREBEAR: - val2 = getLevel()*(mLevelMult+3.0f) + GetStat(STAT_STRENGTH)*2.0f - 20.0f; break; + val2 = getLevel()*(mLevelMult+3.0f) + GetStat(STAT_STRENGTH)*2.0f - 20.0f + m_baseFeralAP; break; case FORM_MOONKIN: - val2 = getLevel()*(mLevelMult+1.5f) + GetStat(STAT_STRENGTH)*2.0f - 20.0f; break; + val2 = getLevel()*(mLevelMult+1.5f) + GetStat(STAT_STRENGTH)*2.0f - 20.0f + m_baseFeralAP; break; default: val2 = GetStat(STAT_STRENGTH)*2.0f - 20.0f; break; } @@ -625,6 +646,12 @@ void Player::UpdateExpertise(WeaponAttackType attack) } } +void Player::ApplyManaRegenBonus(int32 amount, bool apply) +{ + m_baseManaRegen+= apply ? amount : -amount; + UpdateManaRegen(); +} + void Player::UpdateManaRegen() { float Intellect = GetStat(STAT_INTELLECT); @@ -634,7 +661,7 @@ void Player::UpdateManaRegen() power_regen *= GetTotalAuraMultiplierByMiscValue(SPELL_AURA_MOD_POWER_REGEN_PERCENT, POWER_MANA); // Mana regen from SPELL_AURA_MOD_POWER_REGEN aura - float power_regen_mp5 = GetTotalAuraModifierByMiscValue(SPELL_AURA_MOD_POWER_REGEN, POWER_MANA) / 5.0f; + float power_regen_mp5 = (GetTotalAuraModifierByMiscValue(SPELL_AURA_MOD_POWER_REGEN, POWER_MANA) + m_baseManaRegen) / 5.0f; // Get bonus from SPELL_AURA_MOD_MANA_REGEN_FROM_STAT aura AuraList const& regenAura = GetAurasByType(SPELL_AURA_MOD_MANA_REGEN_FROM_STAT); diff --git a/src/game/ThreatManager.h b/src/game/ThreatManager.h index b6e2d3da0..5191b2199 100644 --- a/src/game/ThreatManager.h +++ b/src/game/ThreatManager.h @@ -204,10 +204,10 @@ class MANGOS_DLL_SPEC ThreatManager // methods to access the lists from the outside to do sume dirty manipulation (scriping and such) // I hope they are used as little as possible. - inline std::list& getThreatList() { return iThreatContainer.getThreatList(); } - inline std::list& getOfflieThreatList() { return iThreatOfflineContainer.getThreatList(); } - inline ThreatContainer& getOnlineContainer() { return iThreatContainer; } - inline ThreatContainer& getOfflineContainer() { return iThreatOfflineContainer; } + std::list& getThreatList() { return iThreatContainer.getThreatList(); } + std::list& getOfflieThreatList() { return iThreatOfflineContainer.getThreatList(); } + ThreatContainer& getOnlineContainer() { return iThreatContainer; } + ThreatContainer& getOfflineContainer() { return iThreatOfflineContainer; } }; //================================================= diff --git a/src/game/Totem.cpp b/src/game/Totem.cpp index 504e3ce3e..c5043a472 100644 --- a/src/game/Totem.cpp +++ b/src/game/Totem.cpp @@ -159,18 +159,18 @@ void Totem::SetTypeBySummonSpell(SpellEntry const * spellProto) m_type = TOTEM_STATUE; //Jewelery statue } -bool Totem::IsImmunedToSpell(SpellEntry const* spellInfo) +bool Totem::IsImmunedToSpellEffect(SpellEntry const* spellInfo, uint32 index) const { - for (int i=0;i<3;i++) + // TODO: possibly all negative auras immuned? + switch(spellInfo->EffectApplyAuraName[index]) { - switch(spellInfo->EffectApplyAuraName[i]) - { - case SPELL_AURA_PERIODIC_DAMAGE: - case SPELL_AURA_PERIODIC_LEECH: - return true; - default: - continue; - } + case SPELL_AURA_PERIODIC_DAMAGE: + case SPELL_AURA_PERIODIC_LEECH: + case SPELL_AURA_MOD_FEAR: + case SPELL_AURA_TRANSFORM: + return true; + default: + break; } - return Creature::IsImmunedToSpell(spellInfo); + return Creature::IsImmunedToSpellEffect(spellInfo, index); } diff --git a/src/game/Totem.h b/src/game/Totem.h index df4abaada..98f071b90 100644 --- a/src/game/Totem.h +++ b/src/game/Totem.h @@ -53,7 +53,7 @@ class Totem : public Creature void UpdateAttackPowerAndDamage(bool /*ranged*/ ) {} void UpdateDamagePhysical(WeaponAttackType /*attType*/) {} - bool IsImmunedToSpell(SpellEntry const* spellInfo); + bool IsImmunedToSpellEffect(SpellEntry const* spellInfo, uint32 index) const; protected: TotemType m_type; diff --git a/src/game/Transports.cpp b/src/game/Transports.cpp index d0de6afd4..dfe12119a 100644 --- a/src/game/Transports.cpp +++ b/src/game/Transports.cpp @@ -473,11 +473,8 @@ bool Transport::AddPassenger(Player* passenger) bool Transport::RemovePassenger(Player* passenger) { - if (m_passengers.find(passenger) != m_passengers.end()) - { + if (m_passengers.erase(passenger)) sLog.outDetail("Player %s removed from transport %s.", passenger->GetName(), m_name.c_str()); - m_passengers.erase(passenger); - } return true; } diff --git a/src/game/Transports.h b/src/game/Transports.h index c6ef2a3a4..4d58a80de 100644 --- a/src/game/Transports.h +++ b/src/game/Transports.h @@ -36,16 +36,16 @@ class TransportPath uint32 delay; }; - inline void SetLength(const unsigned int sz) + void SetLength(const unsigned int sz) { i_nodes.resize( sz ); } - inline unsigned int Size(void) const { return i_nodes.size(); } - inline bool Empty(void) const { return i_nodes.empty(); } - inline void Resize(unsigned int sz) { i_nodes.resize(sz); } - inline void Clear(void) { i_nodes.clear(); } - inline PathNode* GetNodes(void) { return static_cast(&i_nodes[0]); } + unsigned int Size(void) const { return i_nodes.size(); } + bool Empty(void) const { return i_nodes.empty(); } + void Resize(unsigned int sz) { i_nodes.resize(sz); } + void Clear(void) { i_nodes.clear(); } + PathNode* GetNodes(void) { return static_cast(&i_nodes[0]); } PathNode& operator[](const unsigned int idx) { return i_nodes[idx]; } const PathNode& operator()(const unsigned int idx) const { return i_nodes[idx]; } diff --git a/src/game/Traveller.h b/src/game/Traveller.h index 51ea73651..3daa558da 100644 --- a/src/game/Traveller.h +++ b/src/game/Traveller.h @@ -44,10 +44,10 @@ struct MANGOS_DLL_DECL Traveller operator T&(void) { return i_traveller; } operator const T&(void) { return i_traveller; } - inline float GetPositionX() const { return i_traveller.GetPositionX(); } - inline float GetPositionY() const { return i_traveller.GetPositionY(); } - inline float GetPositionZ() const { return i_traveller.GetPositionZ(); } - inline T& GetTraveller(void) { return i_traveller; } + float GetPositionX() const { return i_traveller.GetPositionX(); } + float GetPositionY() const { return i_traveller.GetPositionY(); } + float GetPositionZ() const { return i_traveller.GetPositionZ(); } + T& GetTraveller(void) { return i_traveller; } float Speed(void) { assert(false); return 0.0f; } void Relocation(float x, float y, float z, float orientation) {} diff --git a/src/game/Unit.cpp b/src/game/Unit.cpp index fcc496a55..16a4f1d23 100644 --- a/src/game/Unit.cpp +++ b/src/game/Unit.cpp @@ -102,7 +102,6 @@ Unit::Unit() //m_AurasCheck = 2000; //m_removeAuraTimer = 4; //tmpAura = NULL; - waterbreath = false; m_Visibility = VISIBILITY_ON; @@ -800,7 +799,12 @@ uint32 Unit::DealDamage(Unit *pVictim, uint32 damage, CleanDamage const* cleanDa if(Spell* spell = pVictim->m_currentSpells[i]) if(spell->getState() == SPELL_STATE_PREPARING) - spell->Delayed(); + { + if(spell->m_spellInfo->InterruptFlags & SPELL_INTERRUPT_FLAG_ABORT_ON_DMG) + pVictim->InterruptSpell(i); + else + spell->Delayed(); + } } } @@ -1123,17 +1127,6 @@ void Unit::DealSpellDamage(SpellNonMeleeDamage *damageInfo, bool durabilityLoss) return; } - // update at damage Judgement aura duration that applied by attacker at victim - if(damageInfo->damage && spellProto->Id == 35395) - { - AuraMap& vAuras = pVictim->GetAuras(); - for(AuraMap::iterator itr = vAuras.begin(); itr != vAuras.end(); ++itr) - { - SpellEntry const *spellInfo = (*itr).second->GetSpellProto(); - if( spellInfo->AttributesEx3 & 0x40000 && spellInfo->SpellFamilyName == SPELLFAMILY_PALADIN && ((*itr).second->GetCasterGUID() == GetGUID())) - (*itr).second->RefreshAura(); - } - } // Call default DealDamage CleanDamage cleanDamage(damageInfo->cleanDamage, BASE_ATTACK, MELEE_HIT_NORMAL); DealDamage(pVictim, damageInfo->damage, &cleanDamage, SPELL_DIRECT_DAMAGE, SpellSchoolMask(damageInfo->schoolMask), spellProto, durabilityLoss); @@ -1479,18 +1472,6 @@ void Unit::DealMeleeDamage(CalcDamageInfo *damageInfo, bool durabilityLoss) CastSpell(pVictim, 1604, true); } - // update at damage Judgement aura duration that applied by attacker at victim - if(damageInfo->damage) - { - AuraMap& vAuras = pVictim->GetAuras(); - for(AuraMap::iterator itr = vAuras.begin(); itr != vAuras.end(); ++itr) - { - SpellEntry const *spellInfo = (*itr).second->GetSpellProto(); - if( spellInfo->AttributesEx3 & 0x40000 && spellInfo->SpellFamilyName == SPELLFAMILY_PALADIN && ((*itr).second->GetCasterGUID() == GetGUID())) - (*itr).second->RefreshAura(); - } - } - // If not miss if (!(damageInfo->HitInfo & HITINFO_MISS)) { @@ -2370,6 +2351,24 @@ SpellMissInfo Unit::MeleeSpellHitResult(Unit *pVictim, SpellEntry const *spell) if (roll < tmp) return SPELL_MISS_MISS; + // Chance resist mechanic (select max value from every mechanic spell effect) + int32 resist_mech = 0; + // Get effects mechanic and chance + for(int eff = 0; eff < 3; ++eff) + { + int32 effect_mech = GetEffectMechanic(spell, eff); + if (effect_mech) + { + int32 temp = pVictim->GetTotalAuraModifierByMiscValue(SPELL_AURA_MOD_MECHANIC_RESISTANCE, effect_mech); + if (resist_mech < temp*100) + resist_mech = temp*100; + } + } + // Roll chance + tmp += resist_mech; + if (roll < tmp) + return SPELL_MISS_RESIST; + bool canDodge = true; bool canParry = true; @@ -4719,6 +4718,30 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, Aura* triggeredByAu target = this; break; } + // Divine purpose + case 31871: + case 31872: + { + // Roll chane + if (!roll_chance_i(triggeredByAura->GetModifier()->m_amount)) + return false; + + // Remove any stun effect on target + AuraMap& Auras = pVictim->GetAuras(); + for(AuraMap::iterator iter = Auras.begin(); iter != Auras.end();) + { + SpellEntry const *spell = iter->second->GetSpellProto(); + if( spell->Mechanic == MECHANIC_STUN || + spell->EffectMechanic[iter->second->GetEffIndex()] == MECHANIC_STUN) + { + pVictim->RemoveAurasDueToSpell(spell->Id); + iter = Auras.begin(); + } + else + ++iter; + } + return true; + } } break; } @@ -4851,7 +4874,8 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, Aura* triggeredByAu triggered_spell_id = 22858; break; } - else if (dummySpell->SpellIconID == 1697) // Second Wind + // Second Wind + if (dummySpell->SpellIconID == 1697) { // only for spells and hit/crit (trigger start always) and not start from self casted spells (5530 Mace Stun Effect for example) if (procSpell == 0 || !(procEx & (PROC_EX_NORMAL_HIT|PROC_EX_CRITICAL_HIT)) || this == pVictim) @@ -4864,6 +4888,7 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, Aura* triggeredByAu { case 29838: triggered_spell_id=29842; break; case 29834: triggered_spell_id=29841; break; + case 42770: triggered_spell_id=42771; break; default: sLog.outError("Unit::HandleDummyAuraProc: non handled spell id: %u (SW)",dummySpell->Id); return false; @@ -4872,6 +4897,13 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, Aura* triggeredByAu target = this; break; } + // Damage Shield + if (dummySpell->SpellIconID == 3214) + { + triggered_spell_id = 59653; + basepoints0 = GetShieldBlockValue() * triggeredByAura->GetModifier()->m_amount / 100; + break; + } break; } case SPELLFAMILY_WARLOCK: @@ -4919,6 +4951,16 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, Aura* triggeredByAu mod->m_amount-=damage; return true; } + // Fel Synergy + if (dummySpell->SpellIconID == 3222) + { + target = GetPet(); + if (!target) + return false; + triggered_spell_id = 54181; + basepoints0 = damage * triggeredByAura->GetModifier()->m_amount / 100; + break; + } switch(dummySpell->Id) { // Nightfall @@ -5039,7 +5081,7 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, Aura* triggeredByAu return false; // heal amount - basepoints0 = int32(damage * 2 / 100); + basepoints0 = damage * triggeredByAura->GetModifier()->m_amount/100; target = this; triggered_spell_id = 39373; break; @@ -5171,6 +5213,31 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, Aura* triggeredByAu break; } } + // Cut to the Chase + if( dummySpell->SpellIconID == 2909 ) + { + // "refresh your Slice and Dice duration to its 5 combo point maximum" + // lookup Slice and Dice + AuraList const& sd = GetAurasByType(SPELL_AURA_MOD_HASTE); + for(AuraList::const_iterator itr = sd.begin(); itr != sd.end(); ++itr) + { + SpellEntry const *spellProto = (*itr)->GetSpellProto(); + if( spellProto->SpellFamilyName == SPELLFAMILY_ROGUE && + spellProto->SpellFamilyFlags & 0x0000000000040000LL) + { + (*itr)->SetAuraMaxDuration(GetSpellMaxDuration(spellProto)); + (*itr)->RefreshAura(); + return true; + } + } + return false; + } + // Deadly Brew + if( dummySpell->SpellIconID == 2963 ) + { + triggered_spell_id = 25809; + break; + } // Quick Recovery if( dummySpell->SpellIconID == 2116 ) { @@ -5205,6 +5272,33 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, Aura* triggeredByAu triggered_spell_id = 34720; break; } + // Hunting Party + if ( dummySpell->SpellIconID == 3406 ) + { + triggered_spell_id = 57669; + target = this; + break; + } + // Lock and Load + if ( dummySpell->SpellIconID == 3579 ) + { + // Proc only from periodic (from trap activation proc another aura of this spell) + if (!(procFlag & PROC_FLAG_ON_DO_PERIODIC)) + return false; + if (!roll_chance_i(triggeredByAura->GetModifier()->m_amount)) + return false; + triggered_spell_id = 56453; + target = this; + break; + } + // Rapid Recuperation + if ( dummySpell->SpellIconID == 3560 ) + { + // mane regen from Rapid Killing + triggered_spell_id = 56654; + target = this; + break; + } break; } case SPELLFAMILY_PALADIN: @@ -5219,29 +5313,36 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, Aura* triggeredByAu basepoints0 = GetAttackTime(BASE_ATTACK) * int32(ap*0.022f + 0.044f * holy) / 1000; break; } - // Seal of Blood do damage trigger - if(dummySpell->SpellFamilyFlags & 0x0000040000000000LL) + // Sacred Shield + if (dummySpell->SpellFamilyFlags&0x0008000000000000LL) { - switch(triggeredByAura->GetEffIndex()) - { - case 0: - triggered_spell_id = 31893; - break; - case 1: - { - // damage - damage += CalculateDamage(BASE_ATTACK, false) * 35 / 100; // add spell damage from prev effect (35%) - basepoints0 = triggeredByAura->GetModifier()->m_amount * damage / 100; - - target = this; - triggered_spell_id = 32221; - break; - } - } + triggered_spell_id = 58597; + target = this; + break; } - switch(dummySpell->Id) { + // Judgement of Light + case 20185: + { + // Get judgement caster + Unit *caster = triggeredByAura->GetCaster(); + if (!caster) + return false; + float ap = caster->GetTotalAttackPowerValue(BASE_ATTACK); + int32 holy = caster->SpellBaseDamageBonus(SPELL_SCHOOL_MASK_HOLY) + + caster->SpellBaseDamageBonusForVictim(SPELL_SCHOOL_MASK_HOLY, this); + basepoints0 = int32(ap*0.10f + 0.10f*holy); + pVictim->CastCustomSpell(pVictim, 20267, &basepoints0, 0, 0, true, 0, triggeredByAura); + return true; + } + // Judgement of Wisdom + case 20186: + { + if (pVictim->getPowerType() == POWER_MANA) + pVictim->CastSpell(pVictim, 20268, true, 0, triggeredByAura); + return true; + } // Holy Power (Redemption Armor set) case 28789: { @@ -5296,6 +5397,40 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, Aura* triggeredByAu triggered_spell_id = 31786; break; } + // Seal of Blood do damage trigger + case 31892: + { + if (triggeredByAura->GetEffIndex() == 0) // 0 effect - is proc on enemy + triggered_spell_id = 31893; + else if (triggeredByAura->GetEffIndex() == 1) // 1 effect - is proc on self + { + // add spell damage from prev effect (27%) + damage += CalculateDamage(BASE_ATTACK, false) * 27 / 100; + basepoints0 = triggeredByAura->GetModifier()->m_amount * damage / 100; + target = this; + triggered_spell_id = 32221; + } + else + return true; + break; + } + // Seal of the Martyr do damage trigger + case 53720: + { + if (triggeredByAura->GetEffIndex() == 0) // 0 effect - is proc on enemy + triggered_spell_id = 53719; + else if (triggeredByAura->GetEffIndex() == 1) // 1 effect - is proc on self + { + // add spell damage from prev effect (27%) + damage += CalculateDamage(BASE_ATTACK, false) * 27 / 100; + basepoints0 = triggeredByAura->GetModifier()->m_amount * damage / 100; + target = this; + triggered_spell_id = 53718; + } + else + return true; + break; + } // Paladin Tier 6 Trinket (Ashtongue Talisman of Zeal) case 40470: { @@ -5506,8 +5641,27 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, Aura* triggeredByAu triggered_spell_id = 55533; break; } + // Spirit Hunt + case 58877: + { + // Cast on owner + target = GetOwner(); + if(!target) + return false; + basepoints0 = triggeredByAura->GetModifier()->m_amount * damage / 100; + triggered_spell_id = 58879; + break; + } + } + // Ancestral Awakening + if (dummySpell->SpellIconID == 2018) + { + // TODO: frite dummy fot triggered spell + triggered_spell_id = 52759; + basepoints0 = triggeredByAura->GetModifier()->m_amount * damage / 100; + target = this; + break; } - // Earth Shield if(dummySpell->SpellFamilyFlags & 0x0000040000000000LL) { @@ -5516,6 +5670,26 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, Aura* triggeredByAu triggered_spell_id = 379; break; } + // Improved Water Shield + if (dummySpell->SpellIconID == 2287) + { + // lookup water shield + AuraList const& vs = GetAurasByType(SPELL_AURA_PROC_TRIGGER_SPELL); + for(AuraList::const_iterator itr = vs.begin(); itr != vs.end(); ++itr) + { + if( (*itr)->GetSpellProto()->SpellFamilyName == SPELLFAMILY_SHAMAN && + (*itr)->GetSpellProto()->SpellFamilyFlags & 0x0000002000000000LL) + { + uint32 spell = (*itr)->GetSpellProto()->EffectTriggerSpell[(*itr)->GetEffIndex()]; + CastSpell(this, spell, true, castItem, triggeredByAura); + if ((*itr)->DropAuraCharge()) + RemoveAurasDueToSpell((*itr)->GetId()); + return true; + } + } + return false; + break; + } // Lightning Overload if (dummySpell->SpellIconID == 2018) // only this spell have SpellFamily Shaman SpellIconID == 2018 and dummy aura { @@ -5559,6 +5733,7 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, Aura* triggeredByAu return false; } // No thread generated mod + // TODO: exist special flag in spell attributes for this, need found and use! SpellModifier *mod = new SpellModifier; mod->op = SPELLMOD_THREAT; mod->value = -100; @@ -5581,10 +5756,78 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, Aura* triggeredByAu return true; } + // Static Shock + if(dummySpell->SpellIconID == 3059) + { + // lookup Lightning Shield + AuraList const& vs = GetAurasByType(SPELL_AURA_PROC_TRIGGER_SPELL); + for(AuraList::const_iterator itr = vs.begin(); itr != vs.end(); ++itr) + { + if( (*itr)->GetSpellProto()->SpellFamilyName == SPELLFAMILY_SHAMAN && + (*itr)->GetSpellProto()->SpellFamilyFlags & 0x0000000000000400LL) + { + uint32 spell = 0; + switch ((*itr)->GetId()) + { + case 324: spell = 26364; break; + case 325: spell = 26365; break; + case 905: spell = 26366; break; + case 945: spell = 26367; break; + case 8134: spell = 26369; break; + case 10431: spell = 26370; break; + case 10432: spell = 26363; break; + case 25469: spell = 26371; break; + case 25472: spell = 26372; break; + default: + return false; + } + CastSpell(this, spell, true, castItem, triggeredByAura); + if ((*itr)->DropAuraCharge()) + RemoveAurasDueToSpell((*itr)->GetId()); + return true; + } + } + return false; + break; + } break; } case SPELLFAMILY_DEATHKNIGHT: { + // Blood Aura + if (dummySpell->SpellIconID == 2636) + { + if (GetTypeId() != TYPEID_PLAYER || !((Player*)this)->isHonorOrXPTarget(pVictim)) + return false; + basepoints0 = triggeredByAura->GetModifier()->m_amount * damage / 100; + triggered_spell_id = 53168; + break; + } + // Butchery + if (dummySpell->SpellIconID == 2664) + { + basepoints0 = triggeredByAura->GetModifier()->m_amount; + triggered_spell_id = 50163; + target = this; + break; + } + // Dancing Rune Weapon + if (dummySpell->Id == 49028) + { + // 1 dummy aura for dismiss rune blade + if (triggeredByAura->GetEffIndex()!=2) + return false; + // TODO: wite script for this "fights on its own, doing the same attacks" + // NOTE: Trigger here on every attack and spell cast + return false; + } + // Mark of Blood + if (dummySpell->Id == 49005) + { + // TODO: need more info (cooldowns/PPM) + triggered_spell_id = 50424; + break; + } // Vendetta if (dummySpell->SpellFamilyFlags & 0x0000000000010000LL) { @@ -5594,20 +5837,34 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, Aura* triggeredByAu break; } // Necrosis - else if (dummySpell->SpellIconID == 2709) + if (dummySpell->SpellIconID == 2709) { basepoints0 = triggeredByAura->GetModifier()->m_amount * damage / 100; triggered_spell_id = 51460; break; } - // Butchery - else if (dummySpell->SpellIconID == 2664) + // Runic Power Back on Snare/Root + if (dummySpell->Id == 61257) { - basepoints0 = triggeredByAura->GetModifier()->m_amount; - triggered_spell_id = 50163; + // only for spells and hit/crit (trigger start always) and not start from self casted spells + if (procSpell == 0 || !(procEx & (PROC_EX_NORMAL_HIT|PROC_EX_CRITICAL_HIT)) || this == pVictim) + return false; + // Need snare or root mechanic + if (!(GetAllSpellMechanicMask(procSpell) & ((1<SpellIconID == 1614) + { + if (!roll_chance_f(GetUnitCriticalChance(BASE_ATTACK, pVictim))) + return false; + basepoints0 = triggeredByAura->GetModifier()->m_amount * damage / 100; + triggered_spell_id = 50526; + break; + } break; } default: @@ -6076,10 +6333,6 @@ bool Unit::HandleProcTriggerSpell(Unit *pVictim, uint32 damage, Aura* triggeredB trigger_spell_id = 26371; break; case 25472: // Rank 9 trigger_spell_id = 26372; break; - case 49280: // Rank 10 - trigger_spell_id = 49278; break; - case 49281: // Rank 11 - trigger_spell_id = 49279; break; default: sLog.outError("Unit::HandleProcTriggerSpell: Spell %u not handled in LShield", auraSpellInfo->Id); return false; @@ -6298,8 +6551,9 @@ bool Unit::HandleProcTriggerSpell(Unit *pVictim, uint32 damage, Aura* triggeredB // Astral Shift case 52179: { - if(!procSpell) + if (procSpell == 0 || !(procEx & (PROC_EX_NORMAL_HIT|PROC_EX_CRITICAL_HIT)) || this == pVictim) return false; + // Need stun, fear or silence mechanic if (!(GetAllSpellMechanicMask(procSpell) & ((1<GetAurasByType(SPELL_AURA_MOD_DAMAGE_FROM_CASTER); + for(AuraList::const_iterator i = mOwnerTaken.begin(); i != mOwnerTaken.end(); ++i) + if( (*i)->GetCasterGUID() == GetGUID() && (*i)->isAffectedOnSpell(spellProto)) + TakenTotalMod *= ((*i)->GetModifier()->m_amount+100.0f)/100.0f; + // Distribute Damage over multiple effects, reduce by AoE CastingTime = GetCastingTimeForBonus( spellProto, damagetype, CastingTime ); @@ -7329,21 +7589,10 @@ uint32 Unit::SpellDamageBonus(Unit *pVictim, SpellEntry const *spellProto, uint3 DotFactor = 0.95f; CastingTime = 3500; } - // Seal of Righteousness - 10.2%/9.8% ( based on weapon type ) of Holy Damage, multiplied by weapon speed - else if((spellProto->SpellFamilyFlags & 0x8000000LL) && spellProto->SpellIconID == 25) + // Judgement of Righteousness - 32% + else if (spellProto->SpellFamilyFlags & 0x0000000000000400LL) { - Item *item = ((Player*)this)->GetItemByPos(INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_MAINHAND); - float wspeed = GetAttackTime(BASE_ATTACK)/1000.0f; - - if( item && item->GetProto()->InventoryType == INVTYPE_2HWEAPON) - CastingTime = uint32(wspeed*3500*0.102f); - else - CastingTime = uint32(wspeed*3500*0.098f); - } - // Judgement of Righteousness - 73% - else if ((spellProto->SpellFamilyFlags & 1024) && spellProto->SpellIconID == 25) - { - CastingTime = 2555; + CastingTime = 1120; } // Seal of Vengeance - 17% per Fully Stacked Tick - 5 Applications else if ((spellProto->SpellFamilyFlags & 0x80000000000LL) && spellProto->SpellIconID == 2292) @@ -7361,11 +7610,6 @@ uint32 Unit::SpellDamageBonus(Unit *pVictim, SpellEntry const *spellProto, uint3 { CastingTime = 0; } - // Seal of Righteousness trigger - already computed for parent spell - else if ( spellProto->SpellFamilyName==SPELLFAMILY_PALADIN && spellProto->SpellIconID==25 && spellProto->AttributesEx4 & 0x00800000LL ) - { - return pdamage; - } break; case SPELLFAMILY_SHAMAN: // totem attack @@ -7482,6 +7726,9 @@ int32 Unit::SpellBaseDamageBonus(SpellSchoolMask schoolMask) if (GetTypeId() == TYPEID_PLAYER) { + // Base value + DoneAdvertisedBenefit +=((Player*)this)->GetBaseSpellDamageBonus(); + // Damage bonus from stats AuraList const& mDamageDoneOfStatPercent = GetAurasByType(SPELL_AURA_MOD_SPELL_DAMAGE_OF_STAT_PERCENT); for(AuraList::const_iterator i = mDamageDoneOfStatPercent.begin();i != mDamageDoneOfStatPercent.end(); ++i) @@ -7572,7 +7819,7 @@ bool Unit::isSpellCrit(Unit *pVictim, SpellEntry const *spellProto, SpellSchoolM } // Glyph of Shadowburn if (spellProto->SpellFamilyName == SPELLFAMILY_WARLOCK && - spellProto->SpellFamilyFlags & 0x0000000000000080 && + spellProto->SpellFamilyFlags & 0x0000000000000080LL && pVictim->HasAuraState(AURA_STATE_HEALTHLESS_35_PERCENT)) { AuraList const& mOverrideClassScript = GetAurasByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS); @@ -7580,6 +7827,14 @@ bool Unit::isSpellCrit(Unit *pVictim, SpellEntry const *spellProto, SpellSchoolM if((*i)->GetModifier()->m_miscvalue == 7917) crit_chance+=(*i)->GetModifier()->m_amount; } + // Sacred Shield + if (spellProto->SpellFamilyName == SPELLFAMILY_PALADIN && + spellProto->SpellFamilyFlags & 0x0000000040000000LL) + { + Aura *aura = pVictim->GetDummyAura(58597); + if (aura && aura->GetCasterGUID() == GetGUID()) + crit_chance+=aura->GetModifier()->m_amount; + } } break; } @@ -7839,6 +8094,9 @@ int32 Unit::SpellBaseHealingBonus(SpellSchoolMask schoolMask) // Healing bonus of spirit, intellect and strength if (GetTypeId() == TYPEID_PLAYER) { + // Base value + AdvertisedBenefit +=((Player*)this)->GetBaseSpellHealingBonus(); + // Healing bonus from stats AuraList const& mHealingDoneOfStatPercent = GetAurasByType(SPELL_AURA_MOD_SPELL_HEALING_OF_STAT_PERCENT); for(AuraList::const_iterator i = mHealingDoneOfStatPercent.begin();i != mHealingDoneOfStatPercent.end(); ++i) @@ -7923,18 +8181,30 @@ bool Unit::IsImmunedToSpell(SpellEntry const* spellInfo) return false; } -bool Unit::IsImmunedToSpellEffect(uint32 effect, uint32 mechanic) const +bool Unit::IsImmunedToSpellEffect(SpellEntry const* spellInfo, uint32 index) const { //If m_immuneToEffect type contain this effect type, IMMUNE effect. + uint32 effect = spellInfo->Effect[index]; SpellImmuneList const& effectList = m_spellImmune[IMMUNITY_EFFECT]; for (SpellImmuneList::const_iterator itr = effectList.begin(); itr != effectList.end(); ++itr) if(itr->type == effect) return true; - SpellImmuneList const& mechanicList = m_spellImmune[IMMUNITY_MECHANIC]; - for (SpellImmuneList::const_iterator itr = mechanicList.begin(); itr != mechanicList.end(); ++itr) - if(itr->type == mechanic) - return true; + if(uint32 mechanic = spellInfo->EffectMechanic[index]) + { + SpellImmuneList const& mechanicList = m_spellImmune[IMMUNITY_MECHANIC]; + for (SpellImmuneList::const_iterator itr = mechanicList.begin(); itr != mechanicList.end(); ++itr) + if(itr->type == mechanic) + return true; + } + + if(uint32 aura = spellInfo->EffectApplyAuraName[index]) + { + SpellImmuneList const& list = m_spellImmune[IMMUNITY_STATE]; + for(SpellImmuneList::const_iterator itr = list.begin(); itr != list.end(); ++itr) + if(itr->type == aura) + return true; + } return false; } @@ -9021,20 +9291,46 @@ bool Unit::SelectHostilTarget() //threat list sorting etc. assert(GetTypeId()== TYPEID_UNIT); - Unit* target = NULL; //This function only useful once AI has been initialized if (!((Creature*)this)->AI()) return false; - if(!m_ThreatManager.isThreatListEmpty()) + Unit* target = NULL; + + // First checking if we have some taunt on us + const AuraList& tauntAuras = GetAurasByType(SPELL_AURA_MOD_TAUNT); + if ( !tauntAuras.empty() ) { - if(!HasAuraType(SPELL_AURA_MOD_TAUNT)) + Unit* caster; + + // The last taunt aura caster is alive an we are happy to attack him + if ( (caster = tauntAuras.back()->GetCaster()) && caster->isAlive() ) + return true; + else if (tauntAuras.size() > 1) { - target = m_ThreatManager.getHostilTarget(); + // We do not have last taunt aura caster but we have more taunt auras, + // so find first available target + + // Auras are pushed_back, last caster will be on the end + AuraList::const_iterator aura = --tauntAuras.end(); + do + { + --aura; + if ( (caster = (*aura)->GetCaster()) && + caster->IsInMap(this) && caster->isTargetableForAttack() && caster->isInAccessablePlaceFor((Creature*)this) ) + { + target = caster; + break; + } + }while (aura != tauntAuras.begin()); } } + if ( !target && !m_ThreatManager.isThreatListEmpty() ) + // No taunt aura or taunt aura caster is dead standart target selection + target = m_ThreatManager.getHostilTarget(); + if(target) { if(!hasUnitState(UNIT_STAT_STUNNED)) @@ -9197,21 +9493,15 @@ DiminishingLevels Unit::GetDiminishing(DiminishingGroup group) void Unit::IncrDiminishing(DiminishingGroup group) { // Checking for existing in the table - bool IsExist = false; for(Diminishing::iterator i = m_Diminishing.begin(); i != m_Diminishing.end(); ++i) { if(i->DRGroup != group) continue; - - IsExist = true; if(i->hitCount < DIMINISHING_LEVEL_IMMUNE) i->hitCount += 1; - - break; + return; } - - if(!IsExist) - m_Diminishing.push_back(DiminishingReturn(group,getMSTime(),DIMINISHING_LEVEL_2)); + m_Diminishing.push_back(DiminishingReturn(group,getMSTime(),DIMINISHING_LEVEL_2)); } void Unit::ApplyDiminishingToDuration(DiminishingGroup group, int32 &duration,Unit* caster,DiminishingLevels Level) @@ -9260,13 +9550,15 @@ void Unit::ApplyDiminishingAura( DiminishingGroup group, bool apply ) if(i->DRGroup != group) continue; - i->hitTime = getMSTime(); - if(apply) i->stack += 1; else if(i->stack) + { i->stack -= 1; - + // Remember time after last aura from group removed + if (i->stack == 0) + i->hitTime = getMSTime(); + } break; } } @@ -9937,6 +10229,7 @@ bool InitTriggerAuraData() isTriggerAura[SPELL_AURA_MOD_ATTACKER_MELEE_HIT_CHANCE]=true; isTriggerAura[SPELL_AURA_PRAYER_OF_MENDING] = true; isTriggerAura[SPELL_AURA_PROC_TRIGGER_SPELL_WITH_VALUE] = true; + isTriggerAura[SPELL_AURA_MOD_DAMAGE_FROM_CASTER] = true; isNonTriggerAura[SPELL_AURA_MOD_POWER_REGEN]=true; isNonTriggerAura[SPELL_AURA_RESIST_PUSHBACK]=true; @@ -10191,6 +10484,11 @@ void Unit::ProcDamageAndSpellFor( bool isVictim, Unit * pTarget, uint32 procFlag if (procSpell==NULL || procSpell->Mechanic != auraModifier->m_miscvalue) continue; break; + case SPELL_AURA_MOD_DAMAGE_FROM_CASTER: + // Compare casters + if (triggeredByAura->GetCasterGUID() != pTarget->GetGUID()) + continue; + break; default: // nothing do, just charges counter break; @@ -10817,7 +11115,6 @@ Pet* Unit::CreateTamedPetFrom(Creature* creatureTarget,uint32 spell_id) pet->SetUInt32Value(UNIT_FIELD_FLAGS, UNIT_FLAG_PVP_ATTACKABLE); uint32 level = (creatureTarget->getLevel() < (getLevel() - 5)) ? (getLevel() - 5) : creatureTarget->getLevel(); - pet->SetFreeTalentPoints(pet->GetMaxTalentPointsForLevel(level)); if(!pet->InitStatsForLevel(level)) { @@ -10830,6 +11127,7 @@ Pet* Unit::CreateTamedPetFrom(Creature* creatureTarget,uint32 spell_id) // this enables pet details window (Shift+P) pet->AIM_Initialize(); pet->InitPetCreateSpells(); + pet->InitTalentForLevel(); pet->SetHealth(pet->GetMaxHealth()); return pet; diff --git a/src/game/Unit.h b/src/game/Unit.h index 376e59cf8..a779ba874 100644 --- a/src/game/Unit.h +++ b/src/game/Unit.h @@ -40,7 +40,8 @@ enum SpellInterruptFlags SPELL_INTERRUPT_FLAG_DAMAGE = 0x02, SPELL_INTERRUPT_FLAG_INTERRUPT = 0x04, SPELL_INTERRUPT_FLAG_AUTOATTACK = 0x08, - //SPELL_INTERRUPT_FLAG_TURNING = 0x10 // not turning - maybe _complete_ interrupt on direct damage? + SPELL_INTERRUPT_FLAG_ABORT_ON_DMG = 0x10, // _complete_ interrupt on direct damage + //SPELL_INTERRUPT_UNK = 0x20 // unk, 564 of 727 spells having this spell start with "Glyph" }; enum SpellChannelInterruptFlags @@ -458,23 +459,23 @@ enum UnitVisibility // Value masks for UNIT_FIELD_FLAGS enum UnitFlags { - UNIT_FLAG_UNKNOWN7 = 0x00000001, + UNIT_FLAG_UNK_0 = 0x00000001, UNIT_FLAG_NON_ATTACKABLE = 0x00000002, // not attackable UNIT_FLAG_DISABLE_MOVE = 0x00000004, UNIT_FLAG_PVP_ATTACKABLE = 0x00000008, // allow apply pvp rules to attackable state in addition to faction dependent state UNIT_FLAG_RENAME = 0x00000010, UNIT_FLAG_PREPARATION = 0x00000020, // don't take reagents for spells with SPELL_ATTR_EX5_NO_REAGENT_WHILE_PREP - UNIT_FLAG_UNKNOWN9 = 0x00000040, + UNIT_FLAG_UNK_6 = 0x00000040, UNIT_FLAG_NOT_ATTACKABLE_1 = 0x00000080, // ?? (UNIT_FLAG_PVP_ATTACKABLE | UNIT_FLAG_NOT_ATTACKABLE_1) is NON_PVP_ATTACKABLE - UNIT_FLAG_UNKNOWN2 = 0x00000100, // 2.0.8 - UNIT_FLAG_UNKNOWN11 = 0x00000200, // 3.0.3 - makes you unable to attack everything + UNIT_FLAG_UNK_8 = 0x00000100, // 2.0.8 + UNIT_FLAG_UNK_9 = 0x00000200, // 3.0.3 - makes you unable to attack everything UNIT_FLAG_LOOTING = 0x00000400, // loot animation UNIT_FLAG_PET_IN_COMBAT = 0x00000800, // in combat?, 2.0.8 UNIT_FLAG_PVP = 0x00001000, // changed in 3.0.3 UNIT_FLAG_SILENCED = 0x00002000, // silenced, 2.1.1 - UNIT_FLAG_UNKNOWN4 = 0x00004000, // 2.0.8 - UNIT_FLAG_UNKNOWN13 = 0x00008000, - UNIT_FLAG_UNKNOWN14 = 0x00010000, + UNIT_FLAG_UNK_14 = 0x00004000, // 2.0.8 + UNIT_FLAG_UNK_15 = 0x00008000, + UNIT_FLAG_UNK_16 = 0x00010000, UNIT_FLAG_PACIFIED = 0x00020000, // 3.0.3 ok UNIT_FLAG_STUNNED = 0x00040000, // 3.0.3 ok UNIT_FLAG_IN_COMBAT = 0x00080000, @@ -482,19 +483,21 @@ enum UnitFlags UNIT_FLAG_DISARMED = 0x00200000, // 3.0.3, disable melee spells casting..., "Required melee weapon" added to melee spells tooltip. UNIT_FLAG_CONFUSED = 0x00400000, UNIT_FLAG_FLEEING = 0x00800000, - UNIT_FLAG_UNKNOWN5 = 0x01000000, // used in spell Eyes of the Beast for pet... + UNIT_FLAG_UNK_24 = 0x01000000, // used in spell Eyes of the Beast for pet... UNIT_FLAG_NOT_SELECTABLE = 0x02000000, UNIT_FLAG_SKINNABLE = 0x04000000, UNIT_FLAG_MOUNT = 0x08000000, - UNIT_FLAG_UNKNOWN17 = 0x10000000, - UNIT_FLAG_UNKNOWN6 = 0x20000000, // used in Feing Death spell - UNIT_FLAG_SHEATHE = 0x40000000 + UNIT_FLAG_UNK_28 = 0x10000000, + UNIT_FLAG_UNK_29 = 0x20000000, // used in Feing Death spell + UNIT_FLAG_SHEATHE = 0x40000000, + UNIT_FLAG_UNK_31 = 0x80000000 }; // Value masks for UNIT_FIELD_FLAGS_2 enum UnitFlags2 { UNIT_FLAG2_FEIGN_DEATH = 0x00000001, + UNIT_FLAG2_UNK1 = 0x00000002, // Hide unit model (show only player equip) UNIT_FLAG2_COMPREHEND_LANG = 0x00000008, UNIT_FLAG2_FORCE_MOVE = 0x00000040, UNIT_FLAG2_REGENERATE_POWER = 0x00000800 @@ -643,6 +646,8 @@ uint32 createProcExtendMask(SpellNonMeleeDamage *damageInfo, SpellMissInfo missC struct UnitActionBarEntry { + UnitActionBarEntry() : Raw(0) {} + union { struct @@ -798,9 +803,7 @@ class MANGOS_DLL_SPEC Unit : public WorldObject } void _removeAttacker(Unit *pAttacker) // must be called only from Unit::AttackStop() { - AttackerSet::iterator itr = m_attackers.find(pAttacker); - if(itr != m_attackers.end()) - m_attackers.erase(itr); + m_attackers.erase(pAttacker); } Unit * getAttackerForHelper() // If someone wants to help, who to give them { @@ -1208,7 +1211,6 @@ class MANGOS_DLL_SPEC Unit : public WorldObject // function for low level grid visibility checks in player/creature cases virtual bool IsVisibleInGridForPlayer(Player* pl) const = 0; - bool waterbreath; AuraList & GetSingleCastAuras() { return m_scAuras; } AuraList const& GetSingleCastAuras() const { return m_scAuras; } SpellImmuneList m_spellImmune[MAX_SPELL_IMMUNITY]; @@ -1236,14 +1238,7 @@ class MANGOS_DLL_SPEC Unit : public WorldObject void SetVisibleAura(uint8 slot, uint32 spellid) { if(spellid == 0) - { - VisibleAuraMap::iterator itr = m_visibleAuras.find(slot); - if(itr != m_visibleAuras.end()) - { - m_visibleAuras.erase(itr); - return; - } - } + m_visibleAuras.erase(slot); else m_visibleAuras[slot] = spellid; } @@ -1317,7 +1312,7 @@ class MANGOS_DLL_SPEC Unit : public WorldObject virtual bool IsImmunedToSpell(SpellEntry const* spellInfo); // redefined in Creature bool IsImmunedToDamage(SpellSchoolMask meleeSchoolMask); - virtual bool IsImmunedToSpellEffect(uint32 effect, uint32 mechanic) const; + virtual bool IsImmunedToSpellEffect(SpellEntry const* spellInfo, uint32 index) const; // redefined in Creature uint32 CalcArmorReducedDamage(Unit* pVictim, const uint32 damage); diff --git a/src/game/UpdateMask.h b/src/game/UpdateMask.h index d356799f6..5b844ad54 100644 --- a/src/game/UpdateMask.h +++ b/src/game/UpdateMask.h @@ -34,27 +34,27 @@ class UpdateMask delete [] mUpdateMask; } - inline void SetBit (uint32 index) + void SetBit (uint32 index) { ( (uint8 *)mUpdateMask )[ index >> 3 ] |= 1 << ( index & 0x7 ); } - inline void UnsetBit (uint32 index) + void UnsetBit (uint32 index) { ( (uint8 *)mUpdateMask )[ index >> 3 ] &= (0xff ^ (1 << ( index & 0x7 ) ) ); } - inline bool GetBit (uint32 index) + bool GetBit (uint32 index) const { return ( ( (uint8 *)mUpdateMask)[ index >> 3 ] & ( 1 << ( index & 0x7 ) )) != 0; } - inline uint32 GetBlockCount() { return mBlocks; } - inline uint32 GetLength() { return mBlocks << 2; } - inline uint32 GetCount() { return mCount; } - inline uint8* GetMask() { return (uint8*)mUpdateMask; } + uint32 GetBlockCount() const { return mBlocks; } + uint32 GetLength() const { return mBlocks << 2; } + uint32 GetCount() const { return mCount; } + uint8* GetMask() { return (uint8*)mUpdateMask; } - inline void SetCount (uint32 valuesCount) + void SetCount (uint32 valuesCount) { if(mUpdateMask) delete [] mUpdateMask; @@ -66,13 +66,13 @@ class UpdateMask memset(mUpdateMask, 0, mBlocks << 2); } - inline void Clear() + void Clear() { if (mUpdateMask) memset(mUpdateMask, 0, mBlocks << 2); } - inline UpdateMask& operator = ( const UpdateMask& mask ) + UpdateMask& operator = ( const UpdateMask& mask ) { SetCount(mask.mCount); memcpy(mUpdateMask, mask.mUpdateMask, mBlocks << 2); @@ -80,21 +80,21 @@ class UpdateMask return *this; } - inline void operator &= ( const UpdateMask& mask ) + void operator &= ( const UpdateMask& mask ) { ASSERT(mask.mCount <= mCount); for (uint32 i = 0; i < mBlocks; i++) mUpdateMask[i] &= mask.mUpdateMask[i]; } - inline void operator |= ( const UpdateMask& mask ) + void operator |= ( const UpdateMask& mask ) { ASSERT(mask.mCount <= mCount); for (uint32 i = 0; i < mBlocks; i++) mUpdateMask[i] |= mask.mUpdateMask[i]; } - inline UpdateMask operator & ( const UpdateMask& mask ) const + UpdateMask operator & ( const UpdateMask& mask ) const { ASSERT(mask.mCount <= mCount); @@ -105,7 +105,7 @@ class UpdateMask return newmask; } - inline UpdateMask operator | ( const UpdateMask& mask ) const + UpdateMask operator | ( const UpdateMask& mask ) const { ASSERT(mask.mCount <= mCount); diff --git a/src/game/WaypointMovementGenerator.h b/src/game/WaypointMovementGenerator.h index 785940d0f..cc552d974 100644 --- a/src/game/WaypointMovementGenerator.h +++ b/src/game/WaypointMovementGenerator.h @@ -46,7 +46,7 @@ class MANGOS_DLL_SPEC PathMovementBase PathMovementBase() : i_currentNode(0) {} virtual ~PathMovementBase() {}; - inline bool MovementInProgress(void) const { return i_currentNode < i_path.Size(); } + bool MovementInProgress(void) const { return i_currentNode < i_path.Size(); } // template pattern, not defined .. override required void LoadPath(T &); @@ -135,7 +135,7 @@ public PathMovementBase Path& GetPath() { return i_path; } uint32 GetPathAtMapEnd() const; - inline bool HasArrived() const { return (i_currentNode >= i_path.Size()); } + bool HasArrived() const { return (i_currentNode >= i_path.Size()); } void SetCurrentNodeAfterTeleport(); void SkipCurrentNode() { ++i_currentNode; } }; diff --git a/src/game/Weather.cpp b/src/game/Weather.cpp index 5e7c6cf27..aea7c19b9 100644 --- a/src/game/Weather.cpp +++ b/src/game/Weather.cpp @@ -40,7 +40,7 @@ Weather::Weather(uint32 zone, WeatherZoneChances const* weatherChances) : m_zone } /// Launch a weather update -bool Weather::Update(time_t diff) +bool Weather::Update(uint32 diff) { if (m_timer.GetCurrent()>=0) m_timer.Update(diff); diff --git a/src/game/Weather.h b/src/game/Weather.h index d7f10bebd..2cf86276a 100644 --- a/src/game/Weather.h +++ b/src/game/Weather.h @@ -60,7 +60,7 @@ class Weather void SetWeather(WeatherType type, float grade); /// For which zone is this weather? uint32 GetZone() { return m_zone; }; - bool Update(time_t diff); + bool Update(uint32 diff); private: WeatherState GetWeatherState() const; uint32 m_zone; diff --git a/src/game/World.cpp b/src/game/World.cpp index 74be1cbe8..072f6cac5 100644 --- a/src/game/World.cpp +++ b/src/game/World.cpp @@ -464,7 +464,6 @@ void World::LoadConfigSettings(bool reload) rate_values[RATE_XP_KILL] = sConfig.GetFloatDefault("Rate.XP.Kill", 1.0f); rate_values[RATE_XP_QUEST] = sConfig.GetFloatDefault("Rate.XP.Quest", 1.0f); rate_values[RATE_XP_EXPLORE] = sConfig.GetFloatDefault("Rate.XP.Explore", 1.0f); - rate_values[RATE_XP_PAST_70] = sConfig.GetFloatDefault("Rate.XP.PastLevel70", 1.0f); rate_values[RATE_REPUTATION_GAIN] = sConfig.GetFloatDefault("Rate.Reputation.Gain", 1.0f); rate_values[RATE_CREATURE_NORMAL_DAMAGE] = sConfig.GetFloatDefault("Rate.Creature.Normal.Damage", 1.0f); rate_values[RATE_CREATURE_ELITE_ELITE_DAMAGE] = sConfig.GetFloatDefault("Rate.Creature.Elite.Elite.Damage", 1.0f); @@ -1413,7 +1412,7 @@ void World::DetectDBCLang() } /// Update the World ! -void World::Update(time_t diff) +void World::Update(uint32 diff) { ///- Update the different timers for(int i = 0; i < WUPDATE_COUNT; i++) @@ -2592,7 +2591,7 @@ void World::SendServerMessage(uint32 type, const char *text, Player* player) SendGlobalMessage( &data ); } -void World::UpdateSessions( time_t diff ) +void World::UpdateSessions( uint32 diff ) { ///- Add new sessions while(!addSessQueue.empty()) diff --git a/src/game/World.h b/src/game/World.h index 98622effe..3f2640ffa 100644 --- a/src/game/World.h +++ b/src/game/World.h @@ -217,7 +217,6 @@ enum Rates RATE_XP_KILL, RATE_XP_QUEST, RATE_XP_EXPLORE, - RATE_XP_PAST_70, RATE_REPUTATION_GAIN, RATE_CREATURE_NORMAL_HP, RATE_CREATURE_ELITE_ELITE_HP, @@ -427,9 +426,9 @@ class World static void StopNow(uint8 exitcode) { m_stopEvent = true; m_ExitCode = exitcode; } static bool IsStopped() { return m_stopEvent; } - void Update(time_t diff); + void Update(uint32 diff); - void UpdateSessions( time_t diff ); + void UpdateSessions( uint32 diff ); /// Set a server rate (see #Rates) void setRate(Rates rate,float value) { rate_values[rate]=value; } /// Get a server rate (see #Rates) diff --git a/src/game/WorldLog.h b/src/game/WorldLog.h index de8475dd0..8a20d1018 100644 --- a/src/game/WorldLog.h +++ b/src/game/WorldLog.h @@ -49,9 +49,9 @@ class MANGOS_DLL_DECL WorldLog : public MaNGOS::Singleton - - - - @@ -785,7 +777,7 @@ @@ -807,7 +799,7 @@ @@ -817,6 +809,14 @@ RelativePath="..\..\src\shared\revision_nr.h" > + + + + diff --git a/win/VC90/shared.vcproj b/win/VC90/shared.vcproj index 3254e559c..32931be90 100644 --- a/win/VC90/shared.vcproj +++ b/win/VC90/shared.vcproj @@ -781,7 +781,7 @@ @@ -803,7 +803,7 @@