Merge branch 'master' into 308

This commit is contained in:
tomrus88 2009-01-21 10:59:27 +03:00
commit 8ffa79211b
129 changed files with 3156 additions and 1666 deletions

View file

@ -1,23 +0,0 @@
# Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
## 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.

View file

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

View file

@ -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

View file

@ -1,13 +1,7 @@
Linux instructions Linux instructions
------------------ ------------------
1. Configure and build MaNGOS. 1. install cmake
2. cd contrib/map_extractor/libmpq/ 2. cmake -i
3. make 3. make
4. cd .. 4. ./ad
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 :)

View file

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

View file

@ -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

View file

@ -21,7 +21,7 @@
DROP TABLE IF EXISTS `character_db_version`; DROP TABLE IF EXISTS `character_db_version`;
CREATE TABLE `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'; ) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=FIXED COMMENT='Last applied sql update to DB';
-- --

View file

@ -22,7 +22,7 @@
DROP TABLE IF EXISTS `db_version`; DROP TABLE IF EXISTS `db_version`;
CREATE TABLE `db_version` ( CREATE TABLE `db_version` (
`version` varchar(120) default NULL, `version` varchar(120) default NULL,
`required_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'; ) 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), (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), (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), (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), (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), (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), (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), (1106,'%d - %s %s',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL),
(1107,'%d - %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), (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), (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), (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), (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), (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), (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), (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 */; /*!40000 ALTER TABLE `mangos_string` ENABLE KEYS */;
UNLOCK TABLES; UNLOCK TABLES;
@ -9291,6 +9292,105 @@ INSERT INTO `player_levelstats` VALUES
/*!40000 ALTER TABLE `player_levelstats` ENABLE KEYS */; /*!40000 ALTER TABLE `player_levelstats` ENABLE KEYS */;
UNLOCK TABLES; 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` -- Table structure for table `playercreateinfo`
-- --
@ -12899,8 +12999,9 @@ DROP TABLE IF EXISTS `skill_discovery_template`;
CREATE TABLE `skill_discovery_template` ( CREATE TABLE `skill_discovery_template` (
`spellId` mediumint(8) unsigned NOT NULL default '0' COMMENT 'SpellId of the discoverable spell', `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', `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', `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'; ) 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 */; /*!40000 ALTER TABLE `spell_learn_spell` ENABLE KEYS */;
UNLOCK TABLES; 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` -- 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), (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), (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), (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), (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), (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), (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), (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), (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), (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), (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), (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), (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), (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), (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), (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), (35100, 0x00000000, 9, 0x00003001, 0x00000000, 0x00000000, 0x00010140, 0x00000000, 0.000000, 0.000000, 0),
(35102, 0x00000000, 9, 0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 0), (35102, 0x00000000, 9, 0x00003001, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 0),
(35103, 0x00000000, 9, 0x00000001, 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), (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), (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), (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), (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), (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), (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), (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), (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), (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), (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), (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), (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), (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), (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), (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), (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), (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), (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), (47535, 0x00000000, 6, 0x00001800, 0x00800000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 0),
(47536, 0x00000000, 6, 0x00001800, 0x00800000, 0x00000000, 0x00000000, 0x00010000, 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, 0x00010000, 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, 0x00010000, 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, 0x00010000, 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), (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), (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), (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), (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), (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), (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), (47580, 0x00000000, 6, 0x00000000, 0x00000000, 0x00000040, 0x00000000, 0x00010000, 0.000000, 0.000000, 0),
(47581, 0x00000000, 6, 0x00000000, 0x00000000, 0x00000040, 0x00000000, 0x00000000, 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, 0x00000000, 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), (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), (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), (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), (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), (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), (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); (61324, 0x00000000, 10, 0x00000000, 0x00020000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 0);
/*!40000 ALTER TABLE `spell_proc_event` ENABLE KEYS */; /*!40000 ALTER TABLE `spell_proc_event` ENABLE KEYS */;
UNLOCK TABLES; UNLOCK TABLES;

View file

@ -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(TRIM(data),' ');
UPDATE item_instance SET data= CONCAT( UPDATE item_instance SET data= CONCAT(
SUBSTRING_INDEX(SUBSTRING_INDEX(data,' ',30),' ',-30),' 0 0 0 ', SUBSTRING_INDEX(SUBSTRING_INDEX(data,' ',54),' ',-54),' 0 0 0 ',
SUBSTRING_INDEX(SUBSTRING_INDEX(data,' ',60),' ',-60+30),' 0 ') SUBSTRING_INDEX(SUBSTRING_INDEX(data,' ',60),' ',-60+54),' 0 ')
WHERE SUBSTRING_INDEX(data,' ',60) = data AND SUBSTRING_INDEX(data,' ',60-1) <> data; WHERE SUBSTRING_INDEX(data,' ',60) = data AND SUBSTRING_INDEX(data,' ',60-1) <> data;
UPDATE item_instance SET data= CONCAT( UPDATE item_instance SET data= CONCAT(

View file

@ -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;

View file

@ -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);

View file

@ -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');

View file

@ -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);

View file

@ -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;

View file

@ -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);

View file

@ -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;

View file

@ -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;

View file

@ -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;

View file

@ -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';

View file

@ -135,6 +135,16 @@ pkgdata_DATA = \
7074_01_mangos_playercreateinfo_spell.sql \ 7074_01_mangos_playercreateinfo_spell.sql \
7075_01_characters_character_spell.sql \ 7075_01_characters_character_spell.sql \
7075_02_mangos_spell_learn_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 README
## Additional files to include when running 'make dist' ## Additional files to include when running 'make dist'
@ -250,4 +260,14 @@ EXTRA_DIST = \
7074_01_mangos_playercreateinfo_spell.sql \ 7074_01_mangos_playercreateinfo_spell.sql \
7075_01_characters_character_spell.sql \ 7075_01_characters_character_spell.sql \
7075_02_mangos_spell_learn_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 README

View file

@ -74,12 +74,12 @@ class MANGOS_DLL_DECL NGrid
const GridType& operator()(unsigned short x, unsigned short y) const { return i_cells[x][y]; } 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]; } GridType& operator()(unsigned short x, unsigned short y) { return i_cells[x][y]; }
inline const uint32& GetGridId(void) const { return i_gridId; } const uint32& GetGridId(void) const { return i_gridId; }
inline void SetGridId(const uint32 id) const { i_gridId = id; } void SetGridId(const uint32 id) const { i_gridId = id; }
inline grid_state_t GetGridState(void) const { return i_cellstate; } grid_state_t GetGridState(void) const { return i_cellstate; }
inline void SetGridState(grid_state_t s) { i_cellstate = s; } void SetGridState(grid_state_t s) { i_cellstate = s; }
inline int32 getX() const { return i_x; } int32 getX() const { return i_x; }
inline int32 getY() const { return i_y; } int32 getY() const { return i_y; }
void link(GridRefManager<NGrid<N, ACTIVE_OBJECT, WORLD_OBJECT_TYPES, GRID_OBJECT_TYPES, ThreadModel> >* pTo) void link(GridRefManager<NGrid<N, ACTIVE_OBJECT, WORLD_OBJECT_TYPES, GRID_OBJECT_TYPES, ThreadModel> >* pTo)
{ {

View file

@ -32,7 +32,7 @@ namespace MaNGOS
class MANGOS_DLL_DECL ObjectLifeTime class MANGOS_DLL_DECL ObjectLifeTime
{ {
public: public:
inline static void ScheduleCall(void (*destroyer)() ) static void ScheduleCall(void (*destroyer)() )
{ {
at_exit( destroyer ); at_exit( destroyer );
} }
@ -42,7 +42,7 @@ namespace MaNGOS
}; };
template <class T> template <class T>
inline void ObjectLifeTime<T>::OnDeadReference(void)// We don't handle Dead Reference for now void ObjectLifeTime<T>::OnDeadReference(void) // We don't handle Dead Reference for now
{ {
throw std::runtime_error("Dead Reference"); throw std::runtime_error("Dead Reference");
} }

View file

@ -42,7 +42,7 @@ template <class TO, class FROM> class Reference : public LinkedListElement
virtual ~Reference() {} virtual ~Reference() {}
// Create new link // Create new link
inline void link(TO* toObj, FROM* fromObj) void link(TO* toObj, FROM* fromObj)
{ {
assert(fromObj); // fromObj MUST not be NULL assert(fromObj); // fromObj MUST not be NULL
if(isValid()) if(isValid())
@ -57,16 +57,16 @@ template <class TO, class FROM> class Reference : public LinkedListElement
// We don't need the reference anymore. Call comes from the refFrom object // We don't need the reference anymore. Call comes from the refFrom object
// Tell our refTo object, that the link is cut // 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 // 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 // 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; sourceObjectDestroyLink(); delink(); iRefTo = NULL;
} }
inline bool isValid() const // Only check the iRefTo bool isValid() const // Only check the iRefTo
{ {
return iRefTo != NULL; return iRefTo != NULL;
} }
@ -81,10 +81,10 @@ template <class TO, class FROM> class Reference : public LinkedListElement
Reference<TO,FROM> * nocheck_prev() { return((Reference<TO,FROM> *) LinkedListElement::nocheck_prev()); } Reference<TO,FROM> * nocheck_prev() { return((Reference<TO,FROM> *) LinkedListElement::nocheck_prev()); }
Reference<TO,FROM> const * nocheck_prev() const { return((Reference<TO,FROM> const *) LinkedListElement::nocheck_prev()); } Reference<TO,FROM> const * nocheck_prev() const { return((Reference<TO,FROM> const *) LinkedListElement::nocheck_prev()); }
inline TO* operator ->() const { return iRefTo; } TO* operator ->() const { return iRefTo; }
inline TO* getTarget() const { return iRefTo; } TO* getTarget() const { return iRefTo; }
inline FROM* getSource() const { return iRefFrom; } FROM* getSource() const { return iRefFrom; }
}; };
//===================================================== //=====================================================

View file

@ -141,7 +141,8 @@ void AchievementMgr::SaveToDB()
if(!m_criteriaProgress.empty()) if(!m_criteriaProgress.empty())
{ {
/// prepare deleting and insert /// prepare deleting and insert
bool need_execute = false; bool need_execute_del = false;
bool need_execute_ins = false;
std::ostringstream ssdel; std::ostringstream ssdel;
std::ostringstream ssins; std::ostringstream ssins;
for(CriteriaProgressMap::iterator iter = m_criteriaProgress.begin(); iter!=m_criteriaProgress.end(); ++iter) for(CriteriaProgressMap::iterator iter = m_criteriaProgress.begin(); iter!=m_criteriaProgress.end(); ++iter)
@ -149,35 +150,52 @@ void AchievementMgr::SaveToDB()
if(!iter->second.changed) if(!iter->second.changed)
continue; continue;
/// first new/changed record prefix // deleted data (including 0 progress state)
if(!need_execute) {
/// 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 ("; 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_del = true;
need_execute = true;
} }
/// next new/changed record prefix /// next new/changed record prefix
else else
{
ssdel << ", "; ssdel << ", ";
ssins << ", ";
}
// new/changed record data // new/changed record data
ssdel << iter->first; ssdel << iter->first;
ssins << "(" << GetPlayer()->GetGUIDLow() << ", " << iter->first << ", " << iter->second.counter << ", " << iter->second.date << ")"; }
/// mark as saved in db // 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 << ", ";
// new/changed record data
ssins << "(" << GetPlayer()->GetGUIDLow() << ", " << iter->first << ", " << iter->second.counter << ", " << iter->second.date << ")";
}
/// mark as updated in db
iter->second.changed = false; iter->second.changed = false;
} }
if(need_execute) if(need_execute_del) // DELETE ... IN (.... _)_
ssdel << ")"; ssdel << ")";
if(need_execute) if(need_execute_del || need_execute_ins)
{ {
CharacterDatabase.BeginTransaction (); CharacterDatabase.BeginTransaction ();
if(need_execute_del)
CharacterDatabase.Execute( ssdel.str().c_str() ); CharacterDatabase.Execute( ssdel.str().c_str() );
if(need_execute_ins)
CharacterDatabase.Execute( ssins.str().c_str() ); CharacterDatabase.Execute( ssins.str().c_str() );
CharacterDatabase.CommitTransaction (); CharacterDatabase.CommitTransaction ();
} }
@ -386,6 +404,10 @@ void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, ui
if(GetPlayer()->HasSpell(achievementCriteria->learn_spell.spellID)) if(GetPlayer()->HasSpell(achievementCriteria->learn_spell.spellID))
SetCriteriaProgress(achievementCriteria, 1); SetCriteriaProgress(achievementCriteria, 1);
break; 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: case ACHIEVEMENT_CRITERIA_TYPE_DEATH_AT_MAP:
// AchievementMgr::UpdateAchievementCriteria might also be called on login - skip in this case // AchievementMgr::UpdateAchievementCriteria might also be called on login - skip in this case
if(!miscvalue1) if(!miscvalue1)
@ -628,7 +650,7 @@ bool AchievementMgr::IsCompletedCriteria(AchievementCriteriaEntry const* achieve
case ACHIEVEMENT_CRITERIA_TYPE_KILL_CREATURE: case ACHIEVEMENT_CRITERIA_TYPE_KILL_CREATURE:
return progress->counter >= achievementCriteria->kill_creature.creatureCount; return progress->counter >= achievementCriteria->kill_creature.creatureCount;
case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_ACHIEVEMENT: 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: case ACHIEVEMENT_CRITERIA_TYPE_REACH_SKILL_LEVEL:
return progress->counter >= achievementCriteria->reach_skill_level.skillLevel; return progress->counter >= achievementCriteria->reach_skill_level.skillLevel;
case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_QUEST_COUNT: case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_QUEST_COUNT:
@ -729,6 +751,10 @@ void AchievementMgr::SetCriteriaProgress(AchievementCriteriaEntry const* entry,
if(iter == m_criteriaProgress.end()) if(iter == m_criteriaProgress.end())
{ {
// not create record for 0 counter
if(newValue == 0)
return;
progress = &m_criteriaProgress[entry->ID]; progress = &m_criteriaProgress[entry->ID];
progress->counter = newValue; progress->counter = newValue;
progress->date = time(NULL); progress->date = time(NULL);
@ -738,8 +764,11 @@ void AchievementMgr::SetCriteriaProgress(AchievementCriteriaEntry const* entry,
progress = &iter->second; progress = &iter->second;
if(relative) if(relative)
newValue += progress->counter; newValue += progress->counter;
// not update (not mark as changed) if counter will have same value
if(progress->counter == newValue) if(progress->counter == newValue)
return; return;
progress->counter = newValue; progress->counter = newValue;
} }

View file

@ -82,20 +82,12 @@ class AuctionHouseObject
AuctionEntry* GetAuction(uint32 id) const AuctionEntry* GetAuction(uint32 id) const
{ {
AuctionEntryMap::const_iterator itr = AuctionsMap.find( id ); AuctionEntryMap::const_iterator itr = AuctionsMap.find( id );
if( itr != AuctionsMap.end() ) return itr != AuctionsMap.end() ? itr->second : NULL;
return itr->second;
return NULL;
} }
bool RemoveAuction(uint32 id) bool RemoveAuction(uint32 id)
{ {
AuctionEntryMap::iterator i = AuctionsMap.find(id); return AuctionsMap.erase(id) ? true : false;
if (i == AuctionsMap.end())
{
return false;
}
AuctionsMap.erase(i);
return true;
} }
private: private:

View file

@ -116,7 +116,7 @@ BattleGround::~BattleGround()
this->RemoveFromBGFreeSlotQueue(); this->RemoveFromBGFreeSlotQueue();
} }
void BattleGround::Update(time_t diff) void BattleGround::Update(uint32 diff)
{ {
if(!GetPlayersSize() && !GetRemovedPlayersSize() && !GetReviveQueueSize()) if(!GetPlayersSize() && !GetRemovedPlayersSize() && !GetReviveQueueSize())
//BG is empty //BG is empty
@ -552,7 +552,7 @@ void BattleGround::EndBattleGround(uint32 winner)
sBattleGroundMgr.BuildPvpLogDataPacket(&data, this); sBattleGroundMgr.BuildPvpLogDataPacket(&data, this);
plr->GetSession()->SendPacket(&data); 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()); sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, this, plr->GetTeam(), plr->GetBattleGroundQueueIndex(bgQueueTypeId), STATUS_IN_PROGRESS, TIME_TO_AUTOREMOVE, GetStartTime());
plr->GetSession()->SendPacket(&data); plr->GetSession()->SendPacket(&data);
plr->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_BATTLEGROUND, 1); plr->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_BATTLEGROUND, 1);
@ -573,7 +573,7 @@ void BattleGround::EndBattleGround(uint32 winner)
} }
// inform invited players about the removal // 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) if(Source)
{ {
@ -769,7 +769,7 @@ void BattleGround::RemovePlayerAtLeave(uint64 guid, bool Transport, bool SendPac
if(!team) team = plr->GetTeam(); if(!team) team = plr->GetTeam();
uint32 bgTypeId = GetTypeID(); uint32 bgTypeId = GetTypeID();
uint32 bgQueueTypeId = sBattleGroundMgr.BGQueueTypeId(GetTypeID(), GetArenaType()); uint32 bgQueueTypeId = BattleGroundMgr::BGQueueTypeId(GetTypeID(), GetArenaType());
// if arena, remove the specific arena auras // if arena, remove the specific arena auras
if(isArena()) if(isArena())
{ {
@ -1403,7 +1403,7 @@ void BattleGround::EndNow()
SetStatus(STATUS_WAIT_LEAVE); SetStatus(STATUS_WAIT_LEAVE);
SetEndTime(TIME_TO_AUTOREMOVE); SetEndTime(TIME_TO_AUTOREMOVE);
// inform invited players about the removal // 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 // Battleground messages are localized using the dbc lang, they are not client language dependent

View file

@ -254,7 +254,7 @@ class BattleGround
BattleGround(); BattleGround();
/*BattleGround(const BattleGround& bg);*/ /*BattleGround(const BattleGround& bg);*/
virtual ~BattleGround(); 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 virtual bool SetupBattleGround() // must be implemented in BG subclass
{ {
return true; return true;

View file

@ -30,7 +30,7 @@ BattleGroundAA::~BattleGroundAA()
} }
void BattleGroundAA::Update(time_t diff) void BattleGroundAA::Update(uint32 diff)
{ {
BattleGround::Update(diff); BattleGround::Update(diff);
} }

View file

@ -35,7 +35,7 @@ class BattleGroundAA : public BattleGround
public: public:
BattleGroundAA(); BattleGroundAA();
~BattleGroundAA(); ~BattleGroundAA();
void Update(time_t diff); void Update(uint32 diff);
/* inherited from BattlegroundClass */ /* inherited from BattlegroundClass */
virtual void AddPlayer(Player *plr); virtual void AddPlayer(Player *plr);

View file

@ -38,7 +38,7 @@ BattleGroundAB::~BattleGroundAB()
{ {
} }
void BattleGroundAB::Update(time_t diff) void BattleGroundAB::Update(uint32 diff)
{ {
BattleGround::Update(diff); BattleGround::Update(diff);

View file

@ -236,7 +236,7 @@ class BattleGroundAB : public BattleGround
BattleGroundAB(); BattleGroundAB();
~BattleGroundAB(); ~BattleGroundAB();
void Update(time_t diff); void Update(uint32 diff);
void AddPlayer(Player *plr); void AddPlayer(Player *plr);
void RemovePlayer(Player *plr,uint64 guid); void RemovePlayer(Player *plr,uint64 guid);
void HandleAreaTrigger(Player *Source, uint32 Trigger); void HandleAreaTrigger(Player *Source, uint32 Trigger);

View file

@ -34,7 +34,7 @@ BattleGroundAV::~BattleGroundAV()
} }
void BattleGroundAV::Update(time_t diff) void BattleGroundAV::Update(uint32 diff)
{ {
BattleGround::Update(diff); BattleGround::Update(diff);
} }

View file

@ -42,7 +42,7 @@ class BattleGroundAV : public BattleGround
public: public:
BattleGroundAV(); BattleGroundAV();
~BattleGroundAV(); ~BattleGroundAV();
void Update(time_t diff); void Update(uint32 diff);
/* inherited from BattlegroundClass */ /* inherited from BattlegroundClass */
virtual void AddPlayer(Player *plr); virtual void AddPlayer(Player *plr);

View file

@ -35,7 +35,7 @@ BattleGroundBE::~BattleGroundBE()
} }
void BattleGroundBE::Update(time_t diff) void BattleGroundBE::Update(uint32 diff)
{ {
BattleGround::Update(diff); BattleGround::Update(diff);

View file

@ -55,7 +55,7 @@ class BattleGroundBE : public BattleGround
public: public:
BattleGroundBE(); BattleGroundBE();
~BattleGroundBE(); ~BattleGroundBE();
void Update(time_t diff); void Update(uint32 diff);
/* inherited from BattlegroundClass */ /* inherited from BattlegroundClass */
virtual void AddPlayer(Player *plr); virtual void AddPlayer(Player *plr);

View file

@ -30,7 +30,7 @@ BattleGroundDS::~BattleGroundDS()
} }
void BattleGroundDS::Update(time_t diff) void BattleGroundDS::Update(uint32 diff)
{ {
BattleGround::Update(diff); BattleGround::Update(diff);
} }

View file

@ -35,7 +35,7 @@ class BattleGroundDS : public BattleGround
public: public:
BattleGroundDS(); BattleGroundDS();
~BattleGroundDS(); ~BattleGroundDS();
void Update(time_t diff); void Update(uint32 diff);
/* inherited from BattlegroundClass */ /* inherited from BattlegroundClass */
virtual void AddPlayer(Player *plr); virtual void AddPlayer(Player *plr);

View file

@ -42,7 +42,7 @@ BattleGroundEY::~BattleGroundEY()
{ {
} }
void BattleGroundEY::Update(time_t diff) void BattleGroundEY::Update(uint32 diff)
{ {
BattleGround::Update(diff); BattleGround::Update(diff);
// after bg start we get there (once) // after bg start we get there (once)

View file

@ -298,7 +298,7 @@ class BattleGroundEY : public BattleGround
public: public:
BattleGroundEY(); BattleGroundEY();
~BattleGroundEY(); ~BattleGroundEY();
void Update(time_t diff); void Update(uint32 diff);
/* inherited from BattlegroundClass */ /* inherited from BattlegroundClass */
virtual void AddPlayer(Player *plr); virtual void AddPlayer(Player *plr);

View file

@ -94,7 +94,7 @@ void WorldSession::HandleBattleGroundJoinOpcode( WorldPacket & recv_data )
sLog.outDebug( "WORLD: Recvd CMSG_BATTLEMASTER_JOIN Message from: " I64FMT, guid); sLog.outDebug( "WORLD: Recvd CMSG_BATTLEMASTER_JOIN Message from: " I64FMT, guid);
// can do this, since it's battleground, not arena // 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 // ignore if player is already in BG
if(_player->InBattleGround()) if(_player->InBattleGround())
@ -368,7 +368,7 @@ void WorldSession::HandleBattleGroundPlayerPortOpcode( WorldPacket &recv_data )
uint32 bgQueueTypeId = 0; uint32 bgQueueTypeId = 0;
// get the bg what we were invited to // get the bg what we were invited to
BattleGroundQueue::QueuedPlayersMap::iterator itrPlayerStatus; 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()); itrPlayerStatus = sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].m_QueuedPlayers[_player->GetBattleGroundQueueIdFromLevel()].find(_player->GetGUID());
if(itrPlayerStatus == sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].m_QueuedPlayers[_player->GetBattleGroundQueueIdFromLevel()].end()) 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(); BattleGround *bg = _player->GetBattleGround();
if(bg) if(bg)
{ {
uint32 bgQueueTypeId = sBattleGroundMgr.BGQueueTypeId(bg->GetTypeID(), bg->GetArenaType()); uint32 bgQueueTypeId = BattleGroundMgr::BGQueueTypeId(bg->GetTypeID(), bg->GetArenaType());
uint32 queueSlot = _player->GetBattleGroundQueueIndex(bgQueueTypeId); uint32 queueSlot = _player->GetBattleGroundQueueIndex(bgQueueTypeId);
if((bg->GetStatus() <= STATUS_IN_PROGRESS)) 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++) 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 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; uint8 isRated = 0;
if (i == queueSlot || !queue_id) // we need to get the instance ids if (i == queueSlot || !queue_id) // we need to get the instance ids
continue; continue;
@ -551,7 +551,7 @@ void WorldSession::HandleBattlefieldStatusOpcode( WorldPacket & /*recv_data*/ )
arenatype = itrPlayerStatus->second.GroupInfo->ArenaType; arenatype = itrPlayerStatus->second.GroupInfo->ArenaType;
isRated = itrPlayerStatus->second.GroupInfo->IsRated; 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) if(bg2)
{ {
//in this call is small bug, this call should be filled by player's waiting time in queue //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); uint32 queue_id = _player->GetBattleGroundQueueId(i);
if(!queue_id) if(!queue_id)
continue; continue;
uint32 bgTypeId = sBattleGroundMgr.BGTemplateId(queue_id); uint32 bgTypeId = BattleGroundMgr::BGTemplateId(queue_id);
uint8 arenatype = sBattleGroundMgr.BGArenaType(queue_id); uint8 arenatype = BattleGroundMgr::BGArenaType(queue_id);
uint8 isRated = 0; uint8 isRated = 0;
BattleGround *bg = sBattleGroundMgr.GetBattleGroundTemplate(bgTypeId); BattleGround *bg = sBattleGroundMgr.GetBattleGroundTemplate(bgTypeId);
BattleGroundQueue::QueuedPlayersMap::iterator itrPlayerStatus = sBattleGroundMgr.m_BattleGroundQueues[queue_id].m_QueuedPlayers[_player->GetBattleGroundQueueIdFromLevel()].find(_player->GetGUID()); 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(); uint8 bgTypeId = bg->GetTypeID();
uint32 bgQueueTypeId = sBattleGroundMgr.BGQueueTypeId(bgTypeId, arenatype); uint32 bgQueueTypeId = BattleGroundMgr::BGQueueTypeId(bgTypeId, arenatype);
// check queueing conditions // check queueing conditions
if(!asGroup) if(!asGroup)

View file

@ -37,7 +37,6 @@
#include "MapInstanced.h" #include "MapInstanced.h"
#include "ObjectMgr.h" #include "ObjectMgr.h"
#include "ProgressBar.h" #include "ProgressBar.h"
#include "World.h"
#include "Chat.h" #include "Chat.h"
#include "ArenaTeam.h" #include "ArenaTeam.h"
@ -246,7 +245,7 @@ void BattleGroundQueue::AddPlayer(Player *plr, GroupQueueInfo *ginfo)
ginfo->Players[plr->GetGUID()] = &info; 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); 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)) if(Player *plr2 = objmgr.GetPlayer(group->Players.begin()->first))
{ {
BattleGround * bg = sBattleGroundMgr.GetBattleGroundTemplate(group->BgTypeId); 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); 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 plr2->RemoveBattleGroundQueueId(bgQueueTypeId); // must be called this way, because if you move this call to queue->removeplayer, it causes bugs
WorldPacket data; 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 if(ginfo->ArenaType) //if Arena
@ -452,7 +451,7 @@ bool BattleGroundQueue::InviteGroupToBG(GroupQueueInfo * ginfo, BattleGround * b
// not yet invited // not yet invited
// set invitation // set invitation
ginfo->IsInvitedToBGInstanceGUID = bg->GetInstanceID(); ginfo->IsInvitedToBGInstanceGUID = bg->GetInstanceID();
uint32 bgQueueTypeId = sBattleGroundMgr.BGQueueTypeId(bg->GetTypeID(), bg->GetArenaType()); uint32 bgQueueTypeId = BattleGroundMgr::BGQueueTypeId(bg->GetTypeID(), bg->GetArenaType());
// loop through the players // loop through the players
for(std::map<uint64,PlayerQueueInfo*>::iterator itr = ginfo->Players.begin(); itr != ginfo->Players.end(); ++itr) for(std::map<uint64,PlayerQueueInfo*>::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 queue_id = bg->GetQueueType();
uint32 bgInstanceId = bg->GetInstanceID(); uint32 bgInstanceId = bg->GetInstanceID();
uint32 bgQueueTypeId = sBattleGroundMgr.BGQueueTypeId(bg->GetTypeID(), bg->GetArenaType()); uint32 bgQueueTypeId = BattleGroundMgr::BGQueueTypeId(bg->GetTypeID(), bg->GetArenaType());
QueuedGroupsList::iterator itr, next; QueuedGroupsList::iterator itr, next;
for(itr = m_QueuedGroups[queue_id].begin(); itr != m_QueuedGroups[queue_id].end(); 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()) if (m_QueuedGroups[queue_id].empty())
return; 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 //battleground with free slot for player should be always the last in this queue
BGFreeSlotQueueType::iterator itr, next; BGFreeSlotQueueType::iterator itr, next;
@ -995,7 +994,7 @@ bool BGQueueInviteEvent::Execute(uint64 /*e_time*/, uint32 /*p_time*/)
uint32 queueSlot = plr->GetBattleGroundQueueIndex(bg->GetTypeID()); uint32 queueSlot = plr->GetBattleGroundQueueIndex(bg->GetTypeID());
if (queueSlot < PLAYER_MAX_BATTLEGROUND_QUEUES) // player is in queue 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); uint32 queueSlot = plr->GetBattleGroundQueueIndex(bgQueueTypeId);
if (queueSlot < PLAYER_MAX_BATTLEGROUND_QUEUES) // player is in queue 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); 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); uint32 queueSlot = plr->GetBattleGroundQueueIndex(bgQueueTypeId);
if (queueSlot < PLAYER_MAX_BATTLEGROUND_QUEUES) // player is in queue if (queueSlot < PLAYER_MAX_BATTLEGROUND_QUEUES) // player is in queue
{ {
@ -1075,16 +1074,10 @@ void BGQueueRemoveEvent::Abort(uint64 /*e_time*/)
/*** BATTLEGROUND MANAGER ***/ /*** BATTLEGROUND MANAGER ***/
/*********************************************************/ /*********************************************************/
BattleGroundMgr::BattleGroundMgr() BattleGroundMgr::BattleGroundMgr() : m_AutoDistributionTimeChecker(0), m_ArenaTesting(false)
{ {
m_BattleGrounds.clear(); m_BattleGrounds.clear();
m_AutoDistributePoints = (bool)sWorld.getConfig(CONFIG_ARENA_AUTO_DISTRIBUTE_POINTS); m_NextRatingDiscardUpdate = sWorld.getConfig(CONFIG_ARENA_RATING_DISCARD_TIMER);
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;
} }
BattleGroundMgr::~BattleGroundMgr() BattleGroundMgr::~BattleGroundMgr()
@ -1102,7 +1095,7 @@ BattleGroundMgr::~BattleGroundMgr()
} }
// used to update running battlegrounds, and delete finished ones // used to update running battlegrounds, and delete finished ones
void BattleGroundMgr::Update(time_t diff) void BattleGroundMgr::Update(uint32 diff)
{ {
BattleGroundSet::iterator itr, next; BattleGroundSet::iterator itr, next;
for(itr = m_BattleGrounds.begin(); itr != m_BattleGrounds.end(); 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 rating difference counts, maybe force-update queues
if(m_MaxRatingDifference) if(sWorld.getConfig(CONFIG_ARENA_MAX_RATING_DIFFERENCE))
{ {
// it's time to force update // it's time to force update
if(m_NextRatingDiscardUpdate < diff) 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_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_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_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 else
m_NextRatingDiscardUpdate -= diff; m_NextRatingDiscardUpdate -= diff;
} }
if(m_AutoDistributePoints) if(sWorld.getConfig(CONFIG_ARENA_AUTO_DISTRIBUTE_POINTS))
{ {
if(m_AutoDistributionTimeChecker < diff) if(m_AutoDistributionTimeChecker < diff)
{ {
@ -1692,7 +1685,7 @@ void BattleGroundMgr::CreateInitialBattleGrounds()
void BattleGroundMgr::InitAutomaticArenaPointDistribution() void BattleGroundMgr::InitAutomaticArenaPointDistribution()
{ {
if(m_AutoDistributePoints) if(sWorld.getConfig(CONFIG_ARENA_AUTO_DISTRIBUTE_POINTS))
{ {
sLog.outDebug("Initializing Automatic Arena Point Distribution"); sLog.outDebug("Initializing Automatic Arena Point Distribution");
QueryResult * result = CharacterDatabase.Query("SELECT NextArenaPointDistributionTime FROM saved_variables"); QueryResult * result = CharacterDatabase.Query("SELECT NextArenaPointDistributionTime FROM saved_variables");
@ -1761,7 +1754,7 @@ void BattleGroundMgr::DistributeArenaPoints()
sWorld.SendGlobalText("Done flushing Arena points.", NULL); 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; 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); WorldPacket data(SMSG_AREA_SPIRIT_HEALER_TIME, 12);
uint32 time_ = 30000 - bg->GetLastResurrectTime(); // resurrect every 30 seconds uint32 time_ = 30000 - bg->GetLastResurrectTime(); // resurrect every 30 seconds
@ -1827,14 +1820,7 @@ void BattleGroundMgr::SendAreaSpiritHealerQueryOpcode(Player *pl, BattleGround *
pl->GetSession()->SendPacket(&data); pl->GetSession()->SendPacket(&data);
} }
void BattleGroundMgr::RemoveBattleGround(uint32 instanceID) bool BattleGroundMgr::IsArenaType(uint32 bgTypeId)
{
BattleGroundSet::iterator itr = m_BattleGrounds.find(instanceID);
if(itr!=m_BattleGrounds.end())
m_BattleGrounds.erase(itr);
}
bool BattleGroundMgr::IsArenaType(uint32 bgTypeId) const
{ {
return ( bgTypeId == BATTLEGROUND_AA || return ( bgTypeId == BATTLEGROUND_AA ||
bgTypeId == BATTLEGROUND_BE || bgTypeId == BATTLEGROUND_BE ||
@ -1842,12 +1828,7 @@ bool BattleGroundMgr::IsArenaType(uint32 bgTypeId) const
bgTypeId == BATTLEGROUND_RL ); bgTypeId == BATTLEGROUND_RL );
} }
bool BattleGroundMgr::IsBattleGroundType(uint32 bgTypeId) const uint32 BattleGroundMgr::BGQueueTypeId(uint32 bgTypeId, uint8 arenaType)
{
return !IsArenaType(bgTypeId);
}
uint32 BattleGroundMgr::BGQueueTypeId(uint32 bgTypeId, uint8 arenaType) const
{ {
switch(bgTypeId) switch(bgTypeId)
{ {
@ -1883,7 +1864,7 @@ uint32 BattleGroundMgr::BGQueueTypeId(uint32 bgTypeId, uint8 arenaType) const
} }
} }
uint32 BattleGroundMgr::BGTemplateId(uint32 bgQueueTypeId) const uint32 BattleGroundMgr::BGTemplateId(uint32 bgQueueTypeId)
{ {
switch(bgQueueTypeId) switch(bgQueueTypeId)
{ {
@ -1906,7 +1887,7 @@ uint32 BattleGroundMgr::BGTemplateId(uint32 bgQueueTypeId) const
} }
} }
uint8 BattleGroundMgr::BGArenaType(uint32 bgQueueTypeId) const uint8 BattleGroundMgr::BGArenaType(uint32 bgQueueTypeId)
{ {
switch(bgQueueTypeId) switch(bgQueueTypeId)
{ {

View file

@ -20,7 +20,7 @@
#define __BATTLEGROUNDMGR_H #define __BATTLEGROUNDMGR_H
#include "BattleGround.h" #include "BattleGround.h"
#include "Policies/Singleton.h" #include "World.h"
class BattleGround; class BattleGround;
@ -72,10 +72,10 @@ class BattleGroundQueue
GroupQueueInfo * AddGroup(Player * leader, uint32 BgTypeId, uint8 ArenaType, bool isRated, uint32 ArenaRating, uint32 ArenaTeamId = 0); GroupQueueInfo * AddGroup(Player * leader, uint32 BgTypeId, uint8 ArenaType, bool isRated, uint32 ArenaRating, uint32 ArenaTeamId = 0);
void AddPlayer(Player *plr, GroupQueueInfo *ginfo); 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 DecreaseGroupLength(uint32 queueId, uint32 AsGroup);
void BGEndedRemoveInvites(BattleGround * bg); void BGEndedRemoveInvites(BattleGround * bg);
void AnnounceWorld(GroupQueueInfo *ginfo, uint64 playerGUID, bool isAddedToQueue); void AnnounceWorld(GroupQueueInfo *ginfo, const uint64& playerGUID, bool isAddedToQueue);
typedef std::map<uint64, PlayerQueueInfo> QueuedPlayersMap; typedef std::map<uint64, PlayerQueueInfo> QueuedPlayersMap;
QueuedPlayersMap m_QueuedPlayers[MAX_BATTLEGROUND_QUEUES]; QueuedPlayersMap m_QueuedPlayers[MAX_BATTLEGROUND_QUEUES];
@ -137,7 +137,7 @@ class BattleGroundQueue
class BGQueueInviteEvent : public BasicEvent class BGQueueInviteEvent : public BasicEvent
{ {
public: 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 ~BGQueueInviteEvent() {};
virtual bool Execute(uint64 e_time, uint32 p_time); virtual bool Execute(uint64 e_time, uint32 p_time);
@ -153,7 +153,10 @@ class BGQueueInviteEvent : public BasicEvent
class BGQueueRemoveEvent : public BasicEvent class BGQueueRemoveEvent : public BasicEvent
{ {
public: 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 ~BGQueueRemoveEvent() {};
virtual bool Execute(uint64 e_time, uint32 p_time); virtual bool Execute(uint64 e_time, uint32 p_time);
@ -170,18 +173,19 @@ class BattleGroundMgr
/* Construction */ /* Construction */
BattleGroundMgr(); BattleGroundMgr();
~BattleGroundMgr(); ~BattleGroundMgr();
void Update(time_t diff); void Update(uint32 diff);
/* Packet Building */ /* Packet Building */
void BuildPlayerJoinedBattleGroundPacket(WorldPacket *data, Player *plr); void BuildPlayerJoinedBattleGroundPacket(WorldPacket *data, Player *plr);
void BuildPlayerLeftBattleGroundPacket(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 BuildGroupJoinedBattlegroundPacket(WorldPacket *data, uint32 bgTypeId);
void BuildUpdateWorldStatePacket(WorldPacket *data, uint32 field, uint32 value); void BuildUpdateWorldStatePacket(WorldPacket *data, uint32 field, uint32 value);
void BuildPvpLogDataPacket(WorldPacket *data, BattleGround *bg); void BuildPvpLogDataPacket(WorldPacket *data, BattleGround *bg);
void BuildBattleGroundStatusPacket(WorldPacket *data, BattleGround *bg, uint32 team, uint8 QueueSlot, uint8 StatusID, uint32 Time1, uint32 Time2, uint32 arenatype = 0, uint8 israted = 0); 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 BuildPlaySoundPacket(WorldPacket *data, uint32 soundid);
void SendAreaSpiritHealerQueryOpcode(Player *pl, BattleGround *bg, const uint64& guid);
/* Player invitation */ /* Player invitation */
// called from Queue update, or from Addplayer to queue // called from Queue update, or from Addplayer to queue
void InvitePlayer(Player* plr, uint32 bgInstanceGUID, uint32 team); void InvitePlayer(Player* plr, uint32 bgInstanceGUID, uint32 team);
@ -193,10 +197,7 @@ class BattleGroundMgr
BattleGround* GetBattleGround(uint32 ID) BattleGround* GetBattleGround(uint32 ID)
{ {
BattleGroundSet::iterator i = m_BattleGrounds.find(ID); BattleGroundSet::iterator i = m_BattleGrounds.find(ID);
if(i != m_BattleGrounds.end()) return ( (i != m_BattleGrounds.end()) ? i->second : NULL );
return i->second;
else
return NULL;
}; };
BattleGround * GetBattleGroundTemplate(uint32 bgTypeId); 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); 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 AddBattleGround(uint32 ID, BattleGround* BG) { m_BattleGrounds[ID] = BG; };
void RemoveBattleGround(uint32 instanceID); void RemoveBattleGround(uint32 instanceID) { m_BattleGrounds.erase(instanceID); }
void CreateInitialBattleGrounds(); void CreateInitialBattleGrounds();
@ -217,34 +218,28 @@ class BattleGroundMgr
BGFreeSlotQueueType BGFreeSlotQueue[MAX_BATTLEGROUND_TYPES]; BGFreeSlotQueueType BGFreeSlotQueue[MAX_BATTLEGROUND_TYPES];
void SendAreaSpiritHealerQueryOpcode(Player *pl, BattleGround *bg, uint64 guid); uint32 GetMaxRatingDifference() const { return sWorld.getConfig(CONFIG_ARENA_MAX_RATING_DIFFERENCE); }
uint32 GetRatingDiscardTimer() const { return sWorld.getConfig(CONFIG_ARENA_RATING_DISCARD_TIMER); }
bool IsArenaType(uint32 bgTypeId) const; uint32 GetPrematureFinishTime() const { return sWorld.getConfig(CONFIG_BATTLEGROUND_PREMATURE_FINISH_TIMER); }
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;}
void InitAutomaticArenaPointDistribution(); void InitAutomaticArenaPointDistribution();
void DistributeArenaPoints(); void DistributeArenaPoints();
uint32 GetPrematureFinishTime() const {return m_PrematureFinishTimer;}
void ToggleArenaTesting(); 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: private:
/* Battlegrounds */ /* Battlegrounds */
BattleGroundSet m_BattleGrounds; BattleGroundSet m_BattleGrounds;
uint32 m_MaxRatingDifference;
uint32 m_RatingDiscardTimer;
uint32 m_NextRatingDiscardUpdate; uint32 m_NextRatingDiscardUpdate;
bool m_AutoDistributePoints;
uint64 m_NextAutoDistributionTime; uint64 m_NextAutoDistributionTime;
uint32 m_AutoDistributionTimeChecker; uint32 m_AutoDistributionTimeChecker;
uint32 m_PrematureFinishTimer;
bool m_ArenaTesting; bool m_ArenaTesting;
}; };

View file

@ -35,7 +35,7 @@ BattleGroundNA::~BattleGroundNA()
} }
void BattleGroundNA::Update(time_t diff) void BattleGroundNA::Update(uint32 diff)
{ {
BattleGround::Update(diff); BattleGround::Update(diff);

View file

@ -56,7 +56,7 @@ class BattleGroundNA : public BattleGround
public: public:
BattleGroundNA(); BattleGroundNA();
~BattleGroundNA(); ~BattleGroundNA();
void Update(time_t diff); void Update(uint32 diff);
/* inherited from BattlegroundClass */ /* inherited from BattlegroundClass */
virtual void AddPlayer(Player *plr); virtual void AddPlayer(Player *plr);

View file

@ -35,7 +35,7 @@ BattleGroundRL::~BattleGroundRL()
} }
void BattleGroundRL::Update(time_t diff) void BattleGroundRL::Update(uint32 diff)
{ {
BattleGround::Update(diff); BattleGround::Update(diff);

View file

@ -52,7 +52,7 @@ class BattleGroundRL : public BattleGround
public: public:
BattleGroundRL(); BattleGroundRL();
~BattleGroundRL(); ~BattleGroundRL();
void Update(time_t diff); void Update(uint32 diff);
/* inherited from BattlegroundClass */ /* inherited from BattlegroundClass */
virtual void AddPlayer(Player *plr); virtual void AddPlayer(Player *plr);

View file

@ -30,7 +30,7 @@ BattleGroundRV::~BattleGroundRV()
} }
void BattleGroundRV::Update(time_t diff) void BattleGroundRV::Update(uint32 diff)
{ {
BattleGround::Update(diff); BattleGround::Update(diff);
} }

View file

@ -35,7 +35,7 @@ class BattleGroundRV : public BattleGround
public: public:
BattleGroundRV(); BattleGroundRV();
~BattleGroundRV(); ~BattleGroundRV();
void Update(time_t diff); void Update(uint32 diff);
/* inherited from BattlegroundClass */ /* inherited from BattlegroundClass */
virtual void AddPlayer(Player *plr); virtual void AddPlayer(Player *plr);

View file

@ -29,7 +29,7 @@ BattleGroundSA::~BattleGroundSA()
} }
void BattleGroundSA::Update(time_t diff) void BattleGroundSA::Update(uint32 diff)
{ {
BattleGround::Update(diff); BattleGround::Update(diff);
} }

View file

@ -35,7 +35,7 @@ class BattleGroundSA : public BattleGround
public: public:
BattleGroundSA(); BattleGroundSA();
~BattleGroundSA(); ~BattleGroundSA();
void Update(time_t diff); void Update(uint32 diff);
/* inherited from BattlegroundClass */ /* inherited from BattlegroundClass */
virtual void AddPlayer(Player *plr); virtual void AddPlayer(Player *plr);

View file

@ -36,7 +36,7 @@ BattleGroundWS::~BattleGroundWS()
{ {
} }
void BattleGroundWS::Update(time_t diff) void BattleGroundWS::Update(uint32 diff)
{ {
BattleGround::Update(diff); BattleGround::Update(diff);

View file

@ -134,7 +134,7 @@ class BattleGroundWS : public BattleGround
/* Construction */ /* Construction */
BattleGroundWS(); BattleGroundWS();
~BattleGroundWS(); ~BattleGroundWS();
void Update(time_t diff); void Update(uint32 diff);
/* inherited from BattlegroundClass */ /* inherited from BattlegroundClass */
virtual void AddPlayer(Player *plr); virtual void AddPlayer(Player *plr);

View file

@ -91,13 +91,13 @@ struct MANGOS_DLL_DECL Cell
y = data.Part.grid_y*MAX_NUMBER_OF_CELLS + data.Part.cell_y; 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 || return( data.Part.cell_x != cell.data.Part.cell_x ||
data.Part.cell_y != cell.data.Part.cell_y ); 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 || return( data.Part.grid_x != cell.data.Part.grid_x ||
data.Part.grid_y != cell.data.Part.grid_y ); data.Part.grid_y != cell.data.Part.grid_y );

View file

@ -1206,7 +1206,7 @@ void WorldSession::HandleRemoveGlyph( WorldPacket & recv_data )
uint32 slot; uint32 slot;
recv_data >> 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); sLog.outDebug("Client sent wrong glyph slot number in opcode CMSG_REMOVE_GLYPH %u", slot);
return; return;

View file

@ -284,6 +284,7 @@ ChatCommand * ChatHandler::getCommandTable()
{ "spell_chain", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadSpellChainCommand, "", NULL }, { "spell_chain", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadSpellChainCommand, "", NULL },
{ "spell_elixir", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadSpellElixirCommand, "", NULL }, { "spell_elixir", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadSpellElixirCommand, "", NULL },
{ "spell_learn_spell", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadSpellLearnSpellCommand, "", 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_pet_auras", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadSpellPetAurasCommand, "", NULL },
{ "spell_proc_event", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadSpellProcEventCommand, "", NULL }, { "spell_proc_event", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadSpellProcEventCommand, "", NULL },
{ "spell_script_target", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadSpellScriptTargetCommand, "", NULL }, { "spell_script_target", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadSpellScriptTargetCommand, "", NULL },

View file

@ -233,6 +233,7 @@ class ChatHandler
bool HandleReloadLootTemplatesReferenceCommand(const char* args); bool HandleReloadLootTemplatesReferenceCommand(const char* args);
bool HandleReloadLootTemplatesQuestMailCommand(const char* args); bool HandleReloadLootTemplatesQuestMailCommand(const char* args);
bool HandleReloadLootTemplatesSkinningCommand(const char* args); bool HandleReloadLootTemplatesSkinningCommand(const char* args);
bool HandleReloadLootTemplatesSpellCommand(const char* args);
bool HandleReloadMangosStringCommand(const char* args); bool HandleReloadMangosStringCommand(const char* args);
bool HandleReloadNpcGossipCommand(const char* args); bool HandleReloadNpcGossipCommand(const char* args);
bool HandleReloadNpcOptionCommand(const char* args); bool HandleReloadNpcOptionCommand(const char* args);

View file

@ -813,10 +813,8 @@ void Creature::sendPreparedGossip(Player* player)
if(!player) if(!player)
return; return;
GossipMenu& gossipmenu = player->PlayerTalkClass->GetGossipMenu();
// in case empty gossip menu open quest menu if any // 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()); player->SendPreparedQuest(GetGUID());
return; return;
@ -1547,12 +1545,12 @@ bool Creature::IsImmunedToSpell(SpellEntry const* spellInfo)
return Unit::IsImmunedToSpell(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 true;
return Unit::IsImmunedToSpellEffect(effect, mechanic); return Unit::IsImmunedToSpellEffect(spellInfo, index);
} }
SpellEntry const *Creature::reachWithSpellAttack(Unit *pVictim) SpellEntry const *Creature::reachWithSpellAttack(Unit *pVictim)

View file

@ -364,6 +364,10 @@ struct TrainerSpell
uint32 reqskill; uint32 reqskill;
uint32 reqskillvalue; uint32 reqskillvalue;
uint32 reqlevel; uint32 reqlevel;
uint32 learned_spell;
// helpers
bool IsCastable() const { return learned_spell != spell; }
}; };
typedef std::vector<TrainerSpell*> TrainerSpellList; typedef std::vector<TrainerSpell*> TrainerSpellList;
@ -429,7 +433,7 @@ class MANGOS_DLL_SPEC Creature : public Unit
bool IsOutOfThreatArea(Unit* pVictim) const; bool IsOutOfThreatArea(Unit* pVictim) const;
bool IsImmunedToSpell(SpellEntry const* spellInfo); bool IsImmunedToSpell(SpellEntry const* spellInfo);
// redefine Unit::IsImmunedToSpell // redefine Unit::IsImmunedToSpell
bool IsImmunedToSpellEffect(uint32 effect, uint32 mechanic) const; bool IsImmunedToSpellEffect(SpellEntry const* spellInfo, uint32 index) const;
// redefine Unit::IsImmunedToSpellEffect // redefine Unit::IsImmunedToSpellEffect
bool isElite() const bool isElite() const
{ {

View file

@ -78,8 +78,17 @@ namespace MaNGOS
inline uint32 BaseGain(uint32 pl_level, uint32 mob_level, ContentLevels content) inline uint32 BaseGain(uint32 pl_level, uint32 mob_level, ContentLevels content)
{ {
//TODO: need modifier for CONTENT_71_80 different from CONTENT_61_70? uint32 nBaseExp;
const uint32 nBaseExp = content == CONTENT_1_60 ? 45 : 235; 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 ) if( mob_level >= pl_level )
{ {
uint32 nLevelDiff = 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)); 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) inline float xp_in_group_rate(uint32 count, bool isRaid)
{ {
if(isRaid) if(isRaid)

View file

@ -125,7 +125,7 @@ bool PlayerMenu::GossipOptionCoded( unsigned int Selection )
void PlayerMenu::SendGossipMenu( uint32 TitleTextId, uint64 npcGUID ) void PlayerMenu::SendGossipMenu( uint32 TitleTextId, uint64 npcGUID )
{ {
WorldPacket data( SMSG_GOSSIP_MESSAGE, (100) ); // guess size WorldPacket data( SMSG_GOSSIP_MESSAGE, (100) ); // guess size
data << npcGUID; data << uint64(npcGUID);
data << uint32(0); // new 2.4.0 data << uint32(0); // new 2.4.0
data << uint32( TitleTextId ); data << uint32( TitleTextId );
data << uint32( mGossipMenu.MenuItemCount() ); // max count 0x0F data << uint32( mGossipMenu.MenuItemCount() ); // max count 0x0F

View file

@ -41,10 +41,10 @@ class Player;
#define MIN_GRID_DELAY MINUTE*1000 #define MIN_GRID_DELAY MINUTE*1000
#define MIN_MAP_UPDATE_DELAY 50 #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 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 CENTER_GRID_CELL_OFFSET (SIZE_OF_GRID_CELL/2)
#define TOTAL_NUMBER_OF_CELLS_PER_MAP (MAX_NUMBER_OF_GRIDS*MAX_NUMBER_OF_CELLS) #define TOTAL_NUMBER_OF_CELLS_PER_MAP (MAX_NUMBER_OF_GRIDS*MAX_NUMBER_OF_CELLS)

View file

@ -170,7 +170,7 @@ inline void MaNGOS::DynamicObjectUpdater::VisitHelper(Unit* target)
SpellEntry const *spellInfo = sSpellStore.LookupEntry(i_dynobject.GetSpellId()); SpellEntry const *spellInfo = sSpellStore.LookupEntry(i_dynobject.GetSpellId());
uint32 eff_index = i_dynobject.GetEffIndex(); uint32 eff_index = i_dynobject.GetEffIndex();
// Check target immune to spell or aura // 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; return;
// Apply PersistentAreaAura on target // Apply PersistentAreaAura on target
PersistentAreaAura* Aur = new PersistentAreaAura(spellInfo, eff_index, NULL, target, i_dynobject.GetCaster()); PersistentAreaAura* Aur = new PersistentAreaAura(spellInfo, eff_index, NULL, target, i_dynobject.GetCaster());

View file

@ -707,7 +707,7 @@ void WorldSession::BuildPartyMemberStatsChangedPacket(Player *player, WorldPacke
if (mask & GROUP_UPDATE_FLAG_AURAS) if (mask & GROUP_UPDATE_FLAG_AURAS)
{ {
uint64 auramask = player->GetAuraUpdateMask(); const uint64& auramask = player->GetAuraUpdateMask();
*data << uint64(auramask); *data << uint64(auramask);
for(uint32 i = 0; i < MAX_AURAS; ++i) for(uint32 i = 0; i < MAX_AURAS; ++i)
{ {
@ -788,7 +788,7 @@ void WorldSession::BuildPartyMemberStatsChangedPacket(Player *player, WorldPacke
{ {
if(pet) if(pet)
{ {
uint64 auramask = pet->GetAuraUpdateMask(); const uint64& auramask = pet->GetAuraUpdateMask();
*data << uint64(auramask); *data << uint64(auramask);
for(uint32 i = 0; i < MAX_AURAS; ++i) for(uint32 i = 0; i < MAX_AURAS; ++i)
{ {

View file

@ -152,7 +152,7 @@ enum EnchantmentSlot
SOCK_ENCHANTMENT_SLOT_2 = 3, SOCK_ENCHANTMENT_SLOT_2 = 3,
SOCK_ENCHANTMENT_SLOT_3 = 4, SOCK_ENCHANTMENT_SLOT_3 = 4,
BONUS_ENCHANTMENT_SLOT = 5, BONUS_ENCHANTMENT_SLOT = 5,
WOTLK_ENCHANTMENT_SLOT = 6, PRISMATIC_ENCHANTMENT_SLOT = 6, // added at apply special permanent enchantment
MAX_INSPECTED_ENCHANTMENT_SLOT = 7, MAX_INSPECTED_ENCHANTMENT_SLOT = 7,
PROP_ENCHANTMENT_SLOT_0 = 7, // used with RandomSuffix PROP_ENCHANTMENT_SLOT_0 = 7, // used with RandomSuffix

View file

@ -322,7 +322,7 @@ void WorldSession::HandleItemQuerySingleOpcode( WorldPacket & recv_data )
data << pProto->ItemId; data << pProto->ItemId;
data << pProto->Class; data << pProto->Class;
data << pProto->SubClass; 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 << Name;
data << uint8(0x00); //pProto->Name2; // blizz not send name there, just uint8(0x00); <-- \0 = empty string = empty 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); 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->PageMaterial;
data << pProto->StartQuest; data << pProto->StartQuest;
data << pProto->LockID; data << pProto->LockID;
data << pProto->Material; data << int32(pProto->Material);
data << pProto->Sheath; data << pProto->Sheath;
data << pProto->RandomProperty; data << pProto->RandomProperty;
data << pProto->RandomSuffix; data << pProto->RandomSuffix;
@ -1112,10 +1112,6 @@ void WorldSession::HandleSocketOpcode(WorldPacket& recv_data)
CHECK_PACKET_SIZE(recv_data,8*4); CHECK_PACKET_SIZE(recv_data,8*4);
uint64 guids[4]; uint64 guids[4];
uint32 GemEnchants[3], OldEnchants[3];
Item *Gems[3];
bool SocketBonusActivated, SocketBonusToBeActivated;
for(int i = 0; i < 4; i++) for(int i = 0; i < 4; i++)
recv_data >> guids[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 //this slot is excepted when applying / removing meta gem bonus
uint8 slot = itemTarget->IsEquipped() ? itemTarget->GetSlot() : NULL_SLOT; uint8 slot = itemTarget->IsEquipped() ? itemTarget->GetSlot() : NULL_SLOT;
Item *Gems[3];
for(int i = 0; i < 3; i++) for(int i = 0; i < 3; i++)
Gems[i] = guids[i + 1] ? _player->GetItemByGuid(guids[i + 1]) : NULL; Gems[i] = guids[i + 1] ? _player->GetItemByGuid(guids[i + 1]) : NULL;
@ -1152,6 +1149,7 @@ void WorldSession::HandleSocketOpcode(WorldPacket& recv_data)
return; return;
} }
uint32 GemEnchants[3], OldEnchants[3];
for(int i = 0; i < 3; ++i) //get new and old enchantments for(int i = 0; i < 3; ++i) //get new and old enchantments
{ {
GemEnchants[i] = (GemProps[i]) ? GemProps[i]->spellitemenchantement : 0; 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) _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 //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) for(uint32 enchant_slot = SOCK_ENCHANTMENT_SLOT; enchant_slot < SOCK_ENCHANTMENT_SLOT+3; ++enchant_slot)
_player->ApplyEnchantment(itemTarget,EnchantmentSlot(enchant_slot),true); _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... if(SocketBonusActivated ^ SocketBonusToBeActivated) //if there was a change...
{ {
_player->ApplyEnchantment(itemTarget,BONUS_ENCHANTMENT_SLOT,false); _player->ApplyEnchantment(itemTarget,BONUS_ENCHANTMENT_SLOT,false);

View file

@ -74,6 +74,12 @@ enum ItemSpelltriggerType
ITEM_SPELLTRIGGER_ON_EQUIP = 1, ITEM_SPELLTRIGGER_ON_EQUIP = 1,
ITEM_SPELLTRIGGER_CHANCE_ON_HIT = 2, ITEM_SPELLTRIGGER_CHANCE_ON_HIT = 2,
ITEM_SPELLTRIGGER_SOULSTONE = 4, 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_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 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 ItemId;
uint32 Class; // id from ItemClass.dbc uint32 Class; // id from ItemClass.dbc
uint32 SubClass; // id from ItemSubClass.dbc uint32 SubClass; // id from ItemSubClass.dbc
uint32 Unk0; int32 Unk0;
char* Name1; char* Name1;
uint32 DisplayInfoID; // id from ItemDisplayInfo.dbc uint32 DisplayInfoID; // id from ItemDisplayInfo.dbc
uint32 Quality; uint32 Quality;
@ -535,7 +541,7 @@ struct ItemPrototype
uint32 PageMaterial; uint32 PageMaterial;
uint32 StartQuest; // id from QuestCache.wdb uint32 StartQuest; // id from QuestCache.wdb
uint32 LockID; uint32 LockID;
uint32 Material; // id from Material.dbc int32 Material; // id from Material.dbc
uint32 Sheath; uint32 Sheath;
uint32 RandomProperty; // id from ItemRandomProperties.dbc uint32 RandomProperty; // id from ItemRandomProperties.dbc
uint32 RandomSuffix; // id from ItemRandomSuffix.dbc uint32 RandomSuffix; // id from ItemRandomSuffix.dbc

View file

@ -723,7 +723,8 @@ enum MangosStrings
LANG_MUST_MALE_OR_FEMALE = 1119, LANG_MUST_MALE_OR_FEMALE = 1119,
LANG_YOU_CHANGE_GENDER = 1120, LANG_YOU_CHANGE_GENDER = 1120,
LANG_YOUR_GENDER_CHANGED = 1121, 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 // FREE IDS 1200-9999

View file

@ -1677,14 +1677,14 @@ bool ChatHandler::HandleModifyMoneyCommand(const char* args)
return true; return true;
} }
//Edit Player field //Edit Unit field
bool ChatHandler::HandleModifyBitCommand(const char* args) bool ChatHandler::HandleModifyBitCommand(const char* args)
{ {
if( !*args ) if( !*args )
return false; return false;
Player *chr = getSelectedPlayer(); Unit *unit = getSelectedUnit();
if (chr == NULL) if (!unit)
{ {
SendSysMessage(LANG_NO_CHAR_SELECTED); SendSysMessage(LANG_NO_CHAR_SELECTED);
SetSentErrorMessage(true); SetSentErrorMessage(true);
@ -1692,7 +1692,7 @@ bool ChatHandler::HandleModifyBitCommand(const char* args)
} }
// check online security // check online security
if (HasLowerSecurity(chr, 0)) if (unit->GetTypeId() == TYPEID_PLAYER && HasLowerSecurity((Player *)unit, 0))
return false; return false;
char* pField = strtok((char*)args, " "); char* pField = strtok((char*)args, " ");
@ -1706,13 +1706,12 @@ bool ChatHandler::HandleModifyBitCommand(const char* args)
uint16 field = atoi(pField); uint16 field = atoi(pField);
uint32 bit = atoi(pBit); uint32 bit = atoi(pBit);
if (field < 1 || field >= PLAYER_END) if (field < OBJECT_END || field >= unit->GetValuesCount())
{ {
SendSysMessage(LANG_BAD_VALUE); SendSysMessage(LANG_BAD_VALUE);
SetSentErrorMessage(true); SetSentErrorMessage(true);
return false; return false;
} }
if (bit < 1 || bit > 32) if (bit < 1 || bit > 32)
{ {
SendSysMessage(LANG_BAD_VALUE); SendSysMessage(LANG_BAD_VALUE);
@ -1720,17 +1719,16 @@ bool ChatHandler::HandleModifyBitCommand(const char* args)
return false; 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); PSendSysMessage(LANG_REMOVE_BIT, bit, field);
} }
else else
{ {
chr->SetFlag( field, (1<<(bit-1)) ); unit->SetFlag( field, (1<<(bit-1)) );
PSendSysMessage(LANG_SET_BIT, bit, field); PSendSysMessage(LANG_SET_BIT, bit, field);
} }
return true; return true;
} }

View file

@ -854,7 +854,7 @@ bool ChatHandler::HandleNpcAddCommand(const char* args)
{ {
if(!*args) if(!*args)
return false; return false;
char* charID = strtok((char*)args, " "); char* charID = extractKeyFromLink((char*)args,"Hcreature_entry");
if(!charID) if(!charID)
return false; return false;

View file

@ -339,6 +339,15 @@ bool ChatHandler::HandleReloadLootTemplatesSkinningCommand(const char*)
return true; 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*) bool ChatHandler::HandleReloadMangosStringCommand(const char*)
{ {
sLog.outString( "Re-Loading mangos_string Table!" ); sLog.outString( "Re-Loading mangos_string Table!" );
@ -2632,15 +2641,25 @@ bool ChatHandler::HandleLookupSkillCommand(const char* args)
if(loc < MAX_LOCALE) if(loc < MAX_LOCALE)
{ {
char valStr[50] = "";
char const* knownStr = ""; char const* knownStr = "";
if(target && target->HasSkill(id)) if(target && target->HasSkill(id))
{
knownStr = GetMangosString(LANG_KNOWN); 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 // send skill in "id - [namedlink locale]" format
if (m_session) 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 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; ++counter;
} }
@ -3836,8 +3855,6 @@ bool ChatHandler::HandleShowAreaCommand(const char* args)
if (!*args) if (!*args)
return false; return false;
int area = atoi((char*)args);
Player *chr = getSelectedPlayer(); Player *chr = getSelectedPlayer();
if (chr == NULL) if (chr == NULL)
{ {
@ -3846,10 +3863,11 @@ bool ChatHandler::HandleShowAreaCommand(const char* args)
return false; return false;
} }
int area = GetAreaFlagByAreaID(atoi((char*)args));
int offset = area / 32; int offset = area / 32;
uint32 val = (uint32)(1 << (area % 32)); uint32 val = (uint32)(1 << (area % 32));
if(offset >= 128) if(area<0 || offset >= 128)
{ {
SendSysMessage(LANG_BAD_VALUE); SendSysMessage(LANG_BAD_VALUE);
SetSentErrorMessage(true); SetSentErrorMessage(true);
@ -3868,8 +3886,6 @@ bool ChatHandler::HandleHideAreaCommand(const char* args)
if (!*args) if (!*args)
return false; return false;
int area = atoi((char*)args);
Player *chr = getSelectedPlayer(); Player *chr = getSelectedPlayer();
if (chr == NULL) if (chr == NULL)
{ {
@ -3878,10 +3894,11 @@ bool ChatHandler::HandleHideAreaCommand(const char* args)
return false; return false;
} }
int area = GetAreaFlagByAreaID(atoi((char*)args));
int offset = area / 32; int offset = area / 32;
uint32 val = (uint32)(1 << (area % 32)); uint32 val = (uint32)(1 << (area % 32));
if(offset >= 128) if(area<0 || offset >= 128)
{ {
SendSysMessage(LANG_BAD_VALUE); SendSysMessage(LANG_BAD_VALUE);
SetSentErrorMessage(true); SetSentErrorMessage(true);
@ -4394,8 +4411,10 @@ bool ChatHandler::HandleResetLevelCommand(const char * args)
// reset level to summoned pet // reset level to summoned pet
Pet* pet = player->GetPet(); Pet* pet = player->GetPet();
if(pet && pet->getPetType()==SUMMON_PET) if(pet && pet->getPetType()==SUMMON_PET)
{
pet->InitStatsForLevel(1); pet->InitStatsForLevel(1);
pet->InitTalentForLevel();
}
return true; return true;
} }
@ -4507,13 +4526,6 @@ bool ChatHandler::HandleResetTalentsCommand(const char * args)
else else
player = getSelectedPlayer(); player = getSelectedPlayer();
if(!player && !playerGUID)
{
SendSysMessage(LANG_NO_CHAR_SELECTED);
SetSentErrorMessage(true);
return false;
}
if(player) if(player)
{ {
player->resetTalents(true); player->resetTalents(true);
@ -4522,14 +4534,33 @@ bool ChatHandler::HandleResetTalentsCommand(const char * args)
if(m_session->GetPlayer()!=player) if(m_session->GetPlayer()!=player)
PSendSysMessage(LANG_RESET_TALENTS_ONLINE,player->GetName()); 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) ); 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); 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) bool ChatHandler::HandleResetAllCommand(const char * args)

View file

@ -23,6 +23,7 @@
#include "World.h" #include "World.h"
#include "Util.h" #include "Util.h"
#include "SharedDefines.h" #include "SharedDefines.h"
#include "SpellMgr.h"
static Rates const qualityToRate[MAX_ITEM_QUALITY] = { static Rates const qualityToRate[MAX_ITEM_QUALITY] = {
RATE_DROP_ITEM_POOR, // ITEM_QUALITY_POOR 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 RATE_DROP_ITEM_ARTIFACT, // ITEM_QUALITY_ARTIFACT
}; };
LootStore LootTemplates_Creature( "creature_loot_template", "creature entry"); LootStore LootTemplates_Creature( "creature_loot_template", "creature entry", true);
LootStore LootTemplates_Disenchant( "disenchant_loot_template", "item disenchant id"); LootStore LootTemplates_Disenchant( "disenchant_loot_template", "item disenchant id", true);
LootStore LootTemplates_Fishing( "fishing_loot_template", "area id"); LootStore LootTemplates_Fishing( "fishing_loot_template", "area id", true);
LootStore LootTemplates_Gameobject( "gameobject_loot_template", "gameobject entry"); LootStore LootTemplates_Gameobject( "gameobject_loot_template", "gameobject entry", true);
LootStore LootTemplates_Item( "item_loot_template", "item entry"); LootStore LootTemplates_Item( "item_loot_template", "item entry", true);
LootStore LootTemplates_Milling( "milling_loot_template", "item entry"); LootStore LootTemplates_Milling( "milling_loot_template", "item entry (herb)", true);
LootStore LootTemplates_Pickpocketing("pickpocketing_loot_template","creature pickpocket lootid"); LootStore LootTemplates_Pickpocketing("pickpocketing_loot_template","creature pickpocket lootid", true);
LootStore LootTemplates_Prospecting( "prospecting_loot_template", "item entry"); LootStore LootTemplates_Prospecting( "prospecting_loot_template", "item entry (ore)", true);
LootStore LootTemplates_QuestMail( "quest_mail_loot_template", "quest id"); LootStore LootTemplates_QuestMail( "quest_mail_loot_template", "quest id (with mail template)",false);
LootStore LootTemplates_Reference( "reference_loot_template", "reference id"); LootStore LootTemplates_Reference( "reference_loot_template", "reference id", false);
LootStore LootTemplates_Skinning( "skinning_loot_template", "creature skinning id"); 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) 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 HasQuestDrop() const; // True if group includes at least 1 quest drop entry
bool HasQuestDropForPlayer(Player const * player) const; bool HasQuestDropForPlayer(Player const * player) const;
// The same for active quests of the player // 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 RawTotalChance() const; // Overall chance for the group (without equal chanced items)
float TotalChance() const; // Overall chance for the group 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 ExplicitlyChanced; // Entries with chances defined in DB
LootStoreItemList EqualChanced; // Zero chances - every entry takes the same chance 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 //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) // 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 // 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) if(chance>=100.f)
return true; return true;
if(mincountOrRef < 0) // reference case 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); 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); 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); items.reserve(MAX_NR_LOOT_ITEMS);
quest_items.reserve(MAX_NR_QUEST_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 // Setting access rights fow group-looting case
if(!loot_owner) 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 // 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 if (!ExplicitlyChanced.empty()) // First explicitly chanced entries are checked
{ {
@ -775,7 +777,7 @@ LootStoreItem const * LootTemplate::LootGroup::Roll() const
return &ExplicitlyChanced[i]; return &ExplicitlyChanced[i];
ItemPrototype const *pProto = objmgr.GetItemPrototype(ExplicitlyChanced[i].itemid); 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; Roll -= ExplicitlyChanced[i].chance * qualityMultiplier;
if (Roll < 0) if (Roll < 0)
return &ExplicitlyChanced[i]; 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 // 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) if (item != NULL)
loot.AddItem(*item); 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 // 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) // Group reference uses own processing of the group
{ {
if (groupId > Groups.size()) if (groupId > Groups.size())
return; // Error message already printed at loading stage return; // Error message already printed at loading stage
Groups[groupId-1].Process(loot); Groups[groupId-1].Process(loot,rate);
return; return;
} }
// Rolling non-grouped items // Rolling non-grouped items
for (LootStoreItemList::const_iterator i = Entries.begin() ; i != Entries.end() ; ++i ) for (LootStoreItemList::const_iterator i = Entries.begin() ; i != Entries.end() ; ++i )
{ {
if ( !i->Roll() ) if (!i->Roll(rate))
continue; // Bad luck for the entry continue; // Bad luck for the entry
if (i->mincountOrRef < 0) // References processing 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 continue; // Error message already printed at loading stage
for (uint32 loop=0; loop < i->maxcount; ++loop )// Ref multiplicator 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) else // Plain entries (not a reference, not grouped)
loot.AddItem(*i); // Chance is already checked, just add 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 // Now processing groups
for (LootGroups::const_iterator i = Groups.begin( ) ; i != Groups.end( ) ; ++i ) 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 // True if template includes at least 1 quest drop entry
@ -1143,9 +1145,17 @@ void LoadLootTemplates_Milling()
// remove real entries and check existence loot // remove real entries and check existence loot
for(uint32 i = 1; i < sItemStorage.MaxEntry; ++i ) for(uint32 i = 1; i < sItemStorage.MaxEntry; ++i )
if(ItemPrototype const* proto = sItemStorage.LookupEntry<ItemPrototype>(i)) {
ItemPrototype const* proto = sItemStorage.LookupEntry<ItemPrototype>(i);
if(!proto)
continue;
if((proto->BagFamily & BAG_FAMILY_MASK_HERBS)==0)
continue;
if(ids_set.count(proto->ItemId)) if(ids_set.count(proto->ItemId))
ids_set.erase(proto->ItemId); ids_set.erase(proto->ItemId);
}
// output error for any still listed (not referenced from appropriate table) ids // output error for any still listed (not referenced from appropriate table) ids
LootTemplates_Milling.ReportUnusedIds(ids_set); LootTemplates_Milling.ReportUnusedIds(ids_set);
@ -1184,9 +1194,17 @@ void LoadLootTemplates_Prospecting()
// remove real entries and check existence loot // remove real entries and check existence loot
for(uint32 i = 1; i < sItemStorage.MaxEntry; ++i ) for(uint32 i = 1; i < sItemStorage.MaxEntry; ++i )
if(ItemPrototype const* proto = sItemStorage.LookupEntry<ItemPrototype>(i)) {
ItemPrototype const* proto = sItemStorage.LookupEntry<ItemPrototype>(i);
if(!proto)
continue;
if((proto->BagFamily & BAG_FAMILY_MASK_MINING_SUPP)==0)
continue;
if(ids_set.count(proto->ItemId)) if(ids_set.count(proto->ItemId))
ids_set.erase(proto->ItemId); ids_set.erase(proto->ItemId);
}
// output error for any still listed (not referenced from appropriate table) ids // output error for any still listed (not referenced from appropriate table) ids
LootTemplates_Prospecting.ReportUnusedIds(ids_set); LootTemplates_Prospecting.ReportUnusedIds(ids_set);
@ -1200,8 +1218,17 @@ void LoadLootTemplates_QuestMail()
// remove real entries and check existence loot // remove real entries and check existence loot
ObjectMgr::QuestMap const& questMap = objmgr.GetQuestTemplates(); ObjectMgr::QuestMap const& questMap = objmgr.GetQuestTemplates();
for(ObjectMgr::QuestMap::const_iterator itr = questMap.begin(); itr != questMap.end(); ++itr ) for(ObjectMgr::QuestMap::const_iterator itr = questMap.begin(); itr != questMap.end(); ++itr )
{
if(!itr->second->GetRewMailTemplateId())
continue;
if(ids_set.count(itr->first)) if(ids_set.count(itr->first))
ids_set.erase(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 // output error for any still listed (not referenced from appropriate table) ids
LootTemplates_QuestMail.ReportUnusedIds(ids_set); LootTemplates_QuestMail.ReportUnusedIds(ids_set);
@ -1233,6 +1260,32 @@ void LoadLootTemplates_Skinning()
LootTemplates_Skinning.ReportUnusedIds(ids_set); 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() void LoadLootTemplates_Reference()
{ {
LootIdSet ids_set; LootIdSet ids_set;

View file

@ -75,7 +75,7 @@ struct LootStoreItem
group(_group), maxcount(_maxcount), conditionId(_conditionId), group(_group), maxcount(_maxcount), conditionId(_conditionId),
needs_quest(_chanceOrQuestChance < 0) {} 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; bool IsValid(LootStore const& store, uint32 entry) const;
// Checks correctness of values // Checks correctness of values
}; };
@ -127,7 +127,8 @@ typedef std::set<uint32> LootIdSet;
class LootStore class LootStore
{ {
public: 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(); } virtual ~LootStore() { Clear(); }
void Verify() const; void Verify() const;
@ -145,6 +146,7 @@ class LootStore
char const* GetName() const { return m_name; } char const* GetName() const { return m_name; }
char const* GetEntryName() const { return m_entryName; } char const* GetEntryName() const { return m_entryName; }
bool IsRatesAllowed() const { return m_ratesAllowed; }
protected: protected:
void LoadLootTable(); void LoadLootTable();
void Clear(); void Clear();
@ -152,6 +154,7 @@ class LootStore
LootTemplateMap m_LootTemplates; LootTemplateMap m_LootTemplates;
char const* m_name; char const* m_name;
char const* m_entryName; char const* m_entryName;
bool m_ratesAllowed;
}; };
class LootTemplate class LootTemplate
@ -163,7 +166,7 @@ class LootTemplate
// Adds an entry to the group (at loading stage) // Adds an entry to the group (at loading stage)
void AddEntry(LootStoreItem& item); void AddEntry(LootStoreItem& item);
// Rolls for every item in the template and adds the rolled items the the loot // 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 // True if template includes at least 1 quest drop entry
bool HasQuestDrop(LootTemplateMap const& store, uint8 GroupId = 0) const; bool HasQuestDrop(LootTemplateMap const& store, uint8 GroupId = 0) const;
@ -301,6 +304,7 @@ extern LootStore LootTemplates_Skinning;
extern LootStore LootTemplates_Disenchant; extern LootStore LootTemplates_Disenchant;
extern LootStore LootTemplates_Prospecting; extern LootStore LootTemplates_Prospecting;
extern LootStore LootTemplates_QuestMail; extern LootStore LootTemplates_QuestMail;
extern LootStore LootTemplates_Spell;
void LoadLootTemplates_Creature(); void LoadLootTemplates_Creature();
void LoadLootTemplates_Fishing(); void LoadLootTemplates_Fishing();
@ -312,6 +316,8 @@ void LoadLootTemplates_Skinning();
void LoadLootTemplates_Disenchant(); void LoadLootTemplates_Disenchant();
void LoadLootTemplates_Prospecting(); void LoadLootTemplates_Prospecting();
void LoadLootTemplates_QuestMail(); void LoadLootTemplates_QuestMail();
void LoadLootTemplates_Spell();
void LoadLootTemplates_Reference(); void LoadLootTemplates_Reference();
inline void LoadLootTables() inline void LoadLootTables()
@ -326,6 +332,8 @@ inline void LoadLootTables()
LoadLootTemplates_Disenchant(); LoadLootTemplates_Disenchant();
LoadLootTemplates_Prospecting(); LoadLootTemplates_Prospecting();
LoadLootTemplates_QuestMail(); LoadLootTemplates_QuestMail();
LoadLootTemplates_Spell();
LoadLootTemplates_Reference(); LoadLootTemplates_Reference();
} }

View file

@ -1448,14 +1448,6 @@ void Map::RemoveAllObjectsInRemoveList()
//sLog.outDebug("Object remover 2 check."); //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 Map::GetPlayersCountExceptGMs() const
{ {
uint32 count = 0; uint32 count = 0;

View file

@ -131,7 +131,13 @@ class MANGOS_DLL_SPEC Map : public GridRefManager<NGridType>, public MaNGOS::Obj
virtual ~Map(); virtual ~Map();
// currently unused for normal maps // 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 bool Add(Player *);
virtual void Remove(Player *, bool); virtual void Remove(Player *, bool);
@ -150,7 +156,7 @@ class MANGOS_DLL_SPEC Map : public GridRefManager<NGridType>, public MaNGOS::Obj
template<class LOCK_TYPE, class T, class CONTAINER> void Visit(const CellLock<LOCK_TYPE> &cell, TypeContainerVisitor<T, CONTAINER> &visitor); template<class LOCK_TYPE, class T, class CONTAINER> void Visit(const CellLock<LOCK_TYPE> &cell, TypeContainerVisitor<T, CONTAINER> &visitor);
inline bool IsRemovalGrid(float x, float y) const bool IsRemovalGrid(float x, float y) const
{ {
GridPair p = MaNGOS::ComputeGridPair(x, y); 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 ); 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<NGridType>, public MaNGOS::Obj
bool isGridObjectDataLoaded(uint32 x, uint32 y) const { return getNGrid(x,y)->isGridObjectDataLoaded(); } 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); } 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: protected:
typedef MaNGOS::ObjectLevelLockable<Map, ZThread::Mutex>::Lock Guard; typedef MaNGOS::ObjectLevelLockable<Map, ZThread::Mutex>::Lock Guard;

View file

@ -239,7 +239,7 @@ void MapManager::RemoveBonesFromMap(uint32 mapid, uint64 guid, float x, float y)
} }
void void
MapManager::Update(time_t diff) MapManager::Update(uint32 diff)
{ {
i_timer.Update(diff); i_timer.Update(diff);
if( !i_timer.Passed() ) if( !i_timer.Passed() )

View file

@ -45,18 +45,18 @@ class MANGOS_DLL_DECL MapManager : public MaNGOS::Singleton<MapManager, MaNGOS::
Map const* GetBaseMap(uint32 id) const { return const_cast<MapManager*>(this)->_GetBaseMap(id); } Map const* GetBaseMap(uint32 id) const { return const_cast<MapManager*>(this)->_GetBaseMap(id); }
void DeleteInstance(uint32 mapid, uint32 instanceId); 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); Map const* m = GetBaseMap(mapid);
return m->GetAreaFlag(x, y, z); 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); } uint32 GetAreaId(uint32 mapid, float x, float y, float z) const { 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 GetZoneId(uint32 mapid, float x, float y, float z) const { return Map::GetZoneId(GetAreaFlag(mapid, x, y, z),mapid); }
void Initialize(void); void Initialize(void);
void Update(time_t); void Update(uint32);
inline void SetGridCleanUpDelay(uint32 t) void SetGridCleanUpDelay(uint32 t)
{ {
if( t < MIN_GRID_DELAY ) if( t < MIN_GRID_DELAY )
i_gridCleanUpDelay = MIN_GRID_DELAY; i_gridCleanUpDelay = MIN_GRID_DELAY;
@ -64,7 +64,7 @@ class MANGOS_DLL_DECL MapManager : public MaNGOS::Singleton<MapManager, MaNGOS::
i_gridCleanUpDelay = t; i_gridCleanUpDelay = t;
} }
inline void SetMapUpdateInterval(uint32 t) void SetMapUpdateInterval(uint32 t)
{ {
if( t > MIN_MAP_UPDATE_DELAY ) if( t > MIN_MAP_UPDATE_DELAY )
t = MIN_MAP_UPDATE_DELAY; t = MIN_MAP_UPDATE_DELAY;
@ -106,7 +106,7 @@ class MANGOS_DLL_DECL MapManager : public MaNGOS::Singleton<MapManager, MaNGOS::
bool CanPlayerEnter(uint32 mapid, Player* player); bool CanPlayerEnter(uint32 mapid, Player* player);
void RemoveBonesFromMap(uint32 mapid, uint64 guid, float x, float y); void RemoveBonesFromMap(uint32 mapid, uint64 guid, float x, float y);
inline uint32 GenerateInstanceId() { return ++i_MaxInstanceId; } uint32 GenerateInstanceId() { return ++i_MaxInstanceId; }
void InitMaxInstanceId(); void InitMaxInstanceId();
/* statistics */ /* statistics */

View file

@ -955,7 +955,7 @@ void WorldSession::HandleRequestAccountData(WorldPacket& recv_data)
dest.resize(size); dest.resize(size);
uLongf destSize = size; uLongf destSize = size;
if(compress(const_cast<uint8*>(dest.contents()), &destSize, (uint8*)adata->Data.c_str(), size) != Z_OK) if(size && compress(const_cast<uint8*>(dest.contents()), &destSize, (uint8*)adata->Data.c_str(), size) != Z_OK)
{ {
sLog.outDebug("RAD: Failed to compress account data"); sLog.outDebug("RAD: Failed to compress account data");
return; return;

View file

@ -164,16 +164,16 @@ void WorldSession::SendTrainerList( uint64 guid, const std::string& strTitle )
{ {
TrainerSpell const* tSpell = *itr; TrainerSpell const* tSpell = *itr;
if(!_player->IsSpellFitByClassAndRace(tSpell->spell)) if(!_player->IsSpellFitByClassAndRace(tSpell->learned_spell))
continue; continue;
++count; ++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 << uint8(_player->GetTrainerSpellState(tSpell));
data << uint32(floor(tSpell->spellcost * fDiscountMod)); data << uint32(floor(tSpell->spellcost * fDiscountMod));
@ -238,6 +238,14 @@ void WorldSession::HandleTrainerBuySpellOpcode( WorldPacket & recv_data )
if(_player->GetMoney() < nSpellCost ) if(_player->GetMoney() < nSpellCost )
return; return;
_player->ModifyMoney( -int32(nSpellCost) );
// 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 WorldPacket data(SMSG_PLAY_SPELL_VISUAL, 12); // visual effect on trainer
data << uint64(guid) << uint32(0xB3); data << uint64(guid) << uint32(0xB3);
SendPacket(&data); SendPacket(&data);
@ -246,13 +254,11 @@ void WorldSession::HandleTrainerBuySpellOpcode( WorldPacket & recv_data )
data << uint64(_player->GetGUID()) << uint32(0x016A); data << uint64(_player->GetGUID()) << uint32(0x016A);
SendPacket(&data); SendPacket(&data);
_player->ModifyMoney( -int32(nSpellCost) ); _player->learnSpell(spellId);
}
// learn explicitly to prevent lost money at lags, learning spell will be only show spell animation WorldPacket data(SMSG_TRAINER_BUY_SUCCEEDED, 12);
_player->learnSpell(trainer_spell->spell); data << uint64(guid) << uint32(trainer_spell->spell);
data.Initialize(SMSG_TRAINER_BUY_SUCCEEDED, 12);
data << uint64(guid) << uint32(spellId);
SendPacket(&data); SendPacket(&data);
} }

View file

@ -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<Object *>::iterator iter = i_objects.find(obj);
if( iter != i_objects.end() )
i_objects.erase( iter );
}
void void
ObjectAccessor::_buildUpdateObject(Object *obj, UpdateDataMapType &update_players) ObjectAccessor::_buildUpdateObject(Object *obj, UpdateDataMapType &update_players)
{ {

View file

@ -57,9 +57,7 @@ class HashMapHolder
static void Remove(T* o) static void Remove(T* o)
{ {
Guard guard(i_lock); Guard guard(i_lock);
typename MapType::iterator itr = m_objectMap.find(o->GetGUID()); m_objectMap.erase(o->GetGUID());
if (itr != m_objectMap.end())
m_objectMap.erase(itr);
} }
static T* Find(uint64 guid) static T* Find(uint64 guid)
@ -174,16 +172,22 @@ class MANGOS_DLL_DECL ObjectAccessor : public MaNGOS::Singleton<ObjectAccessor,
HashMapHolder<Player>::Remove(pl); HashMapHolder<Player>::Remove(pl);
Guard guard(i_updateGuard); Guard guard(i_updateGuard);
i_objects.erase((Object *)pl);
std::set<Object *>::iterator iter2 = std::find(i_objects.begin(), i_objects.end(), (Object *)pl);
if( iter2 != i_objects.end() )
i_objects.erase(iter2);
} }
void SaveAllPlayers(); void SaveAllPlayers();
void AddUpdateObject(Object *obj); void AddUpdateObject(Object *obj)
void RemoveUpdateObject(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 Update(uint32 diff);
void UpdatePlayers(uint32 diff); void UpdatePlayers(uint32 diff);

View file

@ -1598,6 +1598,32 @@ void ObjectMgr::LoadItemPrototypes()
if(dbcitem) 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) 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); 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 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; return mBaseXPTable[level] ? mBaseXPTable[level] : 0;
} }
uint32 ObjectMgr::GetXPForLevel(uint32 level)
{
if (level < mPlayerXPperLevel.size())
return mPlayerXPperLevel[level];
return 0;
}
void ObjectMgr::LoadPetNames() void ObjectMgr::LoadPetNames()
{ {
uint32 count = 0; uint32 count = 0;
@ -7040,6 +7134,19 @@ void ObjectMgr::LoadTrainerSpell()
if(!pTrainerSpell->reqlevel) if(!pTrainerSpell->reqlevel)
pTrainerSpell->reqlevel = spellinfo->spellLevel; 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]; TrainerSpellData& data = m_mCacheTrainerSpellMap[entry];

View file

@ -568,6 +568,7 @@ class ObjectMgr
std::string GeneratePetName(uint32 entry); std::string GeneratePetName(uint32 entry);
uint32 GetBaseXP(uint32 level); uint32 GetBaseXP(uint32 level);
uint32 GetXPForLevel(uint32 level);
int32 GetFishingBaseSkillLevel(uint32 entry) const int32 GetFishingBaseSkillLevel(uint32 entry) const
{ {
@ -862,6 +863,9 @@ class ObjectMgr
void BuildPlayerLevelInfo(uint8 race, uint8 class_, uint8 level, PlayerLevelInfo* plinfo) const; void BuildPlayerLevelInfo(uint8 race, uint8 class_, uint8 level, PlayerLevelInfo* plinfo) const;
PlayerInfo playerInfo[MAX_RACES][MAX_CLASSES]; PlayerInfo playerInfo[MAX_RACES][MAX_CLASSES];
typedef std::vector<uint32> PlayerXPperLevel; // [level]
PlayerXPperLevel mPlayerXPperLevel;
typedef std::map<uint32,uint32> BaseXPMap; // [area level][base xp] typedef std::map<uint32,uint32> BaseXPMap; // [area level][base xp]
BaseXPMap mBaseXPTable; BaseXPMap mBaseXPTable;

View file

@ -53,6 +53,7 @@ Pet::Pet(PetType type) : Creature()
m_resetTalentsCost = 0; m_resetTalentsCost = 0;
m_resetTalentsTime = 0; m_resetTalentsTime = 0;
m_usedTalentCount = 0;
m_auraUpdateMask = 0; m_auraUpdateMask = 0;
@ -700,7 +701,7 @@ void Pet::GivePetXP(uint32 xp)
newXP -= nextLvlXP; newXP -= nextLvlXP;
SetLevel( level + 1 ); 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(); level = getLevel();
nextLvlXP = GetUInt32Value(UNIT_FIELD_PETNEXTLEVELEXP); nextLvlXP = GetUInt32Value(UNIT_FIELD_PETNEXTLEVELEXP);
@ -716,6 +717,7 @@ void Pet::GivePetLevel(uint32 level)
return; return;
InitStatsForLevel(level); InitStatsForLevel(level);
InitTalentForLevel();
} }
bool Pet::CreateBaseAtCreature(Creature* creature) bool Pet::CreateBaseAtCreature(Creature* creature)
@ -763,7 +765,7 @@ bool Pet::CreateBaseAtCreature(Creature* creature)
setPowerType(POWER_FOCUS); setPowerType(POWER_FOCUS);
SetUInt32Value(UNIT_FIELD_PET_NAME_TIMESTAMP, 0); SetUInt32Value(UNIT_FIELD_PET_NAME_TIMESTAMP, 0);
SetUInt32Value(UNIT_FIELD_PETEXPERIENCE, 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); SetUInt32Value(UNIT_NPC_FLAGS, 0);
CreatureFamilyEntry const* cFamily = sCreatureFamilyStore.LookupEntry(creature->GetCreatureInfo()->family); CreatureFamilyEntry const* cFamily = sCreatureFamilyStore.LookupEntry(creature->GetCreatureInfo()->family);
@ -906,7 +908,7 @@ bool Pet::InitStatsForLevel(uint32 petlevel)
} }
case HUNTER_PET: case HUNTER_PET:
{ {
SetUInt32Value(UNIT_FIELD_PETNEXTLEVELEXP, uint32((MaNGOS::XP::xp_to_level(petlevel))/4)); SetUInt32Value(UNIT_FIELD_PETNEXTLEVELEXP, objmgr.GetXPForLevel(petlevel)/4);
learnLevelupSpells(); learnLevelupSpells();
//these formula may not be correct; however, it is designed to be close to what it should be //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 //this makes dps 0.5 of pets level
@ -1291,8 +1293,27 @@ bool Pet::addSpell(uint16 spell_id, uint16 active, PetSpellState state, PetSpell
else else
newspell->active = active; newspell->active = active;
uint32 chainstart = spellmgr.GetFirstSpellInChain(spell_id); // talent: unlearn all other talent ranks (high and low)
if(TalentSpellPos const* talentPos = GetTalentSpellPos(spell_id))
{
if(TalentEntry const *talentInfo = sTalentStore.LookupEntry( talentPos->talent_id ))
{
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;
// 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) for (PetSpellMap::iterator itr = m_spells.begin(); itr != m_spells.end(); ++itr)
{ {
if(itr->second->state == PETSPELL_REMOVED) continue; if(itr->second->state == PETSPELL_REMOVED) continue;
@ -1309,6 +1330,7 @@ bool Pet::addSpell(uint16 spell_id, uint16 active, PetSpellState state, PetSpell
break; break;
} }
} }
}
m_spells[spell_id] = newspell; m_spells[spell_id] = newspell;
@ -1320,6 +1342,15 @@ bool Pet::addSpell(uint16 spell_id, uint16 active, PetSpellState state, PetSpell
if(newspell->active == ACT_ENABLED) if(newspell->active == ACT_ENABLED)
ToggleAutocast(spell_id, true); 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; return true;
} }
@ -1329,19 +1360,17 @@ bool Pet::learnSpell(uint16 spell_id)
if (!addSpell(spell_id)) if (!addSpell(spell_id))
return false; return false;
if(GetOwner()->GetTypeId() == TYPEID_PLAYER) Unit* owner = GetOwner();
if(owner && owner->GetTypeId() == TYPEID_PLAYER)
{ {
if(!m_loading) if(!m_loading)
{ {
WorldPacket data(SMSG_PET_LEARNED_SPELL, 2); WorldPacket data(SMSG_PET_LEARNED_SPELL, 2);
data << uint16(spell_id); 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(); ((Player*)owner)->PetSpellInitialize();
}
return true; return true;
} }
@ -1399,6 +1428,18 @@ bool Pet::removeSpell(uint16 spell_id)
RemoveAurasDueToSpell(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; 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 Pet::resetTalentsCost() const
{ {
uint32 days = (sWorld.GetGameTime() - m_resetTalentsTime)/DAY; 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); 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) void Pet::ToggleAutocast(uint32 spellid, bool apply)
{ {
if(IsPassiveSpell(spellid)) 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 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 // Get all passive spells in our skill line

View file

@ -201,15 +201,20 @@ class Pet : public Creature
void InitPetCreateSpells(); void InitPetCreateSpells();
void CheckLearning(uint32 spellid); void CheckLearning(uint32 spellid);
bool resetTalents(bool no_cost = false);
uint32 resetTalentsCost() const; 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); } uint8 GetFreeTalentPoints() { return GetByteValue(UNIT_FIELD_BYTES_1, 1); }
void SetFreeTalentPoints(uint8 points) { SetByteValue(UNIT_FIELD_BYTES_1, 1, points); } void SetFreeTalentPoints(uint8 points) { SetByteValue(UNIT_FIELD_BYTES_1, 1, points); }
uint32 m_resetTalentsCost; uint32 m_resetTalentsCost;
time_t m_resetTalentsTime; 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 SetAuraUpdateMask(uint8 slot) { m_auraUpdateMask |= (uint64(1) << slot); }
void ResetAuraUpdateMask() { m_auraUpdateMask = 0; } void ResetAuraUpdateMask() { m_auraUpdateMask = 0; }

View file

@ -139,11 +139,11 @@ void PetAI::UpdateAI(const uint32 diff)
else else
m_updateAlliesTimer -= diff; m_updateAlliesTimer -= diff;
if (inCombat && i_pet.getVictim() == NULL) if (inCombat && !i_pet.getVictim())
_stopAttack(); _stopAttack();
// i_pet.getVictim() can't be used for check in case stop fighting, i_pet.getVictim() clear at Unit death etc. // 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() ) if( _needToStop() )
{ {

View file

@ -91,9 +91,7 @@ void WorldSession::HandlePetAction( WorldPacket & recv_data )
break; break;
case COMMAND_ATTACK: //spellid=1792 //ATTACK case COMMAND_ATTACK: //spellid=1792 //ATTACK
{ {
// only place where pet can be player const uint64& selguid = _player->GetSelection();
pet->clearUnitState(UNIT_STAT_FOLLOW);
uint64 selguid = _player->GetSelection();
Unit *TargetUnit = ObjectAccessor::GetUnit(*_player, selguid); Unit *TargetUnit = ObjectAccessor::GetUnit(*_player, selguid);
if(!TargetUnit) if(!TargetUnit)
return; return;
@ -105,6 +103,9 @@ void WorldSession::HandlePetAction( WorldPacket & recv_data )
if(!pet->IsWithinLOSInMap(TargetUnit)) if(!pet->IsWithinLOSInMap(TargetUnit))
return; return;
// This is true if pet has no target or has target but targets differs.
if(pet->getVictim() != TargetUnit)
{
if (pet->getVictim()) if (pet->getVictim())
pet->AttackStop(); pet->AttackStop();
@ -128,6 +129,7 @@ void WorldSession::HandlePetAction( WorldPacket & recv_data )
pet->Attack(TargetUnit,true); pet->Attack(TargetUnit,true);
pet->SendPetAIReaction(guid1); pet->SendPetAIReaction(guid1);
} }
}
break; break;
} }
case COMMAND_ABANDON: // abandon (hunter pet) or dismiss (summoned pet) 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_PASSIVE: // 0x0100
case ACT_ENABLED: // 0xC100 spell case ACT_ENABLED: // 0xC100 spell
{ {
Unit* unit_target; Unit* unit_target = NULL;
if(guid2)
unit_target = ObjectAccessor::GetUnit(*_player,guid2);
else
unit_target = NULL;
if (((Creature*)pet)->GetGlobalCooldown() > 0) if (((Creature*)pet)->GetGlobalCooldown() > 0)
return; return;
if(guid2)
unit_target = ObjectAccessor::GetUnit(*_player,guid2);
// do not cast unknown spells // do not cast unknown spells
SpellEntry const *spellInfo = sSpellStore.LookupEntry(spellid ); SpellEntry const *spellInfo = sSpellStore.LookupEntry(spellid );
if(!spellInfo) if(!spellInfo)
@ -225,13 +225,16 @@ void WorldSession::HandlePetAction( WorldPacket & recv_data )
if( unit_target && !GetPlayer()->IsFriendlyTo(unit_target) && !pet->HasAuraType(SPELL_AURA_MOD_POSSESS)) if( unit_target && !GetPlayer()->IsFriendlyTo(unit_target) && !pet->HasAuraType(SPELL_AURA_MOD_POSSESS))
{ {
pet->clearUnitState(UNIT_STAT_FOLLOW); // This is true if pet has no target or has target but targets differs.
if (pet->getVictim() != unit_target)
{
if (pet->getVictim()) if (pet->getVictim())
pet->AttackStop(); pet->AttackStop();
pet->GetMotionMaster()->Clear(); pet->GetMotionMaster()->Clear();
if (((Creature*)pet)->AI()) if (((Creature*)pet)->AI())
((Creature*)pet)->AI()->AttackStart(unit_target); ((Creature*)pet)->AI()->AttackStart(unit_target);
} }
}
spell->prepare(&(spell->m_targets)); spell->prepare(&(spell->m_targets));
} }
@ -487,11 +490,11 @@ void WorldSession::HandlePetUnlearnOpcode(WorldPacket& recvPacket)
sLog.outDetail("CMSG_PET_UNLEARN"); sLog.outDetail("CMSG_PET_UNLEARN");
uint64 guid; uint64 guid;
recvPacket >> guid; recvPacket >> guid; // Pet guid
Pet* pet = _player->GetPet(); 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; return;
if(guid != pet->GetGUID()) 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()); sLog.outError("WorldSession::HandlePetUnlearnOpcode: object "I64FMTD" is considered pet-like but doesn't have a charminfo!", pet->GetGUID());
return; return;
} }
pet->resetTalents();
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();
} }
void WorldSession::HandlePetSpellAutocastOpcode( WorldPacket& recvPacket ) void WorldSession::HandlePetSpellAutocastOpcode( WorldPacket& recvPacket )
@ -605,7 +578,7 @@ void WorldSession::HandlePetCastSpellOpcode( WorldPacket& recvPacket )
if(!_player->GetPet() && !_player->GetCharm()) if(!_player->GetPet() && !_player->GetCharm())
return; return;
if(ObjectAccessor::FindPlayer(guid)) if (GUID_HIPART(guid) == HIGHGUID_PLAYER)
return; return;
Creature* pet = ObjectAccessor::GetCreatureOrPet(*_player,guid); Creature* pet = ObjectAccessor::GetCreatureOrPet(*_player,guid);
@ -809,7 +782,4 @@ void WorldSession::HandlePetLearnTalent( WorldPacket & recv_data )
// learn! (other talent ranks will unlearned at learning) // learn! (other talent ranks will unlearned at learning)
pet->learnSpell(spellid); pet->learnSpell(spellid);
sLog.outDetail("TalentID: %u Rank: %u Spell: %u\n", talent_id, requested_rank, spellid); sLog.outDetail("TalentID: %u Rank: %u Spell: %u\n", talent_id, requested_rank, spellid);
// update free talent points
pet->SetFreeTalentPoints(CurTalentPoints - 1);
} }

View file

@ -348,7 +348,7 @@ Player::Player (WorldSession *session): Unit(), m_achievementMgr(this)
m_regenTimer = 0; m_regenTimer = 0;
m_weaponChangeTimer = 0; m_weaponChangeTimer = 0;
m_breathTimer = 0; m_breathTimer = 0;
m_isunderwater = 0; m_isunderwater = UNDERWATER_NONE;
m_isInWater = false; m_isInWater = false;
m_drunkTimer = 0; m_drunkTimer = 0;
m_drunk = 0; m_drunk = 0;
@ -423,6 +423,11 @@ Player::Player (WorldSession *session): Unit(), m_achievementMgr(this)
for (int i = 0; i < MAX_COMBAT_RATING; i++) for (int i = 0; i < MAX_COMBAT_RATING; i++)
m_baseRatingValue[i] = 0; m_baseRatingValue[i] = 0;
m_baseSpellDamage = 0;
m_baseSpellHealing = 0;
m_baseFeralAP = 0;
m_baseManaRegen = 0;
// Honor System // Honor System
m_lastHonorUpdateTime = time(NULL); m_lastHonorUpdateTime = time(NULL);
@ -868,14 +873,15 @@ void Player::EnvironmentalDamage(uint64 guid, EnviromentalDamage type, uint32 da
void Player::HandleDrowning() void Player::HandleDrowning()
{ {
if(!m_isunderwater) if(!(m_isunderwater&~UNDERWATER_INLAVA))
return; return;
//if player is GM, have waterbreath, is dead or if breathing is disabled then 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); StopMirrorTimer(BREATH_TIMER);
m_isunderwater = 0; // drop every flag _except_ LAVA - otherwise waterbreathing will prevent lava damage
m_isunderwater &= UNDERWATER_INLAVA;
return; return;
} }
@ -885,22 +891,22 @@ void Player::HandleDrowning()
for(AuraList::const_iterator i = mModWaterBreathing.begin(); i != mModWaterBreathing.end(); ++i) for(AuraList::const_iterator i = mModWaterBreathing.begin(); i != mModWaterBreathing.end(); ++i)
UnderWaterTime = uint32(UnderWaterTime * (100.0f + (*i)->GetModifier()->m_amount) / 100.0f); 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 //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; m_breathTimer = UnderWaterTime + 1000;
} }
//single trigger "Breathbar" //single trigger "show Breathbar"
if ( m_breathTimer <= UnderWaterTime && !(m_isunderwater & 0x04)) if ( m_breathTimer <= UnderWaterTime && !(m_isunderwater & UNDERWATER_WATER_BREATHB))
{ {
m_isunderwater|= 0x04; m_isunderwater|= UNDERWATER_WATER_BREATHB;
StartMirrorTimer(BREATH_TIMER, UnderWaterTime); StartMirrorTimer(BREATH_TIMER, UnderWaterTime);
} }
//continuous trigger drowning "Damage" //continuous trigger drowning "Damage"
if ((m_breathTimer == 0) && (m_isunderwater & 0x01)) if ((m_breathTimer == 0) && (m_isunderwater & UNDERWATER_INWATER))
{ {
//TODO: Check this formula //TODO: Check this formula
uint64 guid = GetGUID(); uint64 guid = GetGUID();
@ -911,33 +917,34 @@ void Player::HandleDrowning()
} }
} }
//single trigger retract bar //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; uint32 BreathRegen = 10;
// m_breathTimer will be reduced in ModifyMirrorTimer
ModifyMirrorTimer(BREATH_TIMER, UnderWaterTime, m_breathTimer,BreathRegen); ModifyMirrorTimer(BREATH_TIMER, UnderWaterTime, m_breathTimer,BreathRegen);
m_isunderwater = 0x10; m_isunderwater = UNDERWATER_WATER_BREATHB_RETRACTING;
} }
//remove bar //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); StopMirrorTimer(BREATH_TIMER);
m_isunderwater = 0; m_isunderwater = UNDERWATER_NONE;
} }
} }
void Player::HandleLava() 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 // Single trigger Set BreathTimer
if (!(m_isunderwater & 0x80)) if (!(m_isunderwater & UNDERWATER_INLAVA))
{ {
m_isunderwater|= 0x04; m_isunderwater|= UNDERWATER_WATER_BREATHB;
m_breathTimer = 1000; m_breathTimer = 1000;
} }
*/
// Reset BreathTimer and still in the lava // Reset BreathTimer and still in the lava
if (!m_breathTimer) if (!m_breathTimer)
{ {
@ -951,10 +958,10 @@ void Player::HandleLava()
m_breathTimer = 1000; 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_breathTimer = 0;
m_isunderwater = 0; m_isunderwater = UNDERWATER_NONE;
} }
} }
@ -2180,7 +2187,7 @@ void Player::GiveLevel(uint32 level)
GetSession()->SendPacket(&data); 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 //update level, max level of skills
if(getLevel()!= level) if(getLevel()!= level)
@ -2259,7 +2266,7 @@ void Player::InitStatsForLevel(bool reapplyMods)
objmgr.GetPlayerLevelInfo(getRace(),getClass(),getLevel(),&info); objmgr.GetPlayerLevelInfo(getRace(),getClass(),getLevel(),&info);
SetUInt32Value(PLAYER_FIELD_MAX_LEVEL, sWorld.getConfig(CONFIG_MAX_PLAYER_LEVEL) ); 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 (); UpdateSkillsForLevel ();
@ -2853,13 +2860,16 @@ void Player::learnSpell(uint32 spell_id)
bool learning = addSpell(spell_id,active,true,false); bool learning = addSpell(spell_id,active,true,false);
// learn all disabled higher ranks (recursive) // learn all disabled higher ranks (recursive)
if(disabled)
{
SpellChainMapNext const& nextMap = spellmgr.GetSpellChainNext(); SpellChainMapNext const& nextMap = spellmgr.GetSpellChainNext();
for(SpellChainMapNext::const_iterator i = nextMap.lower_bound(spell_id); i != nextMap.upper_bound(spell_id); ++i) 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); PlayerSpellMap::iterator iter = m_spells.find(i->second);
if (disabled && iter != m_spells.end() && iter->second->disabled) if (iter != m_spells.end() && iter->second->disabled)
learnSpell(i->second); learnSpell(i->second);
} }
}
// prevent duplicated entires in spell book, also not send if not in world (loading) // prevent duplicated entires in spell book, also not send if not in world (loading)
if(!learning || !IsInWorld ()) if(!learning || !IsInWorld ())
@ -3451,22 +3461,22 @@ TrainerSpellState Player::GetTrainerSpellState(TrainerSpell const* trainer_spell
if (!trainer_spell) if (!trainer_spell)
return TRAINER_SPELL_RED; return TRAINER_SPELL_RED;
if (!trainer_spell->spell) if (!trainer_spell->learned_spell)
return TRAINER_SPELL_RED; return TRAINER_SPELL_RED;
// known spell // known spell
if(HasSpell(trainer_spell->spell)) if(HasSpell(trainer_spell->learned_spell))
return TRAINER_SPELL_GRAY; return TRAINER_SPELL_GRAY;
// check race/class requirement // check race/class requirement
if(!IsSpellFitByClassAndRace(trainer_spell->spell)) if(!IsSpellFitByClassAndRace(trainer_spell->learned_spell))
return TRAINER_SPELL_RED; return TRAINER_SPELL_RED;
// check level requirement // check level requirement
if(getLevel() < trainer_spell->reqlevel) if(getLevel() < trainer_spell->reqlevel)
return TRAINER_SPELL_RED; 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 // check prev.rank requirement
if(spell_chain->prev && !HasSpell(spell_chain->prev)) if(spell_chain->prev && !HasSpell(spell_chain->prev))
@ -3482,7 +3492,7 @@ TrainerSpellState Player::GetTrainerSpellState(TrainerSpell const* trainer_spell
return TRAINER_SPELL_RED; return TRAINER_SPELL_RED;
// exist, already checked at loading // 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 // secondary prof. or not prof. spell
uint32 skill = spell->EffectMiscValue[1]; 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); AuraList const& modRatingFromStat = GetAurasByType(SPELL_AURA_MOD_RATING_FROM_STAT);
for(AuraList::const_iterator i = modRatingFromStat.begin();i != modRatingFromStat.end(); ++i) for(AuraList::const_iterator i = modRatingFromStat.begin();i != modRatingFromStat.end(); ++i)
if ((*i)->GetMiscValue() & (1<<cr)) if ((*i)->GetMiscValue() & (1<<cr))
amount += GetStat(Stats((*i)->GetMiscBValue())) * (*i)->GetModifier()->m_amount / 100.0f; amount += int32(GetStat(Stats((*i)->GetMiscBValue())) * (*i)->GetModifier()->m_amount / 100.0f);
if (amount < 0) if (amount < 0)
amount = 0; amount = 0;
SetUInt32Value(PLAYER_FIELD_COMBAT_RATING_1 + cr, uint32(amount)); SetUInt32Value(PLAYER_FIELD_COMBAT_RATING_1 + cr, uint32(amount));
@ -4929,7 +4939,7 @@ void Player::UpdateSkillsToMaxSkillsForLevel()
if (GetUInt32Value(PLAYER_SKILL_INDEX(i))) if (GetUInt32Value(PLAYER_SKILL_INDEX(i)))
{ {
uint32 pskill = GetUInt32Value(PLAYER_SKILL_INDEX(i)) & 0x0000FFFF; uint32 pskill = GetUInt32Value(PLAYER_SKILL_INDEX(i)) & 0x0000FFFF;
if( IsProfessionSkill(pskill) || pskill == SKILL_RIDING ) if( IsProfessionOrRidingSkill(pskill))
continue; continue;
uint32 data = GetUInt32Value(PLAYER_SKILL_VALUE_INDEX(i)); uint32 data = GetUInt32Value(PLAYER_SKILL_VALUE_INDEX(i));
@ -5124,6 +5134,22 @@ uint16 Player::GetPureSkillValue(uint32 skill) const
return 0; 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 int16 Player::GetSkillTempBonusValue(uint32 skill) const
{ {
if(!skill) if(!skill)
@ -5312,7 +5338,7 @@ void Player::CheckExploreSystem()
if(offset >= 128) 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; return;
} }
@ -6477,7 +6503,7 @@ void Player::_ApplyItemBonuses(ItemPrototype const *proto, uint8 slot, bool appl
uint32 level = ((getLevel() > ssd->MaxLevel) ? ssd->MaxLevel : getLevel()); uint32 level = ((getLevel() > ssd->MaxLevel) ? ssd->MaxLevel : getLevel());
if(ScalingStatValuesEntry const *ssv = sScalingStatValuesStore.LookupEntry(level)) if(ScalingStatValuesEntry const *ssv = sScalingStatValuesStore.LookupEntry(level))
{ {
int multiplier = ssv->Multiplier[proto->GetScalingStatValuesColumn()]; uint32 multiplier = ssv->Multiplier[proto->GetScalingStatValuesColumn()];
val = (multiplier * modifier) / 10000; val = (multiplier * modifier) / 10000;
} }
} }
@ -6486,7 +6512,7 @@ void Player::_ApplyItemBonuses(ItemPrototype const *proto, uint8 slot, bool appl
else else
{ {
statType = proto->ItemStat[i].ItemStatType; statType = proto->ItemStat[i].ItemStatType;
val = float(proto->ItemStat[i].ItemStatValue); val = proto->ItemStat[i].ItemStatValue;
} }
if(val == 0) if(val == 0)
@ -6610,9 +6636,31 @@ void Player::_ApplyItemBonuses(ItemPrototype const *proto, uint8 slot, bool appl
case ITEM_MOD_EXPERTISE_RATING: case ITEM_MOD_EXPERTISE_RATING:
ApplyRatingMod(CR_EXPERTISE, int32(val), apply); ApplyRatingMod(CR_EXPERTISE, int32(val), apply);
break; 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: case ITEM_MOD_ARMOR_PENETRATION_RATING:
ApplyRatingMod(CR_ARMOR_PENETRATION, int32(val), apply); ApplyRatingMod(CR_ARMOR_PENETRATION, int32(val), apply);
break; 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() void Player::_RemoveAllItemMods()
{ {
sLog.outDebug("_RemoveAllItemMods start."); 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); ((Player*)this)->ApplyRatingMod(CR_EXPERTISE, enchant_amount, apply);
sLog.outDebug("+ %u EXPERTISE", enchant_amount); sLog.outDebug("+ %u EXPERTISE", enchant_amount);
break; 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: case ITEM_MOD_ARMOR_PENETRATION_RATING:
((Player*)this)->ApplyRatingMod(CR_ARMOR_PENETRATION, enchant_amount, apply); ((Player*)this)->ApplyRatingMod(CR_ARMOR_PENETRATION, enchant_amount, apply);
sLog.outDebug("+ %u ARMOR PENETRATION", enchant_amount); sLog.outDebug("+ %u ARMOR PENETRATION", enchant_amount);
break; 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: default:
break; break;
} }
@ -11874,6 +12037,9 @@ void Player::ApplyEnchantment(Item *item,EnchantmentSlot slot,bool apply, bool a
} }
break; break;
} }
case ITEM_ENCHANTMENT_TYPE_USE_SPELL:
// processed in Player::CastItemUseSpell
break;
default: default:
sLog.outError("Unknown item enchantment display type: %d",enchant_display_type); sLog.outError("Unknown item enchantment display type: %d",enchant_display_type);
break; break;
@ -14098,12 +14264,12 @@ bool Player::LoadFromDB( uint32 guid, SqlQueryHolder *holder )
// clear charm/summon related fields // clear charm/summon related fields
SetCharm(NULL); SetCharm(NULL);
SetPet(NULL); SetPet(NULL);
SetCharmerGUID(NULL); SetCharmerGUID(0);
SetOwnerGUID(NULL); SetOwnerGUID(0);
SetCreatorGUID(NULL); SetCreatorGUID(0);
// reset some aura modifiers before aura apply // reset some aura modifiers before aura apply
SetFarSight(NULL); SetFarSightGUID(0);
SetUInt32Value(PLAYER_TRACK_CREATURES, 0 ); SetUInt32Value(PLAYER_TRACK_CREATURES, 0 );
SetUInt32Value(PLAYER_TRACK_RESOURCES, 0 ); SetUInt32Value(PLAYER_TRACK_RESOURCES, 0 );
@ -14151,6 +14317,7 @@ bool Player::LoadFromDB( uint32 guid, SqlQueryHolder *holder )
//_LoadMail(); //_LoadMail();
_LoadAuras(holder->GetResult(PLAYER_LOGIN_QUERY_LOADAURAS), time_diff); _LoadAuras(holder->GetResult(PLAYER_LOGIN_QUERY_LOADAURAS), time_diff);
_LoadGlyphAuras();
// add ghost flag (must be after aura load: PLAYER_FLAGS_GHOST set in aura) // add ghost flag (must be after aura load: PLAYER_FLAGS_GHOST set in aura)
if( HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_GHOST) ) 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); 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() void Player::LoadCorpse()
{ {
if( isAlive() ) if( isAlive() )
@ -18206,20 +18403,25 @@ bool Player::IsSpellFitByClassAndRace( uint32 spell_id ) const
SkillLineAbilityMap::const_iterator lower = spellmgr.GetBeginSkillLineAbilityMap(spell_id); SkillLineAbilityMap::const_iterator lower = spellmgr.GetBeginSkillLineAbilityMap(spell_id);
SkillLineAbilityMap::const_iterator upper = spellmgr.GetEndSkillLineAbilityMap(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) for(SkillLineAbilityMap::const_iterator _spell_idx = lower; _spell_idx != upper; ++_spell_idx)
{ {
// skip wrong race skills // skip wrong race skills
if( _spell_idx->second->racemask && (_spell_idx->second->racemask & racemask) == 0) if( _spell_idx->second->racemask && (_spell_idx->second->racemask & racemask) == 0)
return false; continue;
// skip wrong class skills // skip wrong class skills
if( _spell_idx->second->classmask && (_spell_idx->second->classmask & classmask) == 0) 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) bool Player::HasQuestForGO(int32 GOId)
{ {
for( QuestStatusMap::iterator i = mQuestStatus.begin( ); i != mQuestStatus.end( ); ++i ) for( QuestStatusMap::iterator i = mQuestStatus.begin( ); i != mQuestStatus.end( ); ++i )
@ -18841,18 +19043,20 @@ PartyResult Player::CanUninviteFromGroup() const
void Player::UpdateUnderwaterState( Map* m, float x, float y, float z ) void Player::UpdateUnderwaterState( Map* m, float x, float y, float z )
{ {
float water_z = m->GetWaterLevel(x,y); 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); uint8 flag1 = m->GetTerrainType(x,y);
//!Underwater check, not in water if underground or above water level //!Underwater check, not in water if underground or above water level - take UC royal quater for example
if (height_z <= INVALID_HEIGHT || z < (height_z-2) || z > (water_z - 2) ) if (terrain_z <= INVALID_HEIGHT || z < (terrain_z-2) || z > (water_z - 2) )
m_isunderwater &= 0x7A; m_isunderwater &= ~UNDERWATER_INWATER;
else if ((z < (water_z - 2)) && (flag1 & 0x01)) else if ((z < (water_z - 2)) && (flag1 & 0x01))
m_isunderwater |= 0x01; m_isunderwater |= UNDERWATER_INWATER;
//!in lava check, anywhere under lava level //!in lava check, anywhere under lava level
if ((height_z <= INVALID_HEIGHT || z < (height_z - 0)) && (flag1 == 0x00) && IsInWater()) if ((terrain_z <= INVALID_HEIGHT || z < (terrain_z - 0)) && (flag1 == 0x00) && IsInWater())
m_isunderwater |= 0x80; m_isunderwater |= UNDERWATER_INLAVA;
else
m_isunderwater &= ~UNDERWATER_INLAVA;
} }
void Player::SetCanParry( bool value ) void Player::SetCanParry( bool value )
@ -18963,11 +19167,11 @@ void Player::EnterVehicle(Vehicle *vehicle)
vehicle->SetCharmerGUID(GetGUID()); vehicle->SetCharmerGUID(GetGUID());
vehicle->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_SPELLCLICK); 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()); vehicle->setFaction(getFaction());
SetCharm(vehicle); // charm SetCharm(vehicle); // charm
SetFarSight(vehicle->GetGUID()); // set view SetFarSightGUID(vehicle->GetGUID()); // set view
SetClientControl(vehicle, 1); // redirect controls to vehicle SetClientControl(vehicle, 1); // redirect controls to vehicle
@ -19014,11 +19218,11 @@ void Player::ExitVehicle(Vehicle *vehicle)
{ {
vehicle->SetCharmerGUID(0); vehicle->SetCharmerGUID(0);
vehicle->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_SPELLCLICK); 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); vehicle->setFaction((GetTeam() == ALLIANCE) ? vehicle->GetCreatureInfo()->faction_A : vehicle->GetCreatureInfo()->faction_H);
SetCharm(NULL); SetCharm(NULL);
SetFarSight(NULL); SetFarSightGUID(0);
SetClientControl(vehicle, 0); SetClientControl(vehicle, 0);
@ -19109,3 +19313,23 @@ void Player::InitRunes()
for(uint32 i = 0; i < NUM_RUNE_TYPES; ++i) for(uint32 i = 0; i < NUM_RUNE_TYPES; ++i)
SetFloatValue(PLAYER_RUNE_REGEN_1 + i, 0.1f); 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);
}

View file

@ -46,6 +46,7 @@ class Pet;
class PlayerMenu; class PlayerMenu;
class Transport; class Transport;
class UpdateMask; class UpdateMask;
class SpellCastTargets;
class PlayerSocial; class PlayerSocial;
class AchievementMgr; class AchievementMgr;
class Vehicle; class Vehicle;
@ -62,6 +63,17 @@ enum SpellModType
SPELLMOD_PCT = 108 // SPELL_AURA_ADD_PCT_MODIFIER 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 enum PlayerSpellState
{ {
PLAYERSPELL_UNCHANGED = 0, 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_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_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_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<<bit_index) without (-1) // used for PLAYER__FIELD_KNOWN_TITLES field (uint64), (1<<bit_index) without (-1)
@ -1135,6 +1154,8 @@ class MANGOS_DLL_SPEC Player : public Unit
Item* EquipItem( uint16 pos, Item *pItem, bool update ); Item* EquipItem( uint16 pos, Item *pItem, bool update );
void AutoUnequipOffhandIfNeed(); void AutoUnequipOffhandIfNeed();
bool StoreNewItemInBestSlots(uint32 item_id, uint32 item_count); bool StoreNewItemInBestSlots(uint32 item_id, uint32 item_count);
void AutoStoreLootItem(uint8 bag, uint8 slot, uint32 loot_id, LootStore const& store);
void AutoStoreLootItem(uint32 loot_id, LootStore const& store) { AutoStoreLootItem(NULL_BAG,NULL_SLOT,loot_id,store); }
uint8 _CanTakeMoreSimilarItems(uint32 entry, uint32 count, Item* pItem, uint32* no_space_count = NULL) const; uint8 _CanTakeMoreSimilarItems(uint32 entry, uint32 count, Item* pItem, uint32* no_space_count = NULL) const;
uint8 _CanStoreItem( uint8 bag, uint8 slot, ItemPosCountVec& dest, uint32 entry, uint32 count, Item *pItem = NULL, bool swap = false, uint32* no_space_count = NULL ) const; uint8 _CanStoreItem( uint8 bag, uint8 slot, ItemPosCountVec& dest, uint32 entry, uint32 count, Item *pItem = NULL, bool swap = false, uint32* no_space_count = NULL ) const;
@ -1399,7 +1420,7 @@ class MANGOS_DLL_SPEC Player : public Unit
void SetSelection(const uint64 &guid) { m_curSelection = guid; SetUInt64Value(UNIT_FIELD_TARGET, guid); } void SetSelection(const uint64 &guid) { m_curSelection = guid; SetUInt64Value(UNIT_FIELD_TARGET, guid); }
uint8 GetComboPoints() { return m_comboPoints; } uint8 GetComboPoints() { return m_comboPoints; }
uint64 GetComboTarget() { return m_comboTarget; } const uint64& GetComboTarget() const { return m_comboTarget; }
void AddComboPoints(Unit* target, int8 count); void AddComboPoints(Unit* target, int8 count);
void ClearComboPoints(); void ClearComboPoints();
@ -1435,10 +1456,7 @@ class MANGOS_DLL_SPEC Player : public Unit
Item* GetMItem(uint32 id) Item* GetMItem(uint32 id)
{ {
ItemMap::const_iterator itr = mMitems.find(id); ItemMap::const_iterator itr = mMitems.find(id);
if (itr != mMitems.end()) return itr != mMitems.end() ? itr->second : NULL;
return itr->second;
return NULL;
} }
void AddMItem(Item* it) void AddMItem(Item* it)
@ -1450,12 +1468,7 @@ class MANGOS_DLL_SPEC Player : public Unit
bool RemoveMItem(uint32 id) bool RemoveMItem(uint32 id)
{ {
ItemMap::iterator i = mMitems.find(id); return mMitems.erase(id) ? true : false;
if (i == mMitems.end())
return false;
mMitems.erase(i);
return true;
} }
void PetSpellInitialize(); void PetSpellInitialize();
@ -1625,9 +1638,12 @@ class MANGOS_DLL_SPEC Player : public Unit
void UpdateArmor(); void UpdateArmor();
void UpdateMaxHealth(); void UpdateMaxHealth();
void UpdateMaxPower(Powers power); void UpdateMaxPower(Powers power);
void ApplyFeralAPBonus(int32 amount, bool apply);
void UpdateAttackPowerAndDamage(bool ranged = false); void UpdateAttackPowerAndDamage(bool ranged = false);
void UpdateShieldBlockValue(); void UpdateShieldBlockValue();
void UpdateDamagePhysical(WeaponAttackType attType); void UpdateDamagePhysical(WeaponAttackType attType);
void ApplySpellDamageBonus(int32 amount, bool apply);
void ApplySpellHealingBonus(int32 amount, bool apply);
void UpdateSpellDamageAndHealingBonus(); void UpdateSpellDamageAndHealingBonus();
void CalculateMinMaxDamage(WeaponAttackType attType, bool normalized, float& min_damage, float& max_damage); 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 GetRangedCritDamageReduction(uint32 damage) const;
uint32 GetSpellCritDamageReduction(uint32 damage) const; uint32 GetSpellCritDamageReduction(uint32 damage) const;
uint32 GetDotDamageReduction(uint32 damage) const; uint32 GetDotDamageReduction(uint32 damage) const;
uint32 GetBaseSpellDamageBonus() { return m_baseSpellDamage;}
uint32 GetBaseSpellHealingBonus() { return m_baseSpellHealing;}
float GetExpertiseDodgeOrParryReduction(WeaponAttackType attType) const; float GetExpertiseDodgeOrParryReduction(WeaponAttackType attType) const;
void UpdateBlockPercentage(); void UpdateBlockPercentage();
@ -1659,6 +1677,7 @@ class MANGOS_DLL_SPEC Player : public Unit
void UpdateAllSpellCritChances(); void UpdateAllSpellCritChances();
void UpdateSpellCritChance(uint32 school); void UpdateSpellCritChance(uint32 school);
void UpdateExpertise(WeaponAttackType attType); void UpdateExpertise(WeaponAttackType attType);
void ApplyManaRegenBonus(int32 amount, bool apply);
void UpdateManaRegen(); void UpdateManaRegen();
const uint64& GetLootGUID() const { return m_lootGuid; } 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 UpdateCombatSkills(Unit *pVictim, WeaponAttackType attType, bool defence);
void SetSkill(uint32 id, uint16 currVal, uint16 maxVal); 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 GetPureMaxSkillValue(uint32 skill) const; // max
uint16 GetSkillValue(uint32 skill) const; // skill value + perm. bonus + temp bonus uint16 GetSkillValue(uint32 skill) const; // skill value + perm. bonus + temp bonus
uint16 GetBaseSkillValue(uint32 skill) const; // skill value + perm. bonus uint16 GetBaseSkillValue(uint32 skill) const; // skill value + perm. bonus
uint16 GetPureSkillValue(uint32 skill) const; // skill value uint16 GetPureSkillValue(uint32 skill) const; // skill value
int16 GetSkillPermBonusValue(uint32 skill) const;
int16 GetSkillTempBonusValue(uint32 skill) const; int16 GetSkillTempBonusValue(uint32 skill) const;
bool HasSkill(uint32 skill) const; bool HasSkill(uint32 skill) const;
void learnSkillRewardedSpells( uint32 id ); 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 ApplyEquipSpell(SpellEntry const* spellInfo, Item* item, bool apply, bool form_change = false);
void UpdateEquipSpellsAtFormChange(); void UpdateEquipSpellsAtFormChange();
void CastItemCombatSpell(Item *item,Unit* Target, WeaponAttackType attType); void CastItemCombatSpell(Item *item,Unit* Target, WeaponAttackType attType);
void CastItemUseSpell(Item *item,SpellCastTargets const& targets,uint8 cast_count, uint32 glyphIndex);
void SendInitWorldStates(); void SendInitWorldStates();
void SendUpdateWorldState(uint32 Field, uint32 Value); void SendUpdateWorldState(uint32 Field, uint32 Value);
@ -2037,7 +2058,7 @@ class MANGOS_DLL_SPEC Player : public Unit
void ExitVehicle(Vehicle *vehicle); void ExitVehicle(Vehicle *vehicle);
uint64 GetFarSight() const { return GetUInt64Value(PLAYER_FARSIGHT); } uint64 GetFarSight() const { return GetUInt64Value(PLAYER_FARSIGHT); }
void SetFarSight(uint64 guid) { SetUInt64Value(PLAYER_FARSIGHT, guid); } void SetFarSightGUID(uint64 guid) { SetUInt64Value(PLAYER_FARSIGHT, guid); }
// Transports // Transports
Transport * GetTransport() const { return m_transport; } Transport * GetTransport() const { return m_transport; }
@ -2131,9 +2152,9 @@ class MANGOS_DLL_SPEC Player : public Unit
GroupReference& GetGroupRef() { return m_group; } GroupReference& GetGroupRef() { return m_group; }
void SetGroup(Group *group, int8 subgroup = -1); void SetGroup(Group *group, int8 subgroup = -1);
uint8 GetSubGroup() const { return m_group.getSubGroup(); } 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; } 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); } void SetAuraUpdateMask(uint8 slot) { m_auraUpdateMask |= (uint64(1) << slot); }
Player* GetNextRandomRaidMember(float radius); Player* GetNextRandomRaidMember(float radius);
PartyResult CanUninviteFromGroup() const; PartyResult CanUninviteFromGroup() const;
@ -2207,6 +2228,7 @@ class MANGOS_DLL_SPEC Player : public Unit
void _LoadActions(QueryResult *result); void _LoadActions(QueryResult *result);
void _LoadAuras(QueryResult *result, uint32 timediff); void _LoadAuras(QueryResult *result, uint32 timediff);
void _LoadGlyphAuras();
void _LoadBoundInstances(QueryResult *result); void _LoadBoundInstances(QueryResult *result);
void _LoadInventory(QueryResult *result, uint32 timediff); void _LoadInventory(QueryResult *result, uint32 timediff);
void _LoadMailInit(QueryResult *resultUnread, QueryResult *resultDelivery); void _LoadMailInit(QueryResult *resultUnread, QueryResult *resultDelivery);
@ -2295,6 +2317,10 @@ class MANGOS_DLL_SPEC Player : public Unit
float m_auraBaseMod[BASEMOD_END][MOD_END]; float m_auraBaseMod[BASEMOD_END][MOD_END];
int16 m_baseRatingValue[MAX_COMBAT_RATING]; int16 m_baseRatingValue[MAX_COMBAT_RATING];
uint16 m_baseSpellDamage;
uint16 m_baseSpellHealing;
uint16 m_baseFeralAP;
uint16 m_baseManaRegen;
SpellModList m_spellMods[MAX_SPELLMOD]; SpellModList m_spellMods[MAX_SPELLMOD];
int32 m_SpellModRemoveCount; int32 m_SpellModRemoveCount;

View file

@ -252,7 +252,7 @@ enum ItemQualities
#define SPELL_ATTR_EX_NEGATIVE 0x00000080 // 7 #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_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_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_UNK11 0x00000800 // 11
#define SPELL_ATTR_EX_UNK12 0x00001000 // 12 #define SPELL_ATTR_EX_UNK12 0x00001000 // 12
#define SPELL_ATTR_EX_UNK13 0x00002000 // 13 #define SPELL_ATTR_EX_UNK13 0x00002000 // 13
@ -303,7 +303,7 @@ enum ItemQualities
#define SPELL_ATTR_EX2_UNK25 0x02000000 // 25 #define SPELL_ATTR_EX2_UNK25 0x02000000 // 25
#define SPELL_ATTR_EX2_UNK26 0x04000000 // 26 unaffected by school immunity #define SPELL_ATTR_EX2_UNK26 0x04000000 // 26 unaffected by school immunity
#define SPELL_ATTR_EX2_UNK27 0x08000000 // 27 #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_CANT_CRIT 0x20000000 // 29 Spell can't crit
#define SPELL_ATTR_EX2_UNK30 0x40000000 // 30 #define SPELL_ATTR_EX2_UNK30 0x40000000 // 30
#define SPELL_ATTR_EX2_UNK31 0x80000000 // 31 #define SPELL_ATTR_EX2_UNK31 0x80000000 // 31
@ -324,8 +324,8 @@ enum ItemQualities
#define SPELL_ATTR_EX3_UNK13 0x00002000 // 13 #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_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_UNK15 0x00008000 // 15 Auto Shoot, Shoot, Throw, - this is autoshot flag
#define SPELL_ATTR_EX3_UNK16 0x00010000 // 16 #define SPELL_ATTR_EX3_UNK16 0x00010000 // 16 no triggers effects that trigger on casting a spell??
#define SPELL_ATTR_EX3_NO_INITIAL_AGGRO 0x00020000 // 17 no initial aggro #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_UNK18 0x00040000 // 18
#define SPELL_ATTR_EX3_UNK19 0x00080000 // 19 #define SPELL_ATTR_EX3_UNK19 0x00080000 // 19
#define SPELL_ATTR_EX3_DEATH_PERSISTENT 0x00100000 // 20 Death persistent spells #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_REQ_WAND 0x00400000 // 22 Req wand
#define SPELL_ATTR_EX3_UNK23 0x00800000 // 23 #define SPELL_ATTR_EX3_UNK23 0x00800000 // 23
#define SPELL_ATTR_EX3_REQ_OFFHAND 0x01000000 // 24 Req offhand weapon #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_UNK26 0x04000000 // 26
#define SPELL_ATTR_EX3_UNK27 0x08000000 // 27 #define SPELL_ATTR_EX3_UNK27 0x08000000 // 27
#define SPELL_ATTR_EX3_UNK28 0x10000000 // 28 #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_UNK1 0x00000002 // 1 proc on finishing move?
#define SPELL_ATTR_EX4_UNK2 0x00000004 // 2 #define SPELL_ATTR_EX4_UNK2 0x00000004 // 2
#define SPELL_ATTR_EX4_UNK3 0x00000008 // 3 #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_UNK5 0x00000020 // 5
#define SPELL_ATTR_EX4_UNK6 0x00000040 // 6 #define SPELL_ATTR_EX4_UNK6 0x00000040 // 6
#define SPELL_ATTR_EX4_UNK7 0x00000080 // 7 #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_UNK30 0x40000000 // 30 not set in 3.0.3
#define SPELL_ATTR_EX6_UNK31 0x80000000 // 31 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 enum SheathTypes
{ {
SHEATHETYPE_NONE = 0, SHEATHETYPE_NONE = 0,
@ -673,7 +675,7 @@ enum SpellEffects
SPELL_EFFECT_154 = 154, SPELL_EFFECT_154 = 154,
SPELL_EFFECT_TITAN_GRIP = 155, SPELL_EFFECT_TITAN_GRIP = 155,
SPELL_EFFECT_ADD_SOCKET = 156, SPELL_EFFECT_ADD_SOCKET = 156,
SPELL_EFFECT_157 = 157, SPELL_EFFECT_CREATE_ITEM_2 = 157,
SPELL_EFFECT_MILLING = 158, SPELL_EFFECT_MILLING = 158,
SPELL_EFFECT_ALLOW_RENAME_PET = 159, SPELL_EFFECT_ALLOW_RENAME_PET = 159,
TOTAL_SPELL_EFFECTS = 160 TOTAL_SPELL_EFFECTS = 160

View file

@ -29,14 +29,15 @@
struct SkillDiscoveryEntry struct SkillDiscoveryEntry
{ {
uint32 spellId; uint32 spellId; // discavered spell
float chance; uint32 reqSkillValue; // skill level limitation
float chance; // chance
SkillDiscoveryEntry() SkillDiscoveryEntry()
: spellId(0), chance(0) {} : spellId(0), reqSkillValue(0), chance(0) {}
SkillDiscoveryEntry(uint16 _spellId, float _chance) SkillDiscoveryEntry(uint16 _spellId, uint32 req_skill_val, float _chance)
: spellId(_spellId), chance(_chance) {} : spellId(_spellId), reqSkillValue(req_skill_val), chance(_chance) {}
}; };
typedef std::list<SkillDiscoveryEntry> SkillDiscoveryList; typedef std::list<SkillDiscoveryEntry> SkillDiscoveryList;
@ -51,8 +52,8 @@ void LoadSkillDiscoveryTable()
uint32 count = 0; uint32 count = 0;
// 0 1 2 // 0 1 2 3
QueryResult *result = WorldDatabase.Query("SELECT spellId, reqSpell, chance FROM skill_discovery_template"); QueryResult *result = WorldDatabase.Query("SELECT spellId, reqSpell, reqSkillValue, chance FROM skill_discovery_template");
if (result) if (result)
{ {
@ -67,11 +68,13 @@ void LoadSkillDiscoveryTable()
uint32 spellId = fields[0].GetUInt32(); uint32 spellId = fields[0].GetUInt32();
int32 reqSkillOrSpell = fields[1].GetInt32(); int32 reqSkillOrSpell = fields[1].GetInt32();
float chance = fields[2].GetFloat(); uint32 reqSkillValue = fields[2].GetInt32();
float chance = fields[3].GetFloat();
if( chance <= 0 ) // chance 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; continue;
} }
@ -84,13 +87,16 @@ void LoadSkillDiscoveryTable()
continue; 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; continue;
} }
SkillDiscoveryStore[reqSkillOrSpell].push_back( SkillDiscoveryEntry(spellId, chance) ); SkillDiscoveryStore[reqSkillOrSpell].push_back( SkillDiscoveryEntry(spellId, reqSkillValue, chance) );
} }
else if( reqSkillOrSpell == 0 ) // skill case else if( reqSkillOrSpell == 0 ) // skill case
{ {
@ -105,7 +111,7 @@ void LoadSkillDiscoveryTable()
for(SkillLineAbilityMap::const_iterator _spell_idx = lower; _spell_idx != upper; ++_spell_idx) 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 else
@ -113,6 +119,7 @@ void LoadSkillDiscoveryTable()
sLog.outErrorDb("Spell (ID: %u) have negative value in `reqSpell` field in `skill_discovery_template` table",spellId); sLog.outErrorDb("Spell (ID: %u) have negative value in `reqSpell` field in `skill_discovery_template` table",spellId);
continue; continue;
} }
++count; ++count;
} while (result->NextRow()); } 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 GetSkillDiscoverySpell(uint32 skillId, uint32 spellId, Player* player)
{ {
uint32 skillvalue = skillId ? player->GetSkillValue(skillId) : 0;
// check spell case // check spell case
SkillDiscoveryMap::iterator tab = SkillDiscoveryStore.find(spellId); 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) 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)) if( roll_chance_f(item_iter->chance * sWorld.getRate(RATE_SKILL_DISCOVERY))
&& item_iter->reqSkillValue <= skillvalue
&& !player->HasSpell(item_iter->spellId) ) && !player->HasSpell(item_iter->spellId) )
return item_iter->spellId; return item_iter->spellId;
} }
@ -147,6 +195,9 @@ uint32 GetSkillDiscoverySpell(uint32 skillId, uint32 spellId, Player* player)
return 0; return 0;
} }
if(!skillId)
return 0;
// check skill line case // check skill line case
tab = SkillDiscoveryStore.find(-(int32)skillId); tab = SkillDiscoveryStore.find(-(int32)skillId);
if(tab != SkillDiscoveryStore.end()) 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) 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)) if( roll_chance_f(item_iter->chance * sWorld.getRate(RATE_SKILL_DISCOVERY))
&& item_iter->reqSkillValue <= skillvalue
&& !player->HasSpell(item_iter->spellId) ) && !player->HasSpell(item_iter->spellId) )
return item_iter->spellId; return item_iter->spellId;
} }

View file

@ -25,4 +25,5 @@ class Player;
void LoadSkillDiscoveryTable(); void LoadSkillDiscoveryTable();
uint32 GetSkillDiscoverySpell(uint32 skillId, uint32 spellId, Player* player); uint32 GetSkillDiscoverySpell(uint32 skillId, uint32 spellId, Player* player);
uint32 GetExplicitDiscoverySpell(uint32 spellId, Player* player);
#endif #endif

View file

@ -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) void SocialMgr::GetFriendInfo(Player *player, uint32 friendGUID, FriendInfo &friendInfo)
{ {
if(!player) if(!player)

View file

@ -141,7 +141,8 @@ class SocialMgr
SocialMgr(); SocialMgr();
~SocialMgr(); ~SocialMgr();
// Misc // Misc
void RemovePlayerSocial(uint32 guid); void RemovePlayerSocial(uint32 guid) { m_socialMap.erase(guid); }
void GetFriendInfo(Player *player, uint32 friendGUID, FriendInfo &friendInfo); void GetFriendInfo(Player *player, uint32 friendGUID, FriendInfo &friendInfo);
// Packet management // Packet management
void MakeFriendStatusPacket(FriendsResult result, uint32 friend_guid, WorldPacket *data); void MakeFriendStatusPacket(FriendsResult result, uint32 friend_guid, WorldPacket *data);

View file

@ -682,19 +682,23 @@ void Spell::prepareDataForTriggerSystem()
// Ñan spell trigger another or not ( m_canTrigger ) // Ñan spell trigger another or not ( m_canTrigger )
// Create base triggers flags for Attacker and Victim ( m_procAttacker and m_procVictim) // Create base triggers flags for Attacker and Victim ( m_procAttacker and m_procVictim)
//========================================================================================== //==========================================================================================
// Fill flag can spell trigger or not // 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 m_canTrigger = true; // Normal cast - can trigger
else if (!m_triggeredByAuraSpell) else if (!m_triggeredByAuraSpell)
m_canTrigger = true; // Triggered from SPELL_EFFECT_TRIGGER_SPELL - can trigger 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) switch (m_spellInfo->SpellFamilyName)
{ {
case SPELLFAMILY_MAGE: // Arcane Missles triggers need do it case SPELLFAMILY_MAGE: // Arcane Missles / Blizzard triggers need do it
if (m_spellInfo->SpellFamilyFlags & 0x0000000000200000LL) m_canTrigger = true; if (m_spellInfo->SpellFamilyFlags & 0x0000000000200080LL) m_canTrigger = true;
break; break;
case SPELLFAMILY_WARLOCK: // For Hellfire Effect / Rain of Fire / Seed of Corruption triggers need do it case SPELLFAMILY_WARLOCK: // For Hellfire Effect / Rain of Fire / Seed of Corruption triggers need do it
if (m_spellInfo->SpellFamilyFlags & 0x0000800000000060LL) m_canTrigger = true; 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 case SPELLFAMILY_PRIEST: // For Penance heal/damage triggers need do it
if (m_spellInfo->SpellFamilyFlags & 0x0001800000000000LL) m_canTrigger = true; if (m_spellInfo->SpellFamilyFlags & 0x0001800000000000LL) m_canTrigger = true;
break; break;
case SPELLFAMILY_HUNTER: // Hunter Explosive Trap Effect/Immolation Trap Effect/Frost Trap Aura/Snake Trap Effect case SPELLFAMILY_ROGUE: // For poisons need do it
if (m_spellInfo->SpellFamilyFlags & 0x0000200000000014LL) m_canTrigger = true; 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; break;
case SPELLFAMILY_PALADIN: // For Holy Shock triggers need do it case SPELLFAMILY_PALADIN: // For Holy Shock triggers need do it
if (m_spellInfo->SpellFamilyFlags & 0x0001000000200000LL) m_canTrigger = true; if (m_spellInfo->SpellFamilyFlags & 0x0001000000200000LL) m_canTrigger = true;
break; 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 // Get data for type of attack and fill base info for trigger
switch (m_spellInfo->DmgClass) switch (m_spellInfo->DmgClass)
@ -763,8 +767,6 @@ void Spell::CleanupTargetList()
m_UniqueTargetInfo.clear(); m_UniqueTargetInfo.clear();
m_UniqueGOTargetInfo.clear(); m_UniqueGOTargetInfo.clear();
m_UniqueItemInfo.clear(); m_UniqueItemInfo.clear();
m_countOfHit = 0;
m_countOfMiss = 0;
m_delayMoment = 0; m_delayMoment = 0;
} }
@ -773,6 +775,9 @@ void Spell::AddUnitTarget(Unit* pVictim, uint32 effIndex)
if( m_spellInfo->Effect[effIndex]==0 ) if( m_spellInfo->Effect[effIndex]==0 )
return; return;
// Check for effect immune skip if immuned
bool immuned = pVictim->IsImmunedToSpellEffect(m_spellInfo, effIndex);
uint64 targetGUID = pVictim->GetGUID(); uint64 targetGUID = pVictim->GetGUID();
// Lookup target in already in list // Lookup target in already in list
@ -780,7 +785,8 @@ void Spell::AddUnitTarget(Unit* pVictim, uint32 effIndex)
{ {
if (targetGUID == ihit->targetGUID) // Found in list if (targetGUID == ihit->targetGUID) // Found in list
{ {
ihit->effectMask |= 1<<effIndex; // Add only effect mask if (!immuned)
ihit->effectMask |= 1<<effIndex; // Add only effect mask if not immuned
return; return;
} }
} }
@ -790,15 +796,11 @@ void Spell::AddUnitTarget(Unit* pVictim, uint32 effIndex)
// Get spell hit result on target // Get spell hit result on target
TargetInfo target; TargetInfo target;
target.targetGUID = targetGUID; // Store target GUID target.targetGUID = targetGUID; // Store target GUID
target.effectMask = 1<<effIndex; // Store index of effect target.effectMask = immuned ? 0 : 1<<effIndex; // Store index of effect if not immuned
target.processed = false; // Effects not apply on target target.processed = false; // Effects not apply on target
// Calculate hit result // Calculate hit result
target.missCondition = m_caster->SpellHitResult(pVictim, m_spellInfo, m_canReflect); target.missCondition = m_caster->SpellHitResult(pVictim, m_spellInfo, m_canReflect);
if (target.missCondition == SPELL_MISS_NONE)
++m_countOfHit;
else
++m_countOfMiss;
// Spell have speed - need calculate incoming time // Spell have speed - need calculate incoming time
if (m_spellInfo->speed > 0.0f) if (m_spellInfo->speed > 0.0f)
@ -878,8 +880,6 @@ void Spell::AddGOTarget(GameObject* pVictim, uint32 effIndex)
else else
target.timeDelay = 0LL; target.timeDelay = 0LL;
++m_countOfHit;
// Add target to list // Add target to list
m_UniqueGOTargetInfo.push_back(target); m_UniqueGOTargetInfo.push_back(target);
} }
@ -922,8 +922,6 @@ void Spell::DoAllEffectOnTarget(TargetInfo *target)
// Get mask of effects for target // Get mask of effects for target
uint32 mask = target->effectMask; 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); Unit* unit = m_caster->GetGUID()==target->targetGUID ? m_caster : ObjectAccessor::GetUnit(*m_caster,target->targetGUID);
if (!unit) if (!unit)
@ -1101,14 +1099,9 @@ void Spell::DoSpellHitOnUnit(Unit *unit, const uint32 effectMask)
return; 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); unit->RemoveSpellsCausingAura(SPELL_AURA_MOD_STEALTH);
if( !(m_spellInfo->AttributesEx3 & SPELL_ATTR_EX3_NO_INITIAL_AGGRO) ) if( !(m_spellInfo->AttributesEx & SPELL_ATTR_EX_NO_INITIAL_AGGRO) )
{ {
if(!unit->IsStandState() && !unit->hasUnitState(UNIT_STAT_STUNNED)) if(!unit->IsStandState() && !unit->hasUnitState(UNIT_STAT_STUNNED))
unit->SetStandState(PLAYER_STATE_NONE); unit->SetStandState(PLAYER_STATE_NONE);
@ -1126,7 +1119,6 @@ void Spell::DoSpellHitOnUnit(Unit *unit, const uint32 effectMask)
unit->AddThreat(m_caster, 0.0f); unit->AddThreat(m_caster, 0.0f);
} }
} }
}
else else
{ {
// for delayed spells ignore negative spells (after duel end) for friendly targets // for delayed spells ignore negative spells (after duel end) for friendly targets
@ -1139,7 +1131,7 @@ void Spell::DoSpellHitOnUnit(Unit *unit, const uint32 effectMask)
// assisting case, healing and resurrection // assisting case, healing and resurrection
if(unit->hasUnitState(UNIT_STAT_ATTACK_PLAYER)) if(unit->hasUnitState(UNIT_STAT_ATTACK_PLAYER))
m_caster->SetContestedPvP(); 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); m_caster->SetInCombatState(unit->GetCombatTimer() > 0);
unit->getHostilRefManager().threatAssist(m_caster, 0.0f); unit->getHostilRefManager().threatAssist(m_caster, 0.0f);
@ -2046,7 +2038,7 @@ void Spell::SetTargetMap(uint32 i,uint32 cur,std::list<Unit*> &TagUnitMap)
} }
} }
void Spell::prepare(SpellCastTargets * targets, Aura* triggeredByAura) void Spell::prepare(SpellCastTargets const* targets, Aura* triggeredByAura)
{ {
m_targets = *targets; m_targets = *targets;
@ -2997,7 +2989,23 @@ void Spell::WriteAmmoToPacket( WorldPacket * data )
void Spell::WriteSpellGoTargets( 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<TargetInfo>::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<TargetInfo>::iterator ihit= m_UniqueTargetInfo.begin();ihit != m_UniqueTargetInfo.end();++ihit) for(std::list<TargetInfo>::iterator ihit= m_UniqueTargetInfo.begin();ihit != m_UniqueTargetInfo.end();++ihit)
if ((*ihit).missCondition == SPELL_MISS_NONE) // Add only hits if ((*ihit).missCondition == SPELL_MISS_NONE) // Add only hits
*data << uint64(ihit->targetGUID); *data << uint64(ihit->targetGUID);
@ -3005,7 +3013,7 @@ void Spell::WriteSpellGoTargets( WorldPacket * data )
for(std::list<GOTargetInfo>::iterator ighit= m_UniqueGOTargetInfo.begin();ighit != m_UniqueGOTargetInfo.end();++ighit) for(std::list<GOTargetInfo>::iterator ighit= m_UniqueGOTargetInfo.begin();ighit != m_UniqueGOTargetInfo.end();++ighit)
*data << uint64(ighit->targetGUID); // Always hits *data << uint64(ighit->targetGUID); // Always hits
*data << (uint8)m_countOfMiss; *data << (uint8)miss;
for(std::list<TargetInfo>::iterator ihit= m_UniqueTargetInfo.begin();ihit != m_UniqueTargetInfo.end();++ihit) for(std::list<TargetInfo>::iterator ihit= m_UniqueTargetInfo.begin();ihit != m_UniqueTargetInfo.end();++ihit)
{ {
if( ihit->missCondition != SPELL_MISS_NONE ) // Add only miss if( ihit->missCondition != SPELL_MISS_NONE ) // Add only miss
@ -3080,7 +3088,7 @@ void Spell::SendLogExecute()
data << uint8(0); data << uint8(0);
break; break;
case SPELL_EFFECT_CREATE_ITEM: case SPELL_EFFECT_CREATE_ITEM:
case SPELL_EFFECT_157: case SPELL_EFFECT_CREATE_ITEM_2:
data << uint32(m_spellInfo->EffectItemType[0]); data << uint32(m_spellInfo->EffectItemType[0]);
break; break;
case SPELL_EFFECT_SUMMON: case SPELL_EFFECT_SUMMON:
@ -3513,16 +3521,11 @@ void Spell::HandleEffects(Unit *pUnitTarget,Item *pItemTarget,GameObject *pGOTar
gameObjTarget = pGOTarget; gameObjTarget = pGOTarget;
uint8 eff = m_spellInfo->Effect[i]; uint8 eff = m_spellInfo->Effect[i];
uint32 mechanic = m_spellInfo->EffectMechanic[i];
damage = int32(CalculateDamage((uint8)i,unitTarget)*DamageMultiplier); damage = int32(CalculateDamage((uint8)i,unitTarget)*DamageMultiplier);
sLog.outDebug( "Spell: Effect : %u", eff); 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(eff<TOTAL_SPELL_EFFECTS) if(eff<TOTAL_SPELL_EFFECTS)
{ {
//sLog.outDebug( "WORLD: Spell FX %d < TOTAL_SPELL_EFFECTS ", eff); //sLog.outDebug( "WORLD: Spell FX %d < TOTAL_SPELL_EFFECTS ", eff);
@ -3655,6 +3658,20 @@ uint8 Spell::CanCast(bool strict)
} }
} }
} }
else if (m_caster->GetTypeId()==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 // check pet presents
for(int j=0;j<3;j++) for(int j=0;j<3;j++)

View file

@ -321,7 +321,7 @@ class Spell
Spell( Unit* Caster, SpellEntry const *info, bool triggered, uint64 originalCasterGUID = 0, Spell** triggeringContainer = NULL ); Spell( Unit* Caster, SpellEntry const *info, bool triggered, uint64 originalCasterGUID = 0, Spell** triggeringContainer = NULL );
~Spell(); ~Spell();
void prepare(SpellCastTargets * targets, Aura* triggeredByAura = NULL); void prepare(SpellCastTargets const* targets, Aura* triggeredByAura = NULL);
void cancel(); void cancel();
void update(uint32 difftime); void update(uint32 difftime);
void cast(bool skipCheck = false); void cast(bool skipCheck = false);
@ -354,11 +354,10 @@ class Spell
bool HaveTargetsForEffect(uint8 effect) const; bool HaveTargetsForEffect(uint8 effect) const;
void Delayed(); void Delayed();
void DelayedChannel(); void DelayedChannel();
inline uint32 getState() const { return m_spellState; } uint32 getState() const { return m_spellState; }
void setState(uint32 state) { m_spellState = state; } void setState(uint32 state) { m_spellState = state; }
void DoCreateItem(uint32 i, uint32 itemtype); void DoCreateItem(uint32 i, uint32 itemtype);
void WriteSpellGoTargets( WorldPacket * data ); void WriteSpellGoTargets( WorldPacket * data );
void WriteAmmoToPacket( WorldPacket * data ); void WriteAmmoToPacket( WorldPacket * data );
void FillTargetMap(); void FillTargetMap();
@ -497,8 +496,6 @@ class Spell
// Spell target subsystem // Spell target subsystem
//***************************************** //*****************************************
// Targets store structures and data // Targets store structures and data
uint32 m_countOfHit;
uint32 m_countOfMiss;
struct TargetInfo struct TargetInfo
{ {
uint64 targetGUID; uint64 targetGUID;

View file

@ -187,8 +187,8 @@ enum AuraType
SPELL_AURA_MOD_BASE_RESISTANCE_PCT = 142, SPELL_AURA_MOD_BASE_RESISTANCE_PCT = 142,
SPELL_AURA_MOD_RESISTANCE_EXCLUSIVE = 143, SPELL_AURA_MOD_RESISTANCE_EXCLUSIVE = 143,
SPELL_AURA_SAFE_FALL = 144, SPELL_AURA_SAFE_FALL = 144,
SPELL_AURA_CHARISMA = 145, SPELL_AURA_MOD_PET_TALENT_POINTS = 145,
SPELL_AURA_PERSUADED = 146, SPELL_AURA_ALLOW_TAME_PET_TYPE = 146,
SPELL_AURA_ADD_CREATURE_IMMUNITY = 147, SPELL_AURA_ADD_CREATURE_IMMUNITY = 147,
SPELL_AURA_RETAIN_COMBO_POINTS = 148, SPELL_AURA_RETAIN_COMBO_POINTS = 148,
SPELL_AURA_RESIST_PUSHBACK = 149, // Resist Pushback SPELL_AURA_RESIST_PUSHBACK = 149, // Resist Pushback
@ -313,7 +313,7 @@ enum AuraType
SPELL_AURA_MOD_ATTACK_POWER_OF_STAT_PERCENT = 268, SPELL_AURA_MOD_ATTACK_POWER_OF_STAT_PERCENT = 268,
SPELL_AURA_269 = 269, SPELL_AURA_269 = 269,
SPELL_AURA_270 = 270, SPELL_AURA_270 = 270,
SPELL_AURA_271 = 271, SPELL_AURA_MOD_DAMAGE_FROM_CASTER = 271,
SPELL_AURA_272 = 272, SPELL_AURA_272 = 272,
SPELL_AURA_273 = 273, SPELL_AURA_273 = 273,
SPELL_AURA_274 = 274, SPELL_AURA_274 = 274,

View file

@ -195,8 +195,8 @@ pAuraHandler AuraHandler[TOTAL_AURAS]=
&Aura::HandleAuraModBaseResistancePCT, //142 SPELL_AURA_MOD_BASE_RESISTANCE_PCT &Aura::HandleAuraModBaseResistancePCT, //142 SPELL_AURA_MOD_BASE_RESISTANCE_PCT
&Aura::HandleAuraModResistanceExclusive, //143 SPELL_AURA_MOD_RESISTANCE_EXCLUSIVE &Aura::HandleAuraModResistanceExclusive, //143 SPELL_AURA_MOD_RESISTANCE_EXCLUSIVE
&Aura::HandleNoImmediateEffect, //144 SPELL_AURA_SAFE_FALL implemented in WorldSession::HandleMovementOpcodes &Aura::HandleNoImmediateEffect, //144 SPELL_AURA_SAFE_FALL implemented in WorldSession::HandleMovementOpcodes
&Aura::HandleUnused, //145 SPELL_AURA_CHARISMA obsolete? &Aura::HandleAuraModPetTalentsPoints, //145 SPELL_AURA_MOD_PET_TALENT_POINTS
&Aura::HandleUnused, //146 SPELL_AURA_PERSUADED obsolete? &Aura::HandleNoImmediateEffect, //146 SPELL_AURA_ALLOW_TAME_PET_TYPE
&Aura::HandleNULL, //147 SPELL_AURA_ADD_CREATURE_IMMUNITY &Aura::HandleNULL, //147 SPELL_AURA_ADD_CREATURE_IMMUNITY
&Aura::HandleAuraRetainComboPoints, //148 SPELL_AURA_RETAIN_COMBO_POINTS &Aura::HandleAuraRetainComboPoints, //148 SPELL_AURA_RETAIN_COMBO_POINTS
&Aura::HandleNoImmediateEffect, //149 SPELL_AURA_RESIST_PUSHBACK &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::HandleAuraModAttackPowerOfStatPercent, //268 SPELL_AURA_MOD_ATTACK_POWER_OF_STAT_PERCENT
&Aura::HandleNULL, //269 ignore DR effects? &Aura::HandleNULL, //269 ignore DR effects?
&Aura::HandleNULL, //270 &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, //272 reduce spell cast time?
&Aura::HandleNULL, //273 &Aura::HandleNULL, //273
&Aura::HandleNULL, //274 proc free shot? &Aura::HandleNULL, //274 proc free shot?
@ -941,10 +941,6 @@ void Aura::_AddAura()
break; break;
} }
// register aura
if (getDiminishGroup() != DIMINISHING_NONE )
m_target->ApplyDiminishingAura(getDiminishGroup(),true);
Unit* caster = GetCaster(); Unit* caster = GetCaster();
// passive auras (except totem auras) do not get placed in the slots // passive auras (except totem auras) do not get placed in the slots
@ -967,8 +963,12 @@ void Aura::_AddAura()
//***************************************************** //*****************************************************
if (!secondaura) if (!secondaura)
{ {
// register aura diminishing on apply
if (getDiminishGroup() != DIMINISHING_NONE )
m_target->ApplyDiminishingAura(getDiminishGroup(),true);
// Update Seals information // Update Seals information
if( IsSealSpell(GetSpellProto()) ) if (IsSealSpell(m_spellProto))
m_target->ModifyAuraState(AURA_STATE_JUDGEMENT, true); m_target->ModifyAuraState(AURA_STATE_JUDGEMENT, true);
// Conflagrate aura state on Immolate // Conflagrate aura state on Immolate
@ -1010,10 +1010,6 @@ void Aura::_RemoveAura()
dynObj->RemoveAffected(m_target); dynObj->RemoveAffected(m_target);
} }
// unregister aura
if (getDiminishGroup() != DIMINISHING_NONE )
m_target->ApplyDiminishingAura(getDiminishGroup(),false);
//passive auras do not get put in slots //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) // 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())) //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) // only remove icon when the last aura of the spell is removed (current aura already removed from list)
if (lastaura) if (lastaura)
{ {
// unregister aura diminishing (and store last time)
if (getDiminishGroup() != DIMINISHING_NONE )
m_target->ApplyDiminishingAura(getDiminishGroup(),false);
SetAura(true); SetAura(true);
SetAuraFlags(AFLAG_NONE); SetAuraFlags(AFLAG_NONE);
SetAuraLevel(0); SetAuraLevel(0);
@ -1058,59 +1058,55 @@ void Aura::_RemoveAura()
//***************************************************** //*****************************************************
// Update target aura state flag (at last aura remove) // Update target aura state flag (at last aura remove)
// TODO: Make it easer
//***************************************************** //*****************************************************
// Update Seals information uint32 removeState = 0;
if( IsSealSpell(GetSpellProto()) ) switch(m_spellProto->SpellFamilyName)
m_target->ModifyAuraState(AURA_STATE_JUDGEMENT,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)
// Conflagrate aura state }
if (GetSpellProto()->SpellFamilyName == SPELLFAMILY_WARLOCK && (GetSpellProto()->SpellFamilyFlags & 4)) // Remove state (but need check other auras for it)
m_target->ModifyAuraState(AURA_STATE_IMMOLATE, false); if (removeState)
// 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)
{ {
bool found = false; bool found = false;
Unit::AuraList const& RejorRegr = m_target->GetAurasByType(SPELL_AURA_PERIODIC_HEAL); Unit::AuraMap& Auras = m_target->GetAuras();
for(Unit::AuraList::const_iterator i = RejorRegr.begin(); i != RejorRegr.end(); ++i) for(Unit::AuraMap::iterator i = Auras.begin(); i != Auras.end(); ++i)
{ {
if((*i)->GetSpellProto()->SpellFamilyName == SPELLFAMILY_DRUID && (*i)->GetSpellProto()->SpellFamilyFlags & 0x50 ) SpellEntry const *auraSpellInfo = (*i).second->GetSpellProto();
if(auraSpellInfo->SpellFamilyName == m_spellProto->SpellFamilyName &&
auraSpellInfo->SpellFamilyFlags == m_spellProto->SpellFamilyFlags )
{ {
found = true; found = true;
break; break;
} }
} }
// this has been last aura
if(!found) if(!found)
m_target->ModifyAuraState(AURA_STATE_SWIFTMEND, false); m_target->ModifyAuraState(AuraState(removeState), false);
}
// Deadly poison aura state
if(m_spellProto->SpellFamilyName == SPELLFAMILY_ROGUE && m_spellProto->SpellFamilyFlags & 0x10000)
{
// 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)
{
SpellEntry const* itr_spell = (*itr)->GetSpellProto();
if(itr_spell && itr_spell->SpellFamilyName==SPELLFAMILY_ROGUE && itr_spell->SpellFamilyFlags & 0x10000)
{
found = true;
break;
}
}
// this has been last deadly poison aura
if(!found)
m_target->ModifyAuraState(AURA_STATE_DEADLY_POISON,false);
} }
// reset cooldown state for spells // reset cooldown state for spells
@ -2085,7 +2081,7 @@ void Aura::HandleAuraDummy(bool apply, bool Real)
( GetSpellProto()->EffectApplyAuraName[0]==1 || GetSpellProto()->EffectApplyAuraName[0]==128 ) ) ) ( GetSpellProto()->EffectApplyAuraName[0]==1 || GetSpellProto()->EffectApplyAuraName[0]==128 ) ) )
{ {
// spells with SpellEffect=72 and aura=4: 6196, 6197, 21171, 21425 // 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); WorldPacket data(SMSG_CLEAR_FAR_SIGHT_IMMEDIATE, 0);
((Player*)m_target)->GetSession()->SendPacket(&data); ((Player*)m_target)->GetSession()->SendPacket(&data);
return; return;
@ -2499,12 +2495,8 @@ void Aura::HandleAuraHover(bool apply, bool Real)
void Aura::HandleWaterBreathing(bool apply, bool Real) void Aura::HandleWaterBreathing(bool apply, bool Real)
{ {
if(apply) if(!apply && !m_target->HasAuraType(SPELL_AURA_WATER_BREATHING))
m_target->waterbreath = true;
else if(m_target->GetAurasByType(SPELL_AURA_WATER_BREATHING).empty())
{ {
m_target->waterbreath = false;
// update for enable timer in case not moving target // update for enable timer in case not moving target
if(m_target->GetTypeId()==TYPEID_PLAYER && m_target->IsInWorld()) 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) if(!caster || caster->GetTypeId() != TYPEID_PLAYER)
return; return;
((Player*)caster)->SetFarSight(apply ? m_target->GetGUID() : NULL); ((Player*)caster)->SetFarSightGUID(apply ? m_target->GetGUID() : 0);
} }
void Aura::HandleFarSight(bool apply, bool Real) void Aura::HandleFarSight(bool apply, bool Real)
@ -2984,7 +2976,7 @@ void Aura::HandleFarSight(bool apply, bool Real)
if(!caster || caster->GetTypeId() != TYPEID_PLAYER) if(!caster || caster->GetTypeId() != TYPEID_PLAYER)
return; return;
((Player*)caster)->SetFarSight(apply ? m_target->GetGUID() : NULL); ((Player*)caster)->SetFarSightGUID(apply ? m_target->GetGUID() : 0);
} }
void Aura::HandleAuraTrackCreatures(bool apply, bool Real) void Aura::HandleAuraTrackCreatures(bool apply, bool Real)
@ -3091,7 +3083,7 @@ void Aura::HandleModPossess(bool apply, bool Real)
} }
} }
if(caster->GetTypeId() == TYPEID_PLAYER) 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) void Aura::HandleModPossessPet(bool apply, bool Real)
@ -3108,11 +3100,11 @@ void Aura::HandleModPossessPet(bool apply, bool Real)
return; return;
if(apply) if(apply)
pet->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_UNKNOWN5); pet->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_UNK_24);
else 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)->SetCharm(apply ? pet : NULL);
((Player*)caster)->SetClientControl(pet, apply ? 1 : 0); ((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) void Aura::HandleModCharm(bool apply, bool Real)
{ {
if(!Real) if(!Real)
@ -3271,7 +3273,7 @@ void Aura::HandleFeignDeath(bool apply, bool Real)
m_target->SendMessageToSet(&data,true); m_target->SendMessageToSet(&data,true);
*/ */
// blizz like 2.0.x // 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 // blizz like 2.0.x
m_target->SetFlag(UNIT_FIELD_FLAGS_2, UNIT_FLAG2_FEIGN_DEATH); m_target->SetFlag(UNIT_FIELD_FLAGS_2, UNIT_FLAG2_FEIGN_DEATH);
// blizz like 2.0.x // blizz like 2.0.x
@ -3295,7 +3297,7 @@ void Aura::HandleFeignDeath(bool apply, bool Real)
m_target->SendMessageToSet(&data,true); m_target->SendMessageToSet(&data,true);
*/ */
// blizz like 2.0.x // 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 // blizz like 2.0.x
m_target->RemoveFlag(UNIT_FIELD_FLAGS_2, UNIT_FLAG2_FEIGN_DEATH); m_target->RemoveFlag(UNIT_FIELD_FLAGS_2, UNIT_FLAG2_FEIGN_DEATH);
// blizz like 2.0.x // 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_NO_DETECT);
m_target->SetVisibility(VISIBILITY_GROUP_STEALTH); 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 else
@ -3444,10 +3442,6 @@ void Aura::HandleModStealth(bool apply, bool Real)
// only at real aura remove // only at real aura remove
if(Real) 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 last SPELL_AURA_MOD_STEALTH and no GM invisibility
if(!m_target->HasAuraType(SPELL_AURA_MOD_STEALTH) && m_target->GetVisibility()!=VISIBILITY_OFF) if(!m_target->HasAuraType(SPELL_AURA_MOD_STEALTH) && m_target->GetVisibility()!=VISIBILITY_OFF)
{ {
@ -6559,7 +6553,7 @@ void Aura::PeriodicDummyTick()
if (!caster) if (!caster)
return; return;
// Skip 0 tick // Skip 0 tick
if (m_duration < m_modifier.periodictime) if (m_duration > m_modifier.periodictime)
return; return;
int32 damage = caster->CalculateSpellDamage(spell, GetEffIndex(), GetBasePoints(), m_target); int32 damage = caster->CalculateSpellDamage(spell, GetEffIndex(), GetBasePoints(), m_target);
damage+=caster->GetTotalAttackPowerValue(RANGED_ATTACK) * 8 / 100; damage+=caster->GetTotalAttackPowerValue(RANGED_ATTACK) * 8 / 100;

View file

@ -112,6 +112,7 @@ class MANGOS_DLL_SPEC Aura
void HandlePeriodicTriggerSpell(bool Apply, bool Real); void HandlePeriodicTriggerSpell(bool Apply, bool Real);
void HandlePeriodicEnergize(bool Apply, bool Real); void HandlePeriodicEnergize(bool Apply, bool Real);
void HandleAuraModResistanceExclusive(bool Apply, bool Real); void HandleAuraModResistanceExclusive(bool Apply, bool Real);
void HandleAuraModPetTalentsPoints(bool Apply, bool Real);
void HandleModStealth(bool Apply, bool Real); void HandleModStealth(bool Apply, bool Real);
void HandleInvisibility(bool Apply, bool Real); void HandleInvisibility(bool Apply, bool Real);
void HandleInvisibilityDetect(bool Apply, bool Real); void HandleInvisibilityDetect(bool Apply, bool Real);

View file

@ -54,6 +54,7 @@
#include "Util.h" #include "Util.h"
#include "TemporarySummon.h" #include "TemporarySummon.h"
#include "ScriptCalls.h" #include "ScriptCalls.h"
#include "SkillDiscovery.h"
pEffect SpellEffects[TOTAL_SPELL_EFFECTS]= pEffect SpellEffects[TOTAL_SPELL_EFFECTS]=
{ {
@ -214,7 +215,7 @@ pEffect SpellEffects[TOTAL_SPELL_EFFECTS]=
&Spell::EffectNULL, //154 unused &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::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, //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::EffectMilling, //158 milling
&Spell::EffectNULL //159 allow rename pet once again &Spell::EffectNULL //159 allow rename pet once again
}; };
@ -491,7 +492,7 @@ void Spell::EffectSchoolDMG(uint32 effect_idx)
Aura *poison = 0; Aura *poison = 0;
// Lookup for Deadly poison (only attacker applied) // Lookup for Deadly poison (only attacker applied)
Unit::AuraList const& auras = unitTarget->GetAurasByType(SPELL_AURA_PERIODIC_DAMAGE); 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 && if( (*itr)->GetSpellProto()->SpellFamilyName==SPELLFAMILY_ROGUE &&
(*itr)->GetSpellProto()->SpellFamilyFlags & 0x10000 && (*itr)->GetSpellProto()->SpellFamilyFlags & 0x10000 &&
(*itr)->GetCasterGUID()==m_caster->GetGUID() ) (*itr)->GetCasterGUID()==m_caster->GetGUID() )
@ -721,12 +722,6 @@ void Spell::EffectDummy(uint32 i)
m_caster->CastCustomSpell(unitTarget, 12721, &deepWoundsDotBasePoints0, NULL, NULL, true, NULL); m_caster->CastCustomSpell(unitTarget, 12721, &deepWoundsDotBasePoints0, NULL, NULL, true, NULL);
return; 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 case 13120: // net-o-matic
{ {
if(!unitTarget) if(!unitTarget)
@ -763,30 +758,6 @@ void Spell::EffectDummy(uint32 i)
} }
return; 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 15998: // Capture Worg Pup
case 29435: // Capture Female Kaliri Hatchling case 29435: // Capture Female Kaliri Hatchling
{ {
@ -881,7 +852,7 @@ void Spell::EffectDummy(uint32 i)
return; return;
} }
case 23074: // Arc. Dragonling case 23074: // Arcanite Dragonling
if (!m_CastItem) return; if (!m_CastItem) return;
m_caster->CastSpell(m_caster,19804,true,m_CastItem); m_caster->CastSpell(m_caster,19804,true,m_CastItem);
return; return;
@ -1289,19 +1260,35 @@ void Spell::EffectDummy(uint32 i)
if(!unitTarget) if(!unitTarget)
return; 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->CastCustomSpell(unitTarget, 20647, &basePoints0, NULL, NULL, true, 0);
m_caster->SetPower(POWER_RAGE,0); m_caster->SetPower(POWER_RAGE,0);
return; return;
} }
if(m_spellInfo->Id==21977) //Warrior's Wrath switch(m_spellInfo->Id)
{
// Warrior's Wrath
case 21977:
{ {
if(!unitTarget) if(!unitTarget)
return; return;
m_caster->CastSpell(unitTarget,21887,true); // spell mod m_caster->CastSpell(unitTarget,21887,true); // spell mod
return; 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; break;
case SPELLFAMILY_WARLOCK: case SPELLFAMILY_WARLOCK:
// Life Tap // Life Tap
@ -1425,11 +1412,6 @@ void Spell::EffectDummy(uint32 i)
case SPELLFAMILY_ROGUE: case SPELLFAMILY_ROGUE:
switch(m_spellInfo->Id ) switch(m_spellInfo->Id )
{ {
case 31231: // Cheat Death
{
m_caster->CastSpell(m_caster,45182,true);
return;
}
case 5938: // Shiv case 5938: // Shiv
{ {
if(m_caster->GetTypeId() != TYPEID_PLAYER) if(m_caster->GetTypeId() != TYPEID_PLAYER)
@ -1465,6 +1447,35 @@ void Spell::EffectDummy(uint32 i)
m_caster->CastSpell(unitTarget, 5940, true); m_caster->CastSpell(unitTarget, 5940, true);
return; 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; break;
case SPELLFAMILY_HUNTER: case SPELLFAMILY_HUNTER:
@ -1598,6 +1609,14 @@ void Spell::EffectDummy(uint32 i)
switch(m_spellInfo->Id) 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) case 31789: // Righteous Defense (step 1)
{ {
// 31989 -> dummy effect (step 1) + dummy effect (step 2) -> 31709 (taunt like spell for each target) // 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) if(!unitTarget)
return; 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) // 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 && if( !unitTarget->isAlive() && m_spellInfo->Id != 20584 && m_spellInfo->Id != 8326 &&
(unitTarget->GetTypeId()!=TYPEID_PLAYER || !((Player*)unitTarget)->GetSession()->PlayerLoading()) ) (unitTarget->GetTypeId()!=TYPEID_PLAYER || !((Player*)unitTarget)->GetSession()->PlayerLoading()) )
@ -2815,7 +2829,7 @@ void Spell::EffectEnergisePct(uint32 i)
uint32 gain = damage * maxPower / 100; uint32 gain = damage * maxPower / 100;
unitTarget->ModifyPower(power, gain); 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) void Spell::SendLoot(uint64 guid, LootType loottype)
@ -3551,7 +3565,7 @@ void Spell::EffectAddFarsight(uint32 i)
m_caster->AddDynObject(dynObj); m_caster->AddDynObject(dynObj);
dynObj->GetMap()->Add(dynObj); dynObj->GetMap()->Add(dynObj);
if(m_caster->GetTypeId() == TYPEID_PLAYER) if(m_caster->GetTypeId() == TYPEID_PLAYER)
((Player*)m_caster)->SetFarSight(dynObj->GetGUID()); ((Player*)m_caster)->SetFarSightGUID(dynObj->GetGUID());
} }
void Spell::EffectSummonWild(uint32 i) void Spell::EffectSummonWild(uint32 i)
@ -3797,9 +3811,9 @@ void Spell::EffectEnchantItemPerm(uint32 i)
p_caster->UpdateCraftSkill(m_spellInfo->Id); p_caster->UpdateCraftSkill(m_spellInfo->Id);
if (m_spellInfo->EffectMiscValue[i])
{
uint32 enchant_id = m_spellInfo->EffectMiscValue[i]; uint32 enchant_id = m_spellInfo->EffectMiscValue[i];
if (!enchant_id)
return;
SpellItemEnchantmentEntry const *pEnchant = sSpellItemEnchantmentStore.LookupEntry(enchant_id); SpellItemEnchantmentEntry const *pEnchant = sSpellItemEnchantmentStore.LookupEntry(enchant_id);
if(!pEnchant) if(!pEnchant)
@ -3826,7 +3840,6 @@ void Spell::EffectEnchantItemPerm(uint32 i)
// add new enchanting if equipped // add new enchanting if equipped
item_owner->ApplyEnchantment(itemTarget,PERM_ENCHANTMENT_SLOT,true); item_owner->ApplyEnchantment(itemTarget,PERM_ENCHANTMENT_SLOT,true);
} }
}
void Spell::EffectEnchantItemTmp(uint32 i) void Spell::EffectEnchantItemTmp(uint32 i)
{ {
@ -4139,6 +4152,7 @@ void Spell::EffectSummonPet(uint32 i)
NewSummon->InitStatsForLevel(petlevel); NewSummon->InitStatsForLevel(petlevel);
NewSummon->InitPetCreateSpells(); NewSummon->InitPetCreateSpells();
NewSummon->InitTalentForLevel();
if(NewSummon->getPetType()==SUMMON_PET) if(NewSummon->getPetType()==SUMMON_PET)
{ {
@ -4587,41 +4601,29 @@ void Spell::EffectScriptEffect(uint32 effIndex)
{ {
// TODO: we must implement hunter pet summon at login there (spell 6962) // TODO: we must implement hunter pet summon at login there (spell 6962)
// by spell id switch(m_spellInfo->SpellFamilyName)
{
case SPELLFAMILY_GENERIC:
{
switch(m_spellInfo->Id) switch(m_spellInfo->Id)
{ {
// PX-238 Winter Wondervolt TRAP // PX-238 Winter Wondervolt TRAP
case 26275: case 26275:
{ {
if( unitTarget->HasAura(26272,0) uint32 spells[4] = { 26272, 26157, 26273, 26274 };
|| unitTarget->HasAura(26157,0)
|| unitTarget->HasAura(26273,0) // check presence
|| unitTarget->HasAura(26274,0)) for(int j = 0; j < 4; ++j)
if(unitTarget->HasAura(spells[j],0))
return; return;
uint32 iTmpSpellId; // select spell
uint32 iTmpSpellId = spells[urand(0,3)];
switch(urand(0,3))
{
case 0:
iTmpSpellId = 26272;
break;
case 1:
iTmpSpellId = 26157;
break;
case 2:
iTmpSpellId = 26273;
break;
case 3:
iTmpSpellId = 26274;
break;
}
// cast
unitTarget->CastSpell(unitTarget, iTmpSpellId, true); unitTarget->CastSpell(unitTarget, iTmpSpellId, true);
return; return;
} }
// Bending Shinbone // Bending Shinbone
case 8856: case 8856:
{ {
@ -4638,61 +4640,6 @@ void Spell::EffectScriptEffect(uint32 effIndex)
m_caster->CastSpell(m_caster,spell_id,true,NULL); m_caster->CastSpell(m_caster,spell_id,true,NULL);
return; 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 // Brittle Armor - need remove one 24575 Brittle Armor aura
case 24590: case 24590:
unitTarget->RemoveSingleSpellAurasFromStack(24575); unitTarget->RemoveSingleSpellAurasFromStack(24575);
@ -4732,7 +4679,6 @@ void Spell::EffectScriptEffect(uint32 effIndex)
unitTarget->CastSpell(unitTarget,spellid,false); unitTarget->CastSpell(unitTarget,spellid,false);
return; return;
} }
// Shadow Flame (All script effects, not just end ones to prevent player from dodging the last triggered spell) // Shadow Flame (All script effects, not just end ones to prevent player from dodging the last triggered spell)
case 22539: case 22539:
case 22972: case 22972:
@ -4759,8 +4705,6 @@ void Spell::EffectScriptEffect(uint32 effIndex)
m_caster->CastSpell(unitTarget, 22682, true); m_caster->CastSpell(unitTarget, 22682, true);
return; return;
} }
break;
// Summon Black Qiraji Battle Tank // Summon Black Qiraji Battle Tank
case 26656: case 26656:
{ {
@ -4785,59 +4729,18 @@ void Spell::EffectScriptEffect(uint32 effIndex)
unitTarget->HandleEmoteCommand(EMOTE_STATE_DANCE); unitTarget->HandleEmoteCommand(EMOTE_STATE_DANCE);
break; 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 // Mirren's Drinking Hat
case 29830: case 29830:
{ {
uint32 item = 0; uint32 item = 0;
switch ( urand(1,6) ) switch ( urand(1,6) )
{ {
case 1: case 2: case 3: item = 23584; break;// Loch Modan Lager case 1:case 2:case 3:
case 4: case 5: item = 23585; break;// Stouthammer Lite item = 23584;break; // Loch Modan Lager
case 6: item = 23586; break;// Aerie Peak Pale Ale case 4:case 5:
item = 23585;break; // Stouthammer Lite
case 6:
item = 23586;break; // Aerie Peak Pale Ale
} }
if (item) if (item)
DoCreateItem(effIndex,item); DoCreateItem(effIndex,item);
@ -4869,7 +4772,8 @@ void Spell::EffectScriptEffect(uint32 effIndex)
} }
break; break;
} }
case 41126: // Flame Crash // Flame Crash
case 41126:
{ {
if(!unitTarget) if(!unitTarget)
return; return;
@ -4877,7 +4781,8 @@ void Spell::EffectScriptEffect(uint32 effIndex)
unitTarget->CastSpell(unitTarget, 41131, true); unitTarget->CastSpell(unitTarget, 41131, true);
break; break;
} }
case 44876: // Force Cast - Portal Effect: Sunwell Isle // Force Cast - Portal Effect: Sunwell Isle
case 44876:
{ {
if(!unitTarget) if(!unitTarget)
return; return;
@ -4885,7 +4790,6 @@ void Spell::EffectScriptEffect(uint32 effIndex)
unitTarget->CastSpell(unitTarget, 44870, true); unitTarget->CastSpell(unitTarget, 44870, true);
break; break;
} }
// Goblin Weather Machine // Goblin Weather Machine
case 46203: case 46203:
{ {
@ -4895,18 +4799,10 @@ void Spell::EffectScriptEffect(uint32 effIndex)
uint32 spellId; uint32 spellId;
switch(rand()%4) switch(rand()%4)
{ {
case 0: case 0: spellId = 46740; break;
spellId=46740; case 1: spellId = 46739; break;
break; case 2: spellId = 46738; break;
case 1: case 3: spellId = 46736; break;
spellId=46739;
break;
case 2:
spellId=46738;
break;
case 3:
spellId=46736;
break;
} }
unitTarget->CastSpell(unitTarget, spellId, true); unitTarget->CastSpell(unitTarget, spellId, true);
break; break;
@ -4921,6 +4817,7 @@ void Spell::EffectScriptEffect(uint32 effIndex)
break; break;
} }
// Emblazon Runeblade
case 51770: case 51770:
{ {
if(!unitTarget) if(!unitTarget)
@ -4929,8 +4826,122 @@ void Spell::EffectScriptEffect(uint32 effIndex)
unitTarget->CastSpell(unitTarget,51771,false); unitTarget->CastSpell(unitTarget,51771,false);
break; 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;
} }
if( m_spellInfo->SpellFamilyName == SPELLFAMILY_HUNTER ) // 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) switch(m_spellInfo->Id)
{ {
@ -4981,63 +4992,98 @@ void Spell::EffectScriptEffect(uint32 effIndex)
default: default:
break; break;
} }
break;
} }
else if( m_spellInfo->SpellFamilyName == SPELLFAMILY_PALADIN ) case SPELLFAMILY_PALADIN:
{
switch(m_spellInfo->SpellFamilyFlags)
{ {
// Judgement // Judgement
case 0x800000: if (m_spellInfo->SpellFamilyFlags & 0x0000000000800000LL)
{ {
if(!unitTarget || !unitTarget->isAlive()) if(!unitTarget || !unitTarget->isAlive())
return; return;
uint32 spellId1 = 0;
uint32 spellId2 = 0; uint32 spellId2 = 0;
// all seals have aura dummy // 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); 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) for(Unit::AuraList::const_iterator itr = m_dummyAuras.begin(); itr != m_dummyAuras.end(); ++itr)
{ {
SpellEntry const *spellInfo = (*itr)->GetSpellProto(); SpellEntry const *spellInfo = (*itr)->GetSpellProto();
// search seal (all seals have judgement's aura dummy spell id in 2 effect // search seal (all seals have judgement's aura dummy spell id in 2 effect
if ( !spellInfo || !IsSealSpell((*itr)->GetSpellProto()) || (*itr)->GetEffIndex() != 2 ) if ((*itr)->GetEffIndex() != 2 || !spellInfo || !IsSealSpell(spellInfo))
continue; continue;
spellId2 = (*itr)->GetModifier()->m_amount;
// must be calculated base at raw base points in spell proto, GetModifier()->m_value for S.Righteousness modified by SPELLMOD_DAMAGE SpellEntry const *judge = sSpellStore.LookupEntry(spellId2);
spellId2 = (*itr)->GetSpellProto()->EffectBasePoints[2]+1; if (!judge)
if(spellId2 <= 1)
continue; 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)
{
if ((*i)->GetSpellProto()->SpellIconID == 205 && (*i)->GetSpellProto()->Attributes == 0x01D0LL)
{
int32 chance = (*i)->GetModifier()->m_amount;
if ( roll_chance_i(chance) )
{
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);
}
break; break;
} }
} if (spellId1)
m_caster->CastSpell(unitTarget, spellId1, true);
break; if (spellId2)
}
m_caster->CastSpell(unitTarget, spellId2, true); m_caster->CastSpell(unitTarget, spellId2, true);
return; 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;
}
// 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;
}
} }
// normal DB scripted effect // normal DB scripted effect
@ -5340,9 +5386,6 @@ void Spell::EffectSummonTotem(uint32 i)
if(m_caster->GetTypeId() == TYPEID_PLAYER) if(m_caster->GetTypeId() == TYPEID_PLAYER)
pTotem->SetFlag(UNIT_FIELD_FLAGS,UNIT_FLAG_PVP_ATTACKABLE); 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); pTotem->Summon(m_caster);
if(slot < MAX_TOTEM && m_caster->GetTypeId() == TYPEID_PLAYER) if(slot < MAX_TOTEM && m_caster->GetTypeId() == TYPEID_PLAYER)

View file

@ -125,59 +125,7 @@ void WorldSession::HandleUseItemOpcode(WorldPacket& recvPacket)
if(!Script->ItemUse(pUser,pItem,targets)) if(!Script->ItemUse(pUser,pItem,targets))
{ {
// no script or script not process request by self // no script or script not process request by self
pUser->CastItemUseSpell(pItem,targets,cast_count,glyphIndex);
// 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;
}
} }
} }

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