aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--contrib/extractor/ad.exebin163840 -> 162816 bytes
-rw-r--r--sql/characters.sql4
-rw-r--r--sql/updates/3.2.2a_characters_update.sql31
-rw-r--r--sql/updates/3.2.2a_world_update.sql140
-rw-r--r--sql/world.sql25
-rw-r--r--src/bindings/scripts/scripts/eastern_kingdoms/stormwind_city.cpp6
-rw-r--r--src/game/AchievementMgr.cpp11
-rw-r--r--src/game/AchievementMgr.h4
-rw-r--r--src/game/ArenaTeam.cpp99
-rw-r--r--src/game/ArenaTeamHandler.cpp40
-rw-r--r--src/game/BattleGround.cpp46
-rw-r--r--src/game/BattleGround.h33
-rw-r--r--src/game/BattleGroundAB.cpp4
-rw-r--r--src/game/BattleGroundAB.h4
-rw-r--r--src/game/BattleGroundABG.cpp81
-rw-r--r--src/game/BattleGroundABG.h54
-rw-r--r--src/game/BattleGroundBE.cpp10
-rw-r--r--src/game/BattleGroundBE.h1
-rw-r--r--src/game/BattleGroundDS.cpp105
-rw-r--r--src/game/BattleGroundDS.h39
-rw-r--r--src/game/BattleGroundHandler.cpp7
-rw-r--r--src/game/BattleGroundIC.cpp81
-rw-r--r--src/game/BattleGroundIC.h54
-rw-r--r--src/game/BattleGroundMgr.cpp52
-rw-r--r--src/game/BattleGroundMgr.h1
-rw-r--r--src/game/BattleGroundNA.cpp12
-rw-r--r--src/game/BattleGroundNA.h1
-rw-r--r--src/game/BattleGroundRL.cpp12
-rw-r--r--src/game/BattleGroundRL.h1
-rw-r--r--src/game/BattleGroundRV.cpp15
-rw-r--r--src/game/BattleGroundRV.h4
-rw-r--r--src/game/BattleGroundWS.cpp30
-rw-r--r--src/game/BattleGroundWS.h4
-rw-r--r--src/game/CMakeLists.txt4
-rw-r--r--src/game/CalendarHandler.cpp2
-rw-r--r--src/game/Channel.cpp18
-rw-r--r--src/game/CharacterHandler.cpp45
-rw-r--r--src/game/Chat.cpp83
-rw-r--r--src/game/Chat.h3
-rw-r--r--src/game/Creature.cpp28
-rw-r--r--src/game/Creature.h5
-rw-r--r--src/game/CreatureEventAI.cpp5
-rw-r--r--src/game/CreatureEventAI.h10
-rw-r--r--src/game/CreatureEventAIMgr.cpp8
-rw-r--r--src/game/DBCEnums.h37
-rw-r--r--src/game/DBCStores.cpp45
-rw-r--r--src/game/DBCStores.h5
-rw-r--r--src/game/DBCStructure.h255
-rw-r--r--src/game/DBCfmt.h19
-rw-r--r--src/game/Debugcmds.cpp40
-rw-r--r--src/game/DuelHandler.cpp7
-rw-r--r--src/game/DynamicObject.cpp6
-rw-r--r--src/game/DynamicObject.h2
-rw-r--r--src/game/GameEventMgr.cpp4
-rw-r--r--src/game/GameObject.h1
-rw-r--r--src/game/GossipDef.cpp20
-rw-r--r--src/game/GossipDef.h1
-rw-r--r--src/game/GridDefines.h1
-rw-r--r--src/game/GridNotifiers.h1
-rw-r--r--src/game/Group.cpp168
-rw-r--r--src/game/Group.h25
-rw-r--r--src/game/GroupHandler.cpp15
-rw-r--r--src/game/Guild.cpp57
-rw-r--r--src/game/Guild.h4
-rw-r--r--src/game/GuildHandler.cpp384
-rw-r--r--src/game/InstanceSaveMgr.cpp147
-rw-r--r--src/game/InstanceSaveMgr.h40
-rw-r--r--src/game/Item.cpp6
-rw-r--r--src/game/Item.h22
-rw-r--r--src/game/ItemHandler.cpp120
-rw-r--r--src/game/ItemPrototype.h17
-rw-r--r--src/game/Level1.cpp16
-rw-r--r--src/game/Level2.cpp1
-rw-r--r--src/game/Level3.cpp42
-rw-r--r--src/game/LootHandler.cpp2
-rw-r--r--src/game/LootMgr.cpp1
-rw-r--r--src/game/LootMgr.h4
-rw-r--r--src/game/Map.cpp50
-rw-r--r--src/game/Map.h20
-rw-r--r--src/game/MapInstanced.cpp90
-rw-r--r--src/game/MapInstanced.h8
-rw-r--r--src/game/MapManager.cpp49
-rw-r--r--src/game/MapManager.h1
-rw-r--r--src/game/MiscHandler.cpp108
-rw-r--r--src/game/MotionMaster.cpp1
-rw-r--r--src/game/MovementHandler.cpp91
-rw-r--r--src/game/Object.cpp64
-rw-r--r--src/game/Object.h12
-rw-r--r--src/game/ObjectAccessor.cpp8
-rw-r--r--src/game/ObjectAccessor.h1
-rw-r--r--src/game/ObjectMgr.cpp357
-rw-r--r--src/game/ObjectMgr.h21
-rw-r--r--src/game/Opcodes.cpp75
-rw-r--r--src/game/Opcodes.h93
-rw-r--r--src/game/OutdoorPvPWG.cpp14
-rw-r--r--src/game/OutdoorPvPWG.h4
-rw-r--r--src/game/Pet.cpp3
-rw-r--r--src/game/PetHandler.cpp70
-rw-r--r--src/game/PetitionsHandler.cpp69
-rw-r--r--src/game/Player.cpp719
-rw-r--r--src/game/Player.h137
-rw-r--r--src/game/PoolHandler.cpp198
-rw-r--r--src/game/PoolHandler.h11
-rw-r--r--src/game/QueryHandler.cpp37
-rw-r--r--src/game/QuestDef.cpp75
-rw-r--r--src/game/QuestDef.h10
-rw-r--r--src/game/QuestHandler.cpp3
-rw-r--r--src/game/SharedDefines.h487
-rw-r--r--src/game/Spell.cpp115
-rw-r--r--src/game/Spell.h9
-rw-r--r--src/game/SpellAuraDefines.h33
-rw-r--r--src/game/SpellAuras.cpp393
-rw-r--r--src/game/SpellAuras.h1
-rw-r--r--src/game/SpellEffects.cpp464
-rw-r--r--src/game/SpellHandler.cpp19
-rw-r--r--src/game/SpellMgr.cpp35
-rw-r--r--src/game/SpellMgr.h27
-rw-r--r--src/game/StatSystem.cpp48
-rw-r--r--src/game/TaxiHandler.cpp6
-rw-r--r--src/game/Totem.cpp7
-rw-r--r--src/game/Unit.cpp825
-rw-r--r--src/game/Unit.h16
-rw-r--r--src/game/UpdateFields.h70
-rw-r--r--src/game/World.cpp34
-rw-r--r--src/game/World.h25
-rw-r--r--src/game/WorldSession.cpp55
-rw-r--r--src/game/WorldSession.h13
-rw-r--r--src/game/WorldSocket.cpp10
-rw-r--r--src/shared/Database/SQLStorage.cpp13
-rw-r--r--src/trinityrealm/AuthCodes.h3
-rw-r--r--src/trinityrealm/AuthSocket.cpp12
-rw-r--r--win/VC90/game.vcproj16
132 files changed, 5069 insertions, 2803 deletions
diff --git a/contrib/extractor/ad.exe b/contrib/extractor/ad.exe
index 208eb2da030..608392aec43 100644
--- a/contrib/extractor/ad.exe
+++ b/contrib/extractor/ad.exe
Binary files differ
diff --git a/sql/characters.sql b/sql/characters.sql
index e138dafb6fe..f55cac2a1fe 100644
--- a/sql/characters.sql
+++ b/sql/characters.sql
@@ -1089,6 +1089,7 @@ CREATE TABLE `groups` (
`icon8` int(11) unsigned NOT NULL,
`isRaid` tinyint(1) unsigned NOT NULL,
`difficulty` tinyint(3) unsigned NOT NULL default '0',
+ `raiddifficulty` int(11) UNSIGNED NOT NULL default '0',
PRIMARY KEY (`leaderGuid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=FIXED COMMENT='Groups';
@@ -1394,8 +1395,9 @@ UNLOCK TABLES;
DROP TABLE IF EXISTS `instance_reset`;
CREATE TABLE `instance_reset` (
`mapid` int(11) unsigned NOT NULL default '0',
+ `difficulty` tinyint(1) unsigned NOT NULL default '0',
`resettime` bigint(40) NOT NULL default '0',
- PRIMARY KEY (`mapid`)
+ PRIMARY KEY (`mapid`,`difficulty`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
--
diff --git a/sql/updates/3.2.2a_characters_update.sql b/sql/updates/3.2.2a_characters_update.sql
new file mode 100644
index 00000000000..9c64a873728
--- /dev/null
+++ b/sql/updates/3.2.2a_characters_update.sql
@@ -0,0 +1,31 @@
+UPDATE characters SET data = REPLACE(data,' ',' ');
+UPDATE characters SET data = CONCAT(TRIM(data),' ');
+
+UPDATE `characters` SET `data` = CONCAT(
+SUBSTRING_INDEX(`data`, ' ', 1167 + 1), ' ',
+'0 0 ',
+SUBSTRING_INDEX(SUBSTRING_INDEX(`data`, ' ', 1246 + 1), ' ', -1246 + 1168 - 1), ' ',
+'0 0 0 ',
+SUBSTRING_INDEX(SUBSTRING_INDEX(`data`, ' ', 1294 + 1), ' ', -1294 + 1247 - 1), ' ',
+'0 '
+)
+WHERE length(SUBSTRING_INDEX(data, ' ', 1294)) < length(data) and length(SUBSTRING_INDEX(data, ' ', 1294+1)) >= length(data);
+
+UPDATE characters SET data = REPLACE(data,' ',' ');
+UPDATE characters SET data = CONCAT(TRIM(data),' ');
+
+alter table `groups`
+ add column `raiddifficulty` int(11) UNSIGNED DEFAULT '0' NOT NULL after `difficulty`;
+
+ALTER TABLE instance_reset
+ ADD COLUMN difficulty tinyint(1) unsigned NOT NULL default '0' AFTER mapid,
+ DROP PRIMARY KEY,
+ ADD PRIMARY KEY (`mapid`,`difficulty`);
+
+ALTER TABLE `bugreport` CHANGE `type` `type` LONGTEXT NOT NULL;
+ALTER TABLE `bugreport` CHANGE `content` `content` LONGTEXT NOT NULL;
+
+DELETE FROM `character_spell` WHERE `spell` IN (31892, 53720);
+DELETE FROM `character_spell_cooldown` WHERE `spell` IN (31892, 53720);
+DELETE FROM `character_aura` WHERE `spell` IN (31892, 53720);
+DELETE FROM `character_action` WHERE `action` IN (31892, 53720) AND `type`=0; \ No newline at end of file
diff --git a/sql/updates/3.2.2a_world_update.sql b/sql/updates/3.2.2a_world_update.sql
new file mode 100644
index 00000000000..a6acb6617bc
--- /dev/null
+++ b/sql/updates/3.2.2a_world_update.sql
@@ -0,0 +1,140 @@
+alter table `item_template`
+ add column `Faction` int(11) UNSIGNED DEFAULT '0' NOT NULL after `Flags`;
+
+ALTER TABLE item_template
+ CHANGE COLUMN ItemLevel ItemLevel smallint(5) unsigned NOT NULL DEFAULT 0;
+
+ALTER TABLE `spell_proc_event` CHANGE COLUMN `entry` `entry` mediumint(8) unsigned NOT NULL DEFAULT '0';
+ALTER TABLE `spell_bonus_data` CHANGE COLUMN `entry` `entry` mediumint(8) unsigned NOT NULL DEFAULT '0';
+
+ALTER TABLE `quest_template`
+ ADD COLUMN `ReqItemId5` mediumint(8) UNSIGNED DEFAULT '0' NOT NULL AFTER `ReqItemId4`,
+ ADD COLUMN `ReqItemId6` mediumint(8) UNSIGNED DEFAULT '0' NOT NULL AFTER `ReqItemId5`,
+ ADD COLUMN `ReqItemCount5` smallint(5) UNSIGNED DEFAULT '0' NOT NULL AFTER `ReqItemCount4`,
+ ADD COLUMN `ReqItemCount6` smallint(5) UNSIGNED DEFAULT '0' NOT NULL AFTER `ReqItemCount5`;
+
+ALTER TABLE creature_template
+ CHANGE COLUMN heroic_entry difficulty_entry_1 mediumint(8) unsigned NOT NULL default '0';
+
+ALTER TABLE `creature_template` ADD `difficulty_entry_2` MEDIUMINT(8) unsigned
+ NOT NULL default 0 AFTER `difficulty_entry_1`;
+ALTER TABLE `creature_template` ADD `difficulty_entry_3` MEDIUMINT(8) unsigned
+ NOT NULL default 0 AFTER `difficulty_entry_2`;
+
+ALTER TABLE instance_template
+ DROP COLUMN maxPlayers,
+ DROP COLUMN maxPlayersHeroic,
+ DROP COLUMN reset_delay;
+
+DELETE FROM `spell_elixir` WHERE `entry` IN (67016,67017,67018);
+INSERT INTO `spell_elixir` (`entry`, `mask`) VALUES
+(67016,0x3),
+(67017,0x3),
+(67018,0x3);
+
+DELETE from `player_classlevelstats` where `class` = 7;
+INSERT INTO `player_classlevelstats` (`class`, `level`, `basehp`, `basemana`) VALUES
+(7, 1, 40, 85),
+(7, 2, 47, 91),
+(7, 3, 55, 98),
+(7, 4, 62, 106),
+(7, 5, 70, 115),
+(7, 6, 77, 125),
+(7, 7, 85, 136),
+(7, 8, 92, 148),
+(7, 9, 100, 161),
+(7, 10, 107, 175),
+(7, 11, 114, 190),
+(7, 12, 122, 206),
+(7, 13, 129, 223),
+(7, 14, 137, 241),
+(7, 15, 144, 260),
+(7, 16, 152, 280),
+(7, 17, 161, 301),
+(7, 18, 170, 323),
+(7, 19, 181, 346),
+(7, 20, 193, 370),
+(7, 21, 205, 395),
+(7, 22, 219, 421),
+(7, 23, 234, 448),
+(7, 24, 250, 476),
+(7, 25, 257, 505),
+(7, 26, 275, 535),
+(7, 27, 294, 566),
+(7, 28, 315, 598),
+(7, 29, 336, 631),
+(7, 30, 358, 665),
+(7, 31, 371, 699),
+(7, 32, 396, 733),
+(7, 33, 422, 767),
+(7, 34, 448, 786),
+(7, 35, 465, 820),
+(7, 36, 494, 854),
+(7, 37, 524, 888),
+(7, 38, 545, 922),
+(7, 39, 577, 941),
+(7, 40, 610, 975),
+(7, 41, 633, 1009),
+(7, 42, 669, 1028),
+(7, 43, 694, 1062),
+(7, 44, 732, 1096),
+(7, 45, 760, 1115),
+(7, 46, 799, 1149),
+(7, 47, 829, 1183),
+(7, 48, 871, 1202),
+(7, 49, 903, 1236),
+(7, 50, 947, 1255),
+(7, 51, 981, 1289),
+(7, 52, 1027, 1323),
+(7, 53, 1064, 1342),
+(7, 54, 1101, 1376),
+(7, 55, 1150, 1395),
+(7, 56, 1190, 1414),
+(7, 57, 1231, 1448),
+(7, 58, 1283, 1467),
+(7, 59, 1326, 1501),
+(7, 60, 1423, 1520),
+(7, 61, 1528, 1664),
+(7, 62, 1694, 1808),
+(7, 63, 1883, 1951),
+(7, 64, 2067, 2095),
+(7, 65, 2262, 2239),
+(7, 66, 2465, 2383),
+(7, 67, 2679, 2527),
+(7, 68, 2903, 2670),
+(7, 69, 3136, 2814),
+(7, 70, 3380, 2958),
+(7, 71, 3633, 3102),
+(7, 72, 3903, 3246),
+(7, 73, 4194, 3389),
+(7, 74, 4507, 3533),
+(7, 75, 4843, 3677),
+(7, 76, 5203, 3821),
+(7, 77, 5592, 3965),
+(7, 78, 6009, 4108),
+(7, 79, 6457, 4252),
+(7, 80, 6939, 4396);
+
+DROP TABLE IF EXISTS `playercreateinfo_action`;
+CREATE TABLE `playercreateinfo_action` (
+ `race` tinyint(3) unsigned NOT NULL default '0',
+ `class` tinyint(3) unsigned NOT NULL default '0',
+ `button` smallint(5) unsigned NOT NULL default '0',
+ `action` int(11) unsigned NOT NULL default '0',
+ `type` smallint(5) unsigned NOT NULL default '0',
+ PRIMARY KEY (`race`,`class`,`button`),
+ KEY `playercreateinfo_race_class_index` (`race`,`class`)
+) ENGINE=MyISAM DEFAULT CHARSET=utf8;
+
+insert into `playercreateinfo_action`(`race`,`class`,`button`,`action`,`type`) values (1,1,0,6603,0),(1,1,11,117,128),(1,1,72,6603,0),(1,1,73,78,0),(1,1,82,59752,0),(1,1,83,117,128),(1,1,84,6603,0),(1,1,96,6603,0),(1,1,108,6603,0),(1,2,0,6603,0),(1,2,1,21084,0),(1,2,2,635,0),(1,2,9,59752,0),(1,2,10,159,128),(1,2,11,2070,128),(1,4,0,6603,0),(1,4,1,1752,0),(1,4,2,2098,0),(1,4,3,2764,0),(1,4,10,59752,0),(1,4,11,2070,128),(1,5,0,6603,0),(1,5,1,585,0),(1,5,2,2050,0),(1,5,9,59752,0),(1,5,10,159,128),(1,5,11,2070,128),(1,6,0,6603,0),(1,6,1,49576,0),(1,6,2,45477,0),(1,6,3,45462,0),(1,6,4,45902,0),(1,6,5,47541,0),(1,6,11,59752,0),(1,8,0,6603,0),(1,8,1,133,0),(1,8,2,168,0),(1,8,9,59752,0),(1,8,10,159,128),(1,8,11,2070,128),(1,9,0,6603,0),(1,9,1,686,0),(1,9,2,687,0),(1,9,9,59752,0),(1,9,10,159,128),(1,9,11,4604,128),(2,1,0,6603,0),(2,1,72,6603,0),(2,1,73,78,0),(2,1,74,20572,0),(2,1,83,117,128),(2,1,84,6603,0),(2,1,96,6603,0),(2,1,108,6603,0),(2,3,0,6603,0),(2,3,1,2973,0),(2,3,2,75,0),(2,3,9,20572,0),(2,3,10,159,128),(2,3,11,117,128),(2,4,0,6603,0),(2,4,1,1752,0),(2,4,2,2098,0),(2,4,3,2764,0),(2,4,4,20572,0),(2,4,11,117,128),(2,6,0,6603,0),(2,6,1,49576,0),(2,6,2,45477,0),(2,6,3,45462,0),(2,6,4,45902,0),(2,6,5,47541,0),(2,6,10,20572,0),(2,7,0,6603,0),(2,7,1,403,0),(2,7,2,331,0),(2,7,3,33697,0),(2,7,10,159,128),(2,7,11,117,128),(2,9,0,6603,0),(2,9,1,686,0),(2,9,2,687,0),(2,9,3,33702,0),(2,9,10,159,128),(2,9,11,117,128),(3,1,0,6603,0),(3,1,1,78,0),(3,1,11,117,128),(3,1,72,6603,0),(3,1,73,78,0),(3,1,74,20594,0),(3,1,75,2481,0),(3,1,83,117,128),(3,1,84,6603,0),(3,1,96,6603,0),(3,1,108,6603,0),(3,2,0,6603,0),(3,2,1,21084,0),(3,2,2,635,0),(3,2,3,20594,0),(3,2,4,2481,0),(3,2,10,159,128),(3,2,11,4540,128),(3,3,0,6603,0),(3,3,1,2973,0),(3,3,2,75,0),(3,3,3,20594,0),(3,3,4,2481,0),(3,3,10,159,128),(3,3,11,117,128),(3,3,75,20594,0),(3,3,76,2481,0),(3,4,0,6603,0),(3,4,1,1752,0),(3,4,2,2098,0),(3,4,3,2764,0),(3,4,4,20594,0),(3,4,5,2481,0),(3,4,11,4540,128),(3,5,0,6603,0),(3,5,1,585,0),(3,5,2,2050,0),(3,5,3,20594,0),(3,5,4,2481,0),(3,5,10,159,128),(3,5,11,4540,128),(3,6,0,6603,0),(3,6,1,49576,0),(3,6,2,45477,0),(3,6,3,45462,0),(3,6,4,45902,0),(3,6,5,47541,0),(3,6,10,2481,0),(4,1,72,6603,0),(4,4,82,58984,0),(4,1,73,78,0),(4,1,82,58984,0),(4,1,83,117,128),(4,1,85,6603,0),(4,1,97,6603,0),(4,1,109,6603,0),(4,3,0,6603,0),(4,3,1,2973,0),(4,3,2,75,0),(4,3,3,58984,0),(4,3,10,159,128),(4,3,11,117,128),(4,4,0,6603,0),(4,4,1,1752,0),(4,4,2,2098,0),(4,4,3,2764,0),(4,4,10,58984,0),(4,4,11,4540,128),(4,5,0,6603,0),(4,5,1,585,0),(4,5,2,2050,0),(4,5,3,58984,0),(4,5,10,159,128),(4,5,11,2070,128),(4,6,0,6603,0),(4,6,1,49576,0),(4,6,2,45477,0),(4,6,3,45462,0),(4,6,4,45902,0),(4,6,5,47541,0),(4,6,10,58984,0),(4,6,83,58984,0),(4,11,0,6603,0),(4,11,1,5176,0),(4,11,2,5185,0),(4,11,9,58984,0),(4,11,10,159,128),(4,11,11,4536,128),(5,1,0,6603,0),(5,1,72,6603,0),(5,1,73,78,0),(5,1,74,20577,0),(5,1,83,4604,128),(5,1,84,6603,0),(5,1,96,6603,0),(5,1,108,6603,0),(5,4,0,6603,0),(5,4,1,1752,0),(5,4,2,2098,0),(5,4,3,2764,0),(5,4,4,20577,0),(5,4,11,4604,128),(5,5,0,6603,0),(5,5,1,585,0),(5,5,2,2050,0),(5,5,3,20577,0),(5,5,10,159,128),(5,5,11,4604,128),(5,6,0,6603,0),(5,6,1,49576,0),(5,6,2,45477,0),(5,6,3,45462,0),(5,6,4,45902,0),(5,6,5,47541,0),(5,6,10,20577,0),(5,8,0,6603,0),(5,8,1,133,0),(5,8,2,168,0),(5,8,3,20577,0),(5,8,10,159,128),(5,8,11,4604,128),(5,9,0,6603,0),(5,9,1,686,0),(5,9,2,687,0),(5,9,3,20577,0),(5,9,10,159,128),(5,9,11,4604,128),(6,1,0,6603,0),(6,1,1,78,0),(6,1,3,20549,0),(6,1,72,6603,0),(6,1,73,78,0),(6,1,74,20549,0),(6,1,83,4540,128),(6,1,84,6603,0),(6,1,96,6603,0),(6,1,108,6603,0),(6,3,0,6603,0),(6,3,1,2973,0),(6,3,2,75,0),(6,3,3,20549,0),(6,3,10,159,128),(6,3,11,117,128),(6,3,76,20549,0),(6,6,0,6603,0),(6,6,1,49576,0),(6,6,2,45477,0),(6,6,3,45462,0),(6,6,4,45902,0),(6,6,5,47541,0),(6,6,10,20549,0),(6,6,75,20549,0),(6,7,0,6603,0),(6,7,1,403,0),(6,7,2,331,0),(6,7,3,20549,0),(6,7,10,159,128),(6,7,11,4604,128),(6,7,76,20549,0),(6,11,0,6603,0),(6,11,1,5176,0),(6,11,2,5185,0),(6,11,3,20549,0),(6,11,10,159,128),(6,11,11,4536,128),(6,11,73,6603,0),(6,11,76,20549,0),(6,11,85,6603,0),(6,11,97,6603,0),(6,11,109,6603,0),(7,1,0,6603,0),(7,1,1,78,0),(7,1,10,20589,0),(7,1,11,117,128),(7,1,72,6603,0),(7,1,73,78,0),(7,1,82,20589,0),(7,1,83,117,128),(7,1,84,6603,0),(7,1,96,6603,0),(7,1,108,6603,0),(7,4,0,6603,0),(7,4,1,1752,0),(7,4,2,2098,0),(7,4,3,2764,0),(7,4,10,20589,0),(7,4,11,117,128),(7,6,0,6603,0),(7,6,1,49576,0),(7,6,2,45477,0),(7,6,3,45462,0),(7,6,4,45902,0),(7,6,5,47541,0),(7,6,10,20589,0),(7,6,83,41751,128),(7,6,72,6603,0),(7,6,11,41751,128),(7,6,84,6603,0),(7,6,96,6603,0),(7,6,108,6603,0),(7,8,0,6603,0),(7,8,1,133,0),(7,8,2,168,0),(7,8,9,20589,0),(7,8,10,159,128),(7,8,11,4536,128),(7,9,0,6603,0),(7,9,1,686,0),(7,9,2,687,0),(7,9,9,20589,0),(7,9,10,159,128),(7,9,11,4604,128),(8,1,0,6603,0),(8,1,72,6603,0),(8,1,73,78,0),(8,1,74,2764,0),(8,1,75,26297,0),(8,1,83,117,128),(8,1,84,6603,0),(8,1,96,6603,0),(8,1,108,6603,0),(8,3,0,6603,0),(8,3,1,2973,0),(8,3,2,75,0),(8,3,10,159,128),(8,3,11,4604,128),(8,8,3,26297,0),(8,4,0,6603,0),(8,4,1,1752,0),(8,4,2,2098,0),(8,4,3,2764,0),(8,4,11,117,128),(8,4,4,26297,0),(8,5,0,6603,0),(8,5,1,585,0),(8,5,2,2050,0),(8,5,10,159,128),(8,5,11,4540,128),(8,7,3,26297,0),(8,6,0,6603,0),(8,6,1,49576,0),(8,6,2,45477,0),(8,6,3,45462,0),(8,6,4,45902,0),(8,6,5,47541,0),(8,6,10,26297,0),(8,7,0,6603,0),(8,7,1,403,0),(8,7,2,331,0),(8,7,10,159,128),(8,7,11,117,128),(8,5,3,26297,0),(8,8,0,6603,0),(8,8,1,133,0),(8,8,2,168,0),(8,8,10,159,128),(8,8,11,117,128),(8,3,3,26297,0),(10,2,0,6603,0),(10,2,1,21084,0),(10,2,2,635,0),(10,2,3,28730,0),(10,2,10,159,128),(10,2,11,20857,128),(10,3,0,6603,0),(10,3,1,2973,0),(10,3,2,75,0),(10,3,3,28730,0),(10,3,10,159,128),(10,3,11,20857,128),(10,4,0,6603,0),(10,4,1,1752,0),(10,4,2,2098,0),(10,4,3,2764,0),(10,4,4,25046,0),(10,4,11,20857,128),(10,5,0,6603,0),(10,5,1,585,0),(10,5,2,2050,0),(10,5,3,28730,0),(10,5,10,159,128),(10,5,11,20857,128),(10,6,0,6603,0),(10,6,1,49576,0),(10,6,2,45477,0),(10,6,3,45462,0),(10,6,4,45902,0),(10,6,5,47541,0),(10,6,6,50613,0),(10,8,0,6603,0),(10,8,1,133,0),(10,8,2,168,0),(10,8,3,28730,0),(10,8,10,159,128),(10,8,11,20857,128),(10,9,0,6603,0),(10,9,1,686,0),(10,9,2,687,0),(10,9,3,28730,0),(10,9,10,159,128),(10,9,11,20857,128),(11,1,0,6603,0),(11,1,72,6603,0),(11,1,73,78,0),(11,1,74,28880,0),(11,1,83,4540,128),(11,1,84,6603,0),(11,1,96,6603,0),(11,1,108,6603,0),(11,2,0,6603,0),(11,2,1,21084,0),(11,2,2,635,0),(11,2,3,59542,0),(11,2,10,159,128),(11,2,11,4540,128),(11,2,83,4540,128),(11,3,0,6603,0),(11,3,1,2973,0),(11,3,2,75,0),(11,3,3,59543,0),(11,3,10,159,128),(11,3,11,4540,128),(11,3,72,6603,0),(11,3,73,2973,0),(11,3,74,75,0),(11,3,82,159,128),(11,3,83,4540,128),(11,5,0,6603,0),(11,5,1,585,0),(11,5,2,2050,0),(11,5,3,59544,0),(11,5,10,159,128),(11,5,11,4540,128),(11,5,83,4540,128),(11,6,0,6603,0),(11,6,1,49576,0),(11,6,2,45477,0),(11,6,3,45462,0),(11,6,4,45902,0),(11,6,5,47541,0),(11,6,10,59545,0),(11,7,0,6603,0),(11,7,1,403,0),(11,7,2,331,0),(11,7,3,59547,0),(11,7,10,159,128),(11,7,11,4540,128),(11,8,0,6603,0),(11,8,1,133,0),(11,8,2,168,0),(11,8,3,59548,0),(11,8,10,159,128),(11,8,11,4540,128),(11,8,83,4540,128),(11,6,11,41751,128);
+
+DROP TABLE IF EXISTS `playercreateinfo_spell`;
+CREATE TABLE `playercreateinfo_spell` (
+ `race` tinyint(3) unsigned NOT NULL default '0',
+ `class` tinyint(3) unsigned NOT NULL default '0',
+ `Spell` mediumint(8) unsigned NOT NULL default '0',
+ `Note` varchar(255) default NULL,
+ PRIMARY KEY (`race`,`class`,`Spell`)
+) ENGINE=MyISAM DEFAULT CHARSET=utf8;
+
+insert into `playercreateinfo_spell`(`race`,`class`,`Spell`,`Note`) values (1,1,78,'Heroic Strike'),(1,1,81,'Dodge'),(1,1,107,'Block'),(1,1,196,'One-Handed Axes'),(1,1,198,'One-Handed Maces'),(1,1,201,'One-Handed Swords'),(1,1,203,'Unarmed'),(1,1,204,'Defense'),(1,1,522,'SPELLDEFENSE (DND)'),(1,1,668,'Language Common'),(1,1,1843,'Disarm'),(1,1,2382,'Generic'),(1,1,2457,'Battle Stance'),(1,1,2479,'Honorless Target'),(1,1,3050,'Detect'),(1,1,3365,'Opening'),(1,1,5301,'Defensive State (DND)'),(1,1,6233,'Closing'),(1,1,6246,'Closing'),(1,1,6247,'Opening'),(1,1,6477,'Opening'),(1,1,6478,'Opening'),(1,1,6603,'Attack'),(1,1,7266,'Duel'),(1,1,7267,'Grovel'),(1,1,7355,'Stuck'),(1,1,8386,'Attacking'),(1,1,8737,'Mail'),(1,1,9077,'Leather'),(1,1,9078,'Cloth'),(1,1,9116,'Shield'),(1,1,9125,'Generic'),(1,1,20597,'Sword Specialization'),(1,1,20598,'The Human Spirit'),(1,1,20599,'Diplomacy'),(1,1,20864,'Mace Specialization'),(1,1,21651,'Opening'),(1,1,21652,'Closing'),(1,1,22027,'Remove Insignia'),(1,1,22810,'Opening - No Text'),(1,1,32215,'Victorious State'),(1,1,45927,'Summon Friend'),(1,1,58985,'Perception'),(1,1,59752,'Every Man for Himself'),(1,1,61437,'Opening'),(1,2,81,'Dodge'),(1,2,107,'Block'),(1,2,198,'One-Handed Maces'),(1,2,199,'Two-Handed Maces'),(1,2,203,'Unarmed'),(1,2,204,'Defense'),(1,2,522,'SPELLDEFENSE (DND)'),(1,2,635,'Holy Light'),(1,2,668,'Language Common'),(1,2,1843,'Disarm'),(1,2,2382,'Generic'),(1,2,2479,'Honorless Target'),(1,2,3050,'Detect'),(1,2,3365,'Opening'),(1,2,6233,'Closing'),(1,2,6246,'Closing'),(1,2,6247,'Opening'),(1,2,6477,'Opening'),(1,2,6478,'Opening'),(1,2,6603,'Attack'),(1,2,7266,'Duel'),(1,2,7267,'Grovel'),(1,2,7355,'Stuck'),(1,2,8386,'Attacking'),(1,2,8737,'Mail'),(1,2,9077,'Leather'),(1,2,9078,'Cloth'),(1,2,9116,'Shield'),(1,2,9125,'Generic'),(1,2,21084,'Seal of Righteousness'),(1,2,20597,'Sword Specialization'),(1,2,20598,'The Human Spirit'),(1,2,20599,'Diplomacy'),(1,2,20864,'Mace Specialization'),(1,2,21651,'Opening'),(1,2,21652,'Closing'),(1,2,22027,'Remove Insignia'),(1,2,22810,'Opening - No Text'),(1,2,27762,'Libram'),(1,2,45927,'Summon Friend'),(1,2,58985,'Perception'),(1,2,59752,'Every Man for Himself'),(1,2,61437,'Opening'),(1,4,81,'Dodge'),(1,4,203,'Unarmed'),(1,4,204,'Defense'),(1,4,522,'SPELLDEFENSE (DND)'),(1,4,668,'Language Common'),(1,4,1180,'Daggers'),(1,4,1752,'Sinister Strike'),(1,4,1843,'Disarm'),(1,4,2098,'Eviscerate'),(1,4,2382,'Generic'),(1,4,2479,'Honorless Target'),(1,4,2567,'Thrown'),(1,4,2764,'Throw'),(1,4,3050,'Detect'),(1,4,3365,'Opening'),(1,4,6233,'Closing'),(1,4,6246,'Closing'),(1,4,6247,'Opening'),(1,4,6477,'Opening'),(1,4,6478,'Opening'),(1,4,6603,'Attack'),(1,4,7266,'Duel'),(1,4,7267,'Grovel'),(1,4,7355,'Stuck'),(1,4,8386,'Attacking'),(1,4,9077,'Leather'),(1,4,9078,'Cloth'),(1,4,9125,'Generic'),(1,4,16092,'Defensive State (DND)'),(1,4,20597,'Sword Specialization'),(1,4,20598,'The Human Spirit'),(1,4,20599,'Diplomacy'),(1,4,20864,'Mace Specialization'),(1,4,21184,'Rogue Passive (DND)'),(1,4,21651,'Opening'),(1,4,21652,'Closing'),(1,4,22027,'Remove Insignia'),(1,4,22810,'Opening - No Text'),(1,4,45927,'Summon Friend'),(1,4,58985,'Perception'),(1,4,59752,'Every Man for Himself'),(1,4,61437,'Opening'),(1,5,81,'Dodge'),(1,5,198,'One-Handed Maces'),(1,5,203,'Unarmed'),(1,5,204,'Defense'),(1,5,522,'SPELLDEFENSE (DND)'),(1,5,585,'Smite'),(1,5,668,'Language Common'),(1,5,1843,'Disarm'),(1,5,2050,'Lesser Heal'),(1,5,2382,'Generic'),(1,5,2479,'Honorless Target'),(1,5,3050,'Detect'),(1,5,3365,'Opening'),(1,5,5009,'Wands'),(1,5,5019,'Shoot'),(1,5,6233,'Closing'),(1,5,6246,'Closing'),(1,5,6247,'Opening'),(1,5,6477,'Opening'),(1,5,6478,'Opening'),(1,5,6603,'Attack'),(1,5,7266,'Duel'),(1,5,7267,'Grovel'),(1,5,7355,'Stuck'),(1,5,8386,'Attacking'),(1,5,9078,'Cloth'),(1,5,9125,'Generic'),(1,5,20597,'Sword Specialization'),(1,5,20598,'The Human Spirit'),(1,5,20599,'Diplomacy'),(1,5,20864,'Mace Specialization'),(1,5,21651,'Opening'),(1,5,21652,'Closing'),(1,5,22027,'Remove Insignia'),(1,5,22810,'Opening - No Text'),(1,5,45927,'Summon Friend'),(1,5,58985,'Perception'),(1,5,59752,'Every Man for Himself'),(1,5,61437,'Opening'),(1,6,81,'Dodge'),(1,6,196,'One-Handed Axes'),(1,6,197,'Two-Handed Axes'),(1,6,200,'Polearms'),(1,6,201,'One-Handed Swords'),(1,6,202,'Two-Handed Swords'),(1,6,203,'Unarmed'),(1,6,204,'Defense'),(1,6,522,'SPELLDEFENSE (DND)'),(1,6,668,'Language Common'),(1,6,674,'Dual Wield'),(1,6,750,'Plate Mail'),(1,6,1843,'Disarm'),(1,6,2382,'Generic'),(1,6,2479,'Honorless Target'),(1,6,3050,'Detect'),(1,6,3127,'Parry'),(1,6,3275,'Linen Bandage'),(1,6,3276,'Heavy Linen Bandage'),(1,6,3277,'Wool Bandage'),(1,6,3278,'Heavy Wool Bandage'),(1,6,3365,'Opening'),(1,6,6233,'Closing'),(1,6,6246,'Closing'),(1,6,6247,'Opening'),(1,6,6477,'Opening'),(1,6,6478,'Opening'),(1,6,6603,'Attack'),(1,6,7266,'Duel'),(1,6,7267,'Grovel'),(1,6,7355,'Stuck'),(1,6,7928,'Silk Bandage'),(1,6,7929,'Heavy Silk Bandage'),(1,6,7934,'Anti-Venom'),(1,6,8386,'Attacking'),(1,6,8737,'Mail'),(1,6,9077,'Leather'),(1,6,9078,'Cloth'),(1,6,9125,'Generic'),(1,6,10840,'Mageweave Bandage'),(1,6,10841,'Heavy Mageweave Bandage'),(1,6,10846,'First Aid'),(1,6,18629,'Runecloth Bandage'),(1,6,18630,'Heavy Runecloth Bandage'),(1,6,20597,'Sword Specialization'),(1,6,20598,'The Human Spirit'),(1,6,20599,'Diplomacy'),(1,6,20864,'Mace Specialization'),(1,6,21651,'Opening'),(1,6,21652,'Closing'),(1,6,22027,'Remove Insignia'),(1,6,22810,'Opening - No Text'),(1,6,33391,'Journeyman Riding'),(1,6,45462,'Plague Strike'),(1,6,45477,'Icy Touch'),(1,6,45902,'Blood Strike'),(1,6,45903,'Offensive State (DND)'),(1,6,45927,'Summon Friend'),(1,6,47541,'Death Coil'),(1,6,48266,'Blood Presence'),(1,6,49410,'Forceful Deflection'),(1,6,49576,'Death Grip'),(1,6,52665,'Sigil'),(1,6,58985,'Perception'),(1,6,59752,'Every Man for Himself'),(1,6,59879,'Blood Plague'),(1,6,59921,'Frost Fever'),(1,6,61437,'Opening'),(1,6,61455,'Runic Focus'),(1,8,81,'Dodge'),(1,8,133,'Fireball'),(1,8,168,'Frost Armor'),(1,8,203,'Unarmed'),(1,8,204,'Defense'),(1,8,227,'Staves'),(1,8,522,'SPELLDEFENSE (DND)'),(1,8,668,'Language Common'),(1,8,1843,'Disarm'),(1,8,2382,'Generic'),(1,8,2479,'Honorless Target'),(1,8,3050,'Detect'),(1,8,3365,'Opening'),(1,8,5009,'Wands'),(1,8,5019,'Shoot'),(1,8,6233,'Closing'),(1,8,6246,'Closing'),(1,8,6247,'Opening'),(1,8,6477,'Opening'),(1,8,6478,'Opening'),(1,8,6603,'Attack'),(1,8,7266,'Duel'),(1,8,7267,'Grovel'),(1,8,7355,'Stuck'),(1,8,8386,'Attacking'),(1,8,9078,'Cloth'),(1,8,9125,'Generic'),(1,8,20597,'Sword Specialization'),(1,8,20598,'The Human Spirit'),(1,8,20599,'Diplomacy'),(1,8,20864,'Mace Specialization'),(1,8,21651,'Opening'),(1,8,21652,'Closing'),(1,8,22027,'Remove Insignia'),(1,8,22810,'Opening - No Text'),(1,8,45927,'Summon Friend'),(1,8,58985,'Perception'),(1,8,59752,'Every Man for Himself'),(1,8,61437,'Opening'),(1,9,81,'Dodge'),(1,9,203,'Unarmed'),(1,9,204,'Defense'),(1,9,522,'SPELLDEFENSE (DND)'),(1,9,668,'Language Common'),(1,9,686,'Shadow Bolt'),(1,9,687,'Demon Skin'),(1,9,1180,'Daggers'),(1,9,1843,'Disarm'),(1,9,2382,'Generic'),(1,9,2479,'Honorless Target'),(1,9,3050,'Detect'),(1,9,3365,'Opening'),(1,9,5009,'Wands'),(1,9,5019,'Shoot'),(1,9,6233,'Closing'),(1,9,6246,'Closing'),(1,9,6247,'Opening'),(1,9,6477,'Opening'),(1,9,6478,'Opening'),(1,9,6603,'Attack'),(1,9,7266,'Duel'),(1,9,7267,'Grovel'),(1,9,7355,'Stuck'),(1,9,8386,'Attacking'),(1,9,9078,'Cloth'),(1,9,9125,'Generic'),(1,9,20597,'Sword Specialization'),(1,9,20598,'The Human Spirit'),(1,9,20599,'Diplomacy'),(1,9,20864,'Mace Specialization'),(1,9,21651,'Opening'),(1,9,21652,'Closing'),(1,9,22027,'Remove Insignia'),(1,9,22810,'Opening - No Text'),(1,9,45927,'Summon Friend'),(5,9,58284,'Chaos Bolt Passive'),(1,9,58985,'Perception'),(1,9,59752,'Every Man for Himself'),(1,9,61437,'Opening'),(2,1,78,'Heroic Strike'),(2,1,81,'Dodge'),(2,1,107,'Block'),(2,1,196,'One-Handed Axes'),(2,1,197,'Two-Handed Axes'),(2,1,201,'One-Handed Swords'),(2,1,203,'Unarmed'),(2,1,204,'Defense'),(2,1,522,'SPELLDEFENSE (DND)'),(2,1,669,'Language Orcish'),(2,1,1843,'Disarm'),(2,1,2382,'Generic'),(2,1,2457,'Battle Stance'),(2,1,2479,'Honorless Target'),(2,1,3050,'Detect'),(2,1,3365,'Opening'),(2,1,5301,'Defensive State (DND)'),(2,1,6233,'Closing'),(2,1,6246,'Closing'),(2,1,6247,'Opening'),(2,1,6477,'Opening'),(2,1,6478,'Opening'),(2,1,6603,'Attack'),(2,1,7266,'Duel'),(2,1,7267,'Grovel'),(2,1,7355,'Stuck'),(2,1,8386,'Attacking'),(2,1,8737,'Mail'),(2,1,9077,'Leather'),(2,1,9078,'Cloth'),(2,1,9116,'Shield'),(2,1,9125,'Generic'),(2,1,20572,'Blood Fury'),(2,1,20573,'Hardiness'),(2,1,20574,'Axe Specialization'),(2,1,21563,'Command'),(2,1,21651,'Opening'),(2,1,21652,'Closing'),(2,1,22027,'Remove Insignia'),(2,1,22810,'Opening - No Text'),(2,1,32215,'Victorious State'),(2,1,45927,'Summon Friend'),(2,1,61437,'Opening'),(2,3,75,'Auto Shot'),(2,3,81,'Dodge'),(2,3,196,'One-Handed Axes'),(2,3,203,'Unarmed'),(2,3,204,'Defense'),(2,3,264,'Bows'),(2,3,522,'SPELLDEFENSE (DND)'),(2,3,669,'Language Orcish'),(2,3,1843,'Disarm'),(2,3,2382,'Generic'),(2,3,2479,'Honorless Target'),(2,3,2973,'Raptor Strike'),(2,3,3050,'Detect'),(2,3,3365,'Opening'),(2,3,6233,'Closing'),(2,3,6246,'Closing'),(2,3,6247,'Opening'),(2,3,6477,'Opening'),(2,3,6478,'Opening'),(2,3,6603,'Attack'),(2,3,7266,'Duel'),(2,3,7267,'Grovel'),(2,3,7355,'Stuck'),(2,3,8386,'Attacking'),(2,3,9077,'Leather'),(2,3,9078,'Cloth'),(2,3,9125,'Generic'),(2,3,13358,'Defensive State (DND)'),(2,3,20572,'Blood Fury'),(2,3,20573,'Hardiness'),(2,3,20574,'Axe Specialization'),(2,3,20576,'Command'),(2,3,21651,'Opening'),(2,3,21652,'Closing'),(2,3,22027,'Remove Insignia'),(2,3,22810,'Opening - No Text'),(2,3,24949,'Defensive State 2 (DND)'),(2,3,34082,'Advantaged State (DND)'),(2,3,45927,'Summon Friend'),(2,3,61437,'Opening'),(2,4,81,'Dodge'),(2,4,203,'Unarmed'),(2,4,204,'Defense'),(2,4,522,'SPELLDEFENSE (DND)'),(2,4,669,'Language Orcish'),(2,4,1180,'Daggers'),(2,4,1752,'Sinister Strike'),(2,4,1843,'Disarm'),(2,4,2098,'Eviscerate'),(2,4,2382,'Generic'),(2,4,2479,'Honorless Target'),(2,4,2567,'Thrown'),(2,4,2764,'Throw'),(2,4,3050,'Detect'),(2,4,3365,'Opening'),(2,4,6233,'Closing'),(2,4,6246,'Closing'),(2,4,6247,'Opening'),(2,4,6477,'Opening'),(2,4,6478,'Opening'),(2,4,6603,'Attack'),(2,4,7266,'Duel'),(2,4,7267,'Grovel'),(2,4,7355,'Stuck'),(2,4,8386,'Attacking'),(2,4,9077,'Leather'),(2,4,9078,'Cloth'),(2,4,9125,'Generic'),(2,4,16092,'Defensive State (DND)'),(2,4,20572,'Blood Fury'),(2,4,20573,'Hardiness'),(2,4,20574,'Axe Specialization'),(2,4,21184,'Rogue Passive (DND)'),(2,4,21563,'Command'),(2,4,21651,'Opening'),(2,4,21652,'Closing'),(2,4,22027,'Remove Insignia'),(2,4,22810,'Opening - No Text'),(2,4,45927,'Summon Friend'),(2,4,61437,'Opening'),(2,6,81,'Dodge'),(2,6,196,'One-Handed Axes'),(2,6,197,'Two-Handed Axes'),(2,6,200,'Polearms'),(2,6,201,'One-Handed Swords'),(2,6,202,'Two-Handed Swords'),(2,6,203,'Unarmed'),(2,6,204,'Defense'),(2,6,522,'SPELLDEFENSE (DND)'),(2,6,669,'Language Orcish'),(2,6,674,'Dual Wield'),(2,6,750,'Plate Mail'),(2,6,1843,'Disarm'),(2,6,2382,'Generic'),(2,6,2479,'Honorless Target'),(2,6,3050,'Detect'),(2,6,3127,'Parry'),(2,6,3275,'Linen Bandage'),(2,6,3276,'Heavy Linen Bandage'),(2,6,3277,'Wool Bandage'),(2,6,3278,'Heavy Wool Bandage'),(2,6,3365,'Opening'),(2,6,6233,'Closing'),(2,6,6246,'Closing'),(2,6,6247,'Opening'),(2,6,6477,'Opening'),(2,6,6478,'Opening'),(2,6,6603,'Attack'),(2,6,7266,'Duel'),(2,6,7267,'Grovel'),(2,6,7355,'Stuck'),(2,6,7928,'Silk Bandage'),(2,6,7929,'Heavy Silk Bandage'),(2,6,7934,'Anti-Venom'),(2,6,8386,'Attacking'),(2,6,8737,'Mail'),(2,6,9077,'Leather'),(2,6,9078,'Cloth'),(2,6,9125,'Generic'),(2,6,10840,'Mageweave Bandage'),(2,6,10841,'Heavy Mageweave Bandage'),(2,6,10846,'First Aid'),(2,6,18629,'Runecloth Bandage'),(2,6,18630,'Heavy Runecloth Bandage'),(2,6,20572,'Blood Fury'),(2,6,20573,'Hardiness'),(2,6,20574,'Axe Specialization'),(2,6,21651,'Opening'),(2,6,21652,'Closing'),(2,6,22027,'Remove Insignia'),(2,6,22810,'Opening - No Text'),(2,6,33391,'Journeyman Riding'),(2,6,45462,'Plague Strike'),(2,6,45477,'Icy Touch'),(2,6,45902,'Blood Strike'),(2,6,45903,'Offensive State (DND)'),(2,6,45927,'Summon Friend'),(2,6,47541,'Death Coil'),(2,6,48266,'Blood Presence'),(2,6,49410,'Forceful Deflection'),(2,6,49576,'Death Grip'),(2,6,52665,'Sigil'),(2,6,54562,'Command'),(2,6,59879,'Blood Plague'),(2,6,59921,'Frost Fever'),(2,6,61437,'Opening'),(2,6,61455,'Runic Focus'),(2,7,81,'Dodge'),(2,7,107,'Block'),(2,7,198,'One-Handed Maces'),(2,7,203,'Unarmed'),(2,7,204,'Defense'),(2,7,227,'Staves'),(2,7,331,'Healing Wave'),(2,7,403,'Lightning Bolt'),(2,7,522,'SPELLDEFENSE (DND)'),(2,7,669,'Language Orcish'),(2,7,1843,'Disarm'),(2,7,2382,'Generic'),(2,7,2479,'Honorless Target'),(2,7,3050,'Detect'),(2,7,3365,'Opening'),(2,7,6233,'Closing'),(2,7,6246,'Closing'),(2,7,6247,'Opening'),(2,7,6477,'Opening'),(2,7,6478,'Opening'),(2,7,6603,'Attack'),(2,7,7266,'Duel'),(2,7,7267,'Grovel'),(2,7,7355,'Stuck'),(2,7,8386,'Attacking'),(2,7,9077,'Leather'),(2,7,9078,'Cloth'),(2,7,9116,'Shield'),(2,7,9125,'Generic'),(2,7,20573,'Hardiness'),(2,7,20574,'Axe Specialization'),(2,7,21563,'Command'),(2,7,21651,'Opening'),(2,7,21652,'Closing'),(2,7,22027,'Remove Insignia'),(2,7,22810,'Opening - No Text'),(2,7,27763,'Totem'),(2,7,33697,'Blood Fury'),(2,7,45927,'Summon Friend'),(2,7,61437,'Opening'),(2,9,81,'Dodge'),(2,9,203,'Unarmed'),(2,9,204,'Defense'),(2,9,522,'SPELLDEFENSE (DND)'),(2,9,669,'Language Orcish'),(2,9,686,'Shadow Bolt'),(2,9,687,'Demon Skin'),(2,9,1180,'Daggers'),(2,9,1843,'Disarm'),(2,9,2382,'Generic'),(2,9,2479,'Honorless Target'),(2,9,3050,'Detect'),(2,9,3365,'Opening'),(2,9,5009,'Wands'),(2,9,5019,'Shoot'),(2,9,6233,'Closing'),(2,9,6246,'Closing'),(2,9,6247,'Opening'),(2,9,6477,'Opening'),(2,9,6478,'Opening'),(2,9,6603,'Attack'),(2,9,7266,'Duel'),(2,9,7267,'Grovel'),(2,9,7355,'Stuck'),(2,9,8386,'Attacking'),(2,9,9078,'Cloth'),(2,9,9125,'Generic'),(2,9,20573,'Hardiness'),(2,9,20574,'Axe Specialization'),(2,9,20575,'Command'),(2,9,21651,'Opening'),(2,9,21652,'Closing'),(2,9,22027,'Remove Insignia'),(2,9,22810,'Opening - No Text'),(2,9,33702,'Blood Fury'),(2,9,45927,'Summon Friend'),(2,9,58284,'Chaos Bolt Passive'),(2,9,61437,'Opening'),(3,1,78,'Heroic Strike'),(3,1,81,'Dodge'),(3,1,107,'Block'),(3,1,196,'One-Handed Axes'),(3,1,197,'Two-Handed Axes'),(3,1,198,'One-Handed Maces'),(3,1,203,'Unarmed'),(3,1,204,'Defense'),(3,1,522,'SPELLDEFENSE (DND)'),(3,1,668,'Language Common'),(3,1,672,'Language Dwarven'),(3,1,1843,'Disarm'),(3,1,2382,'Generic'),(3,1,2457,'Battle Stance'),(3,1,2479,'Honorless Target'),(3,1,2481,'Find Treasure'),(3,1,3050,'Detect'),(3,1,3365,'Opening'),(3,1,5301,'Defensive State (DND)'),(3,1,6233,'Closing'),(3,1,6246,'Closing'),(3,1,6247,'Opening'),(3,1,6477,'Opening'),(3,1,6478,'Opening'),(3,1,6603,'Attack'),(3,1,7266,'Duel'),(3,1,7267,'Grovel'),(3,1,7355,'Stuck'),(3,1,8386,'Attacking'),(3,1,8737,'Mail'),(3,1,9077,'Leather'),(3,1,9078,'Cloth'),(3,1,9116,'Shield'),(3,1,9125,'Generic'),(3,1,20594,'Stoneform'),(3,1,20595,'Gun Specialization'),(3,1,20596,'Frost Resistance'),(3,1,21651,'Opening'),(3,1,21652,'Closing'),(3,1,22027,'Remove Insignia'),(3,1,22810,'Opening - No Text'),(3,1,32215,'Victorious State'),(3,1,45927,'Summon Friend'),(3,1,59224,'Mace Specialization'),(3,1,61437,'Opening'),(3,2,81,'Dodge'),(3,2,107,'Block'),(3,2,198,'One-Handed Maces'),(3,2,199,'Two-Handed Maces'),(3,2,203,'Unarmed'),(3,2,204,'Defense'),(3,2,522,'SPELLDEFENSE (DND)'),(3,2,635,'Holy Light'),(3,2,668,'Language Common'),(3,2,672,'Language Dwarven'),(3,2,1843,'Disarm'),(3,2,2382,'Generic'),(3,2,2479,'Honorless Target'),(3,2,2481,'Find Treasure'),(3,2,3050,'Detect'),(3,2,3365,'Opening'),(3,2,6233,'Closing'),(3,2,6246,'Closing'),(3,2,6247,'Opening'),(3,2,6477,'Opening'),(3,2,6478,'Opening'),(3,2,6603,'Attack'),(3,2,7266,'Duel'),(3,2,7267,'Grovel'),(3,2,7355,'Stuck'),(3,2,8386,'Attacking'),(3,2,8737,'Mail'),(3,2,9077,'Leather'),(3,2,9078,'Cloth'),(3,2,9116,'Shield'),(3,2,9125,'Generic'),(3,2,21084,'Seal of Righteousness'),(3,2,20594,'Stoneform'),(3,2,20595,'Gun Specialization'),(3,2,20596,'Frost Resistance'),(3,2,21651,'Opening'),(3,2,21652,'Closing'),(3,2,22027,'Remove Insignia'),(3,2,22810,'Opening - No Text'),(3,2,27762,'Libram'),(3,2,45927,'Summon Friend'),(3,2,59224,'Mace Specialization'),(3,2,61437,'Opening'),(3,3,75,'Auto Shot'),(3,3,81,'Dodge'),(3,3,196,'One-Handed Axes'),(3,3,203,'Unarmed'),(3,3,204,'Defense'),(3,3,266,'Guns'),(3,3,522,'SPELLDEFENSE (DND)'),(3,3,668,'Language Common'),(3,3,672,'Language Dwarven'),(3,3,1843,'Disarm'),(3,3,2382,'Generic'),(3,3,2479,'Honorless Target'),(3,3,2481,'Find Treasure'),(3,3,2973,'Raptor Strike'),(3,3,3050,'Detect'),(3,3,3365,'Opening'),(3,3,6233,'Closing'),(3,3,6246,'Closing'),(3,3,6247,'Opening'),(3,3,6477,'Opening'),(3,3,6478,'Opening'),(3,3,6603,'Attack'),(3,3,7266,'Duel'),(3,3,7267,'Grovel'),(3,3,7355,'Stuck'),(3,3,8386,'Attacking'),(3,3,9077,'Leather'),(3,3,9078,'Cloth'),(3,3,9125,'Generic'),(3,3,13358,'Defensive State (DND)'),(3,3,20594,'Stoneform'),(3,3,20595,'Gun Specialization'),(3,3,20596,'Frost Resistance'),(3,3,21651,'Opening'),(3,3,21652,'Closing'),(3,3,22027,'Remove Insignia'),(3,3,22810,'Opening - No Text'),(3,3,24949,'Defensive State 2 (DND)'),(3,3,34082,'Advantaged State (DND)'),(3,3,45927,'Summon Friend'),(3,3,59224,'Mace Specialization'),(3,3,61437,'Opening'),(3,4,81,'Dodge'),(3,4,203,'Unarmed'),(3,4,204,'Defense'),(3,4,522,'SPELLDEFENSE (DND)'),(3,4,668,'Language Common'),(3,4,672,'Language Dwarven'),(3,4,1180,'Daggers'),(3,4,1752,'Sinister Strike'),(3,4,1843,'Disarm'),(3,4,2098,'Eviscerate'),(3,4,2382,'Generic'),(3,4,2479,'Honorless Target'),(3,4,2481,'Find Treasure'),(3,4,2567,'Thrown'),(3,4,2764,'Throw'),(3,4,3050,'Detect'),(3,4,3365,'Opening'),(3,4,6233,'Closing'),(3,4,6246,'Closing'),(3,4,6247,'Opening'),(3,4,6477,'Opening'),(3,4,6478,'Opening'),(3,4,6603,'Attack'),(3,4,7266,'Duel'),(3,4,7267,'Grovel'),(3,4,7355,'Stuck'),(3,4,8386,'Attacking'),(3,4,9077,'Leather'),(3,4,9078,'Cloth'),(3,4,9125,'Generic'),(3,4,16092,'Defensive State (DND)'),(3,4,20594,'Stoneform'),(3,4,20595,'Gun Specialization'),(3,4,20596,'Frost Resistance'),(3,4,21184,'Rogue Passive (DND)'),(3,4,21651,'Opening'),(3,4,21652,'Closing'),(3,4,22027,'Remove Insignia'),(3,4,22810,'Opening - No Text'),(3,4,45927,'Summon Friend'),(3,4,59224,'Mace Specialization'),(3,4,61437,'Opening'),(3,5,81,'Dodge'),(3,5,198,'One-Handed Maces'),(3,5,203,'Unarmed'),(3,5,204,'Defense'),(3,5,522,'SPELLDEFENSE (DND)'),(3,5,585,'Smite'),(3,5,668,'Language Common'),(3,5,672,'Language Dwarven'),(3,5,1843,'Disarm'),(3,5,2050,'Lesser Heal'),(3,5,2382,'Generic'),(3,5,2479,'Honorless Target'),(3,5,2481,'Find Treasure'),(3,5,3050,'Detect'),(3,5,3365,'Opening'),(3,5,5009,'Wands'),(3,5,5019,'Shoot'),(3,5,6233,'Closing'),(3,5,6246,'Closing'),(3,5,6247,'Opening'),(3,5,6477,'Opening'),(3,5,6478,'Opening'),(3,5,6603,'Attack'),(3,5,7266,'Duel'),(3,5,7267,'Grovel'),(3,5,7355,'Stuck'),(3,5,8386,'Attacking'),(3,5,9078,'Cloth'),(3,5,9125,'Generic'),(3,5,20594,'Stoneform'),(3,5,20595,'Gun Specialization'),(3,5,20596,'Frost Resistance'),(3,5,21651,'Opening'),(3,5,21652,'Closing'),(3,5,22027,'Remove Insignia'),(3,5,22810,'Opening - No Text'),(3,5,45927,'Summon Friend'),(3,5,59224,'Mace Specialization'),(3,5,61437,'Opening'),(3,6,81,'Dodge'),(3,6,196,'One-Handed Axes'),(3,6,197,'Two-Handed Axes'),(3,6,200,'Polearms'),(3,6,201,'One-Handed Swords'),(3,6,202,'Two-Handed Swords'),(3,6,203,'Unarmed'),(3,6,204,'Defense'),(3,6,522,'SPELLDEFENSE (DND)'),(3,6,668,'Language Common'),(3,6,672,'Language Dwarven'),(3,6,674,'Dual Wield'),(3,6,750,'Plate Mail'),(3,6,1843,'Disarm'),(3,6,2382,'Generic'),(3,6,2479,'Honorless Target'),(3,6,2481,'Find Treasure'),(3,6,3050,'Detect'),(3,6,3127,'Parry'),(3,6,3275,'Linen Bandage'),(3,6,3276,'Heavy Linen Bandage'),(3,6,3277,'Wool Bandage'),(3,6,3278,'Heavy Wool Bandage'),(3,6,3365,'Opening'),(3,6,6233,'Closing'),(3,6,6246,'Closing'),(3,6,6247,'Opening'),(3,6,6477,'Opening'),(3,6,6478,'Opening'),(3,6,6603,'Attack'),(3,6,7266,'Duel'),(3,6,7267,'Grovel'),(3,6,7355,'Stuck'),(3,6,7928,'Silk Bandage'),(3,6,7929,'Heavy Silk Bandage'),(3,6,7934,'Anti-Venom'),(3,6,8386,'Attacking'),(3,6,8737,'Mail'),(3,6,9077,'Leather'),(3,6,9078,'Cloth'),(3,6,9125,'Generic'),(3,6,10840,'Mageweave Bandage'),(3,6,10841,'Heavy Mageweave Bandage'),(3,6,10846,'First Aid'),(3,6,18629,'Runecloth Bandage'),(3,6,18630,'Heavy Runecloth Bandage'),(3,6,20594,'Stoneform'),(3,6,20595,'Gun Specialization'),(3,6,20596,'Frost Resistance'),(3,6,21651,'Opening'),(3,6,21652,'Closing'),(3,6,22027,'Remove Insignia'),(3,6,22810,'Opening - No Text'),(3,6,33391,'Journeyman Riding'),(3,6,45462,'Plague Strike'),(3,6,45477,'Icy Touch'),(3,6,45902,'Blood Strike'),(3,6,45903,'Offensive State (DND)'),(3,6,45927,'Summon Friend'),(3,6,47541,'Death Coil'),(3,6,48266,'Blood Presence'),(3,6,49410,'Forceful Deflection'),(3,6,49576,'Death Grip'),(3,6,52665,'Sigil'),(3,6,59224,'Mace Specialization'),(3,6,59879,'Blood Plague'),(3,6,59921,'Frost Fever'),(3,6,61437,'Opening'),(3,6,61455,'Runic Focus'),(4,1,78,'Heroic Strike'),(4,1,81,'Dodge'),(4,1,107,'Block'),(4,1,198,'One-Handed Maces'),(4,1,201,'One-Handed Swords'),(4,1,203,'Unarmed'),(4,1,204,'Defense'),(4,1,522,'SPELLDEFENSE (DND)'),(4,1,668,'Language Common'),(4,1,671,'Language Darnassian'),(4,1,1180,'Daggers'),(4,1,1843,'Disarm'),(4,1,2382,'Generic'),(4,1,2457,'Battle Stance'),(4,1,2479,'Honorless Target'),(4,1,3050,'Detect'),(4,1,3365,'Opening'),(4,1,5301,'Defensive State (DND)'),(4,1,6233,'Closing'),(4,1,6246,'Closing'),(4,1,6247,'Opening'),(4,1,6477,'Opening'),(4,1,6478,'Opening'),(4,1,6603,'Attack'),(4,1,7266,'Duel'),(4,1,7267,'Grovel'),(4,1,7355,'Stuck'),(4,1,8386,'Attacking'),(4,1,8737,'Mail'),(4,1,9077,'Leather'),(4,1,9078,'Cloth'),(4,1,9116,'Shield'),(4,1,9125,'Generic'),(4,1,20582,'Quickness'),(4,1,20583,'Nature Resistance'),(4,1,20585,'Wisp Spirit'),(4,1,21651,'Opening'),(4,1,21652,'Closing'),(4,1,22027,'Remove Insignia'),(4,1,22810,'Opening - No Text'),(4,1,32215,'Victorious State'),(4,1,45927,'Summon Friend'),(4,1,58984,'Shadowmelt'),(4,1,61437,'Opening'),(4,3,75,'Auto Shot'),(4,3,81,'Dodge'),(4,3,203,'Unarmed'),(4,3,204,'Defense'),(4,3,264,'Bows'),(4,3,522,'SPELLDEFENSE (DND)'),(4,3,668,'Language Common'),(4,3,671,'Language Darnassian'),(4,3,1180,'Daggers'),(4,3,1843,'Disarm'),(4,3,2382,'Generic'),(4,3,2479,'Honorless Target'),(4,3,2973,'Raptor Strike'),(4,3,3050,'Detect'),(4,3,3365,'Opening'),(4,3,6233,'Closing'),(4,3,6246,'Closing'),(4,3,6247,'Opening'),(4,3,6477,'Opening'),(4,3,6478,'Opening'),(4,3,6603,'Attack'),(4,3,7266,'Duel'),(4,3,7267,'Grovel'),(4,3,7355,'Stuck'),(4,3,8386,'Attacking'),(4,3,9077,'Leather'),(4,3,9078,'Cloth'),(4,3,9125,'Generic'),(4,3,13358,'Defensive State (DND)'),(4,3,20582,'Quickness'),(4,3,20583,'Nature Resistance'),(4,3,20585,'Wisp Spirit'),(4,3,21651,'Opening'),(4,3,21652,'Closing'),(4,3,22027,'Remove Insignia'),(4,3,22810,'Opening - No Text'),(4,3,24949,'Defensive State 2 (DND)'),(4,3,34082,'Advantaged State (DND)'),(4,3,45927,'Summon Friend'),(4,3,58984,'Shadowmelt'),(4,3,61437,'Opening'),(4,4,81,'Dodge'),(4,4,203,'Unarmed'),(4,4,204,'Defense'),(4,4,522,'SPELLDEFENSE (DND)'),(4,4,668,'Language Common'),(4,4,671,'Language Darnassian'),(4,4,1180,'Daggers'),(4,4,1752,'Sinister Strike'),(4,4,1843,'Disarm'),(4,4,2098,'Eviscerate'),(4,4,2382,'Generic'),(4,4,2479,'Honorless Target'),(4,4,2567,'Thrown'),(4,4,2764,'Throw'),(4,4,3050,'Detect'),(4,4,3365,'Opening'),(4,4,6233,'Closing'),(4,4,6246,'Closing'),(4,4,6247,'Opening'),(4,4,6477,'Opening'),(4,4,6478,'Opening'),(4,4,6603,'Attack'),(4,4,7266,'Duel'),(4,4,7267,'Grovel'),(4,4,7355,'Stuck'),(4,4,8386,'Attacking'),(4,4,9077,'Leather'),(4,4,9078,'Cloth'),(4,4,9125,'Generic'),(4,4,16092,'Defensive State (DND)'),(4,4,20582,'Quickness'),(4,4,20583,'Nature Resistance'),(4,4,20585,'Wisp Spirit'),(4,4,21184,'Rogue Passive (DND)'),(4,4,21651,'Opening'),(4,4,21652,'Closing'),(4,4,22027,'Remove Insignia'),(4,4,22810,'Opening - No Text'),(4,4,45927,'Summon Friend'),(4,4,58984,'Shadowmelt'),(4,4,61437,'Opening'),(4,5,81,'Dodge'),(4,5,198,'One-Handed Maces'),(4,5,203,'Unarmed'),(4,5,204,'Defense'),(4,5,522,'SPELLDEFENSE (DND)'),(4,5,585,'Smite'),(4,5,668,'Language Common'),(4,5,671,'Language Darnassian'),(4,5,1843,'Disarm'),(4,5,2050,'Lesser Heal'),(4,5,2382,'Generic'),(4,5,2479,'Honorless Target'),(4,5,3050,'Detect'),(4,5,3365,'Opening'),(4,5,5009,'Wands'),(4,5,5019,'Shoot'),(4,5,6233,'Closing'),(4,5,6246,'Closing'),(4,5,6247,'Opening'),(4,5,6477,'Opening'),(4,5,6478,'Opening'),(4,5,6603,'Attack'),(4,5,7266,'Duel'),(4,5,7267,'Grovel'),(4,5,7355,'Stuck'),(4,5,8386,'Attacking'),(4,5,9078,'Cloth'),(4,5,9125,'Generic'),(4,5,20582,'Quickness'),(4,5,20583,'Nature Resistance'),(4,5,20585,'Wisp Spirit'),(4,5,21651,'Opening'),(4,5,21652,'Closing'),(4,5,22027,'Remove Insignia'),(4,5,22810,'Opening - No Text'),(4,5,45927,'Summon Friend'),(4,5,58984,'Shadowmelt'),(4,5,61437,'Opening'),(4,6,81,'Dodge'),(4,6,196,'One-Handed Axes'),(4,6,197,'Two-Handed Axes'),(4,6,200,'Polearms'),(4,6,201,'One-Handed Swords'),(4,6,202,'Two-Handed Swords'),(4,6,203,'Unarmed'),(4,6,204,'Defense'),(4,6,522,'SPELLDEFENSE (DND)'),(4,6,668,'Language Common'),(4,6,671,'Language Darnassian'),(4,6,674,'Dual Wield'),(4,6,750,'Plate Mail'),(4,6,1843,'Disarm'),(4,6,2382,'Generic'),(4,6,2479,'Honorless Target'),(4,6,3050,'Detect'),(4,6,3127,'Parry'),(4,6,3275,'Linen Bandage'),(4,6,3276,'Heavy Linen Bandage'),(4,6,3277,'Wool Bandage'),(4,6,3278,'Heavy Wool Bandage'),(4,6,3365,'Opening'),(4,6,6233,'Closing'),(4,6,6246,'Closing'),(4,6,6247,'Opening'),(4,6,6477,'Opening'),(4,6,6478,'Opening'),(4,6,6603,'Attack'),(4,6,7266,'Duel'),(4,6,7267,'Grovel'),(4,6,7355,'Stuck'),(4,6,7928,'Silk Bandage'),(4,6,7929,'Heavy Silk Bandage'),(4,6,7934,'Anti-Venom'),(4,6,8386,'Attacking'),(4,6,8737,'Mail'),(4,6,9077,'Leather'),(4,6,9078,'Cloth'),(4,6,9125,'Generic'),(4,6,10840,'Mageweave Bandage'),(4,6,10841,'Heavy Mageweave Bandage'),(4,6,10846,'First Aid'),(4,6,18629,'Runecloth Bandage'),(4,6,18630,'Heavy Runecloth Bandage'),(4,6,20582,'Quickness'),(4,6,20583,'Nature Resistance'),(4,6,20585,'Wisp Spirit'),(4,6,21651,'Opening'),(4,6,21652,'Closing'),(4,6,22027,'Remove Insignia'),(4,6,22810,'Opening - No Text'),(4,6,33391,'Journeyman Riding'),(4,6,45462,'Plague Strike'),(4,6,45477,'Icy Touch'),(4,6,45902,'Blood Strike'),(4,6,45903,'Offensive State (DND)'),(4,6,45927,'Summon Friend'),(4,6,47541,'Death Coil'),(4,6,48266,'Blood Presence'),(4,6,49410,'Forceful Deflection'),(4,6,49576,'Death Grip'),(4,6,52665,'Sigil'),(4,6,58984,'Shadowmeld'),(4,6,59879,'Blood Plague'),(4,6,59921,'Frost Fever'),(4,6,61437,'Opening'),(4,6,61455,'Runic Focus'),(4,11,81,'Dodge'),(4,11,203,'Unarmed'),(4,11,204,'Defense'),(4,11,227,'Staves'),(4,11,522,'SPELLDEFENSE (DND)'),(4,11,668,'Language Common'),(4,11,671,'Language Darnassian'),(4,11,1180,'Daggers'),(4,11,1843,'Disarm'),(4,11,2382,'Generic'),(4,11,2479,'Honorless Target'),(4,11,3050,'Detect'),(4,11,3365,'Opening'),(4,11,5176,'Wrath'),(4,11,5185,'Healing Touch'),(4,11,6233,'Closing'),(4,11,6246,'Closing'),(4,11,6247,'Opening'),(4,11,6477,'Opening'),(4,11,6478,'Opening'),(4,11,6603,'Attack'),(4,11,7266,'Duel'),(4,11,7267,'Grovel'),(4,11,7355,'Stuck'),(4,11,8386,'Attacking'),(4,11,9077,'Leather'),(4,11,9078,'Cloth'),(4,11,9125,'Generic'),(4,11,20582,'Quickness'),(4,11,20583,'Nature Resistance'),(4,11,20585,'Wisp Spirit'),(4,11,21651,'Opening'),(4,11,21652,'Closing'),(4,11,22027,'Remove Insignia'),(4,11,22810,'Opening - No Text'),(4,11,27764,'Fetish'),(4,11,45927,'Summon Friend'),(4,11,58984,'Shadowmelt'),(4,11,61437,'Opening'),(5,1,78,'Heroic Strike'),(5,1,81,'Dodge'),(5,1,107,'Block'),(5,1,201,'One-Handed Swords'),(5,1,202,'Two-Handed Swords'),(5,1,203,'Unarmed'),(5,1,204,'Defense'),(5,1,522,'SPELLDEFENSE (DND)'),(5,1,669,'Language Orcish'),(5,1,1180,'Daggers'),(5,1,1843,'Disarm'),(5,1,2382,'Generic'),(5,1,2457,'Battle Stance'),(5,1,2479,'Honorless Target'),(5,1,3050,'Detect'),(5,1,3365,'Opening'),(5,1,5227,'Underwater Breathing'),(5,1,5301,'Defensive State (DND)'),(5,1,6233,'Closing'),(5,1,6246,'Closing'),(5,1,6247,'Opening'),(5,1,6477,'Opening'),(5,1,6478,'Opening'),(5,1,6603,'Attack'),(5,1,7266,'Duel'),(5,1,7267,'Grovel'),(5,1,7355,'Stuck'),(5,1,7744,'Will of the Forsaken'),(5,1,8386,'Attacking'),(5,1,8737,'Mail'),(5,1,9077,'Leather'),(5,1,9078,'Cloth'),(5,1,9116,'Shield'),(5,1,9125,'Generic'),(5,1,17737,'Language Gutterspeak'),(5,1,20577,'Cannibalize'),(5,1,20579,'Shadow Resistance'),(5,1,21651,'Opening'),(5,1,21652,'Closing'),(5,1,22027,'Remove Insignia'),(5,1,22810,'Opening - No Text'),(5,1,32215,'Victorious State'),(5,1,45927,'Summon Friend'),(5,1,61437,'Opening'),(5,4,81,'Dodge'),(5,4,203,'Unarmed'),(5,4,204,'Defense'),(5,4,522,'SPELLDEFENSE (DND)'),(5,4,669,'Language Orcish'),(5,4,1180,'Daggers'),(5,4,1752,'Sinister Strike'),(5,4,1843,'Disarm'),(5,4,2098,'Eviscerate'),(5,4,2382,'Generic'),(5,4,2479,'Honorless Target'),(5,4,2567,'Thrown'),(5,4,2764,'Throw'),(5,4,3050,'Detect'),(5,4,3365,'Opening'),(5,4,5227,'Underwater Breathing'),(5,4,6233,'Closing'),(5,4,6246,'Closing'),(5,4,6247,'Opening'),(5,4,6477,'Opening'),(5,4,6478,'Opening'),(5,4,6603,'Attack'),(5,4,7266,'Duel'),(5,4,7267,'Grovel'),(5,4,7355,'Stuck'),(5,4,7744,'Will of the Forsaken'),(5,4,8386,'Attacking'),(5,4,9077,'Leather'),(5,4,9078,'Cloth'),(5,4,9125,'Generic'),(5,4,16092,'Defensive State (DND)'),(5,4,17737,'Language Gutterspeak'),(5,4,20577,'Cannibalize'),(5,4,20579,'Shadow Resistance'),(5,4,21184,'Rogue Passive (DND)'),(5,4,21651,'Opening'),(5,4,21652,'Closing'),(5,4,22027,'Remove Insignia'),(5,4,22810,'Opening - No Text'),(5,4,45927,'Summon Friend'),(5,4,61437,'Opening'),(5,5,81,'Dodge'),(5,5,198,'One-Handed Maces'),(5,5,203,'Unarmed'),(5,5,204,'Defense'),(5,5,522,'SPELLDEFENSE (DND)'),(5,5,585,'Smite'),(5,5,669,'Language Orcish'),(5,5,1843,'Disarm'),(5,5,2050,'Lesser Heal'),(5,5,2382,'Generic'),(5,5,2479,'Honorless Target'),(5,5,3050,'Detect'),(5,5,3365,'Opening'),(5,5,5009,'Wands'),(5,5,5019,'Shoot'),(5,5,5227,'Underwater Breathing'),(5,5,6233,'Closing'),(5,5,6246,'Closing'),(5,5,6247,'Opening'),(5,5,6477,'Opening'),(5,5,6478,'Opening'),(5,5,6603,'Attack'),(5,5,7266,'Duel'),(5,5,7267,'Grovel'),(5,5,7355,'Stuck'),(5,5,7744,'Will of the Forsaken'),(5,5,8386,'Attacking'),(5,5,9078,'Cloth'),(5,5,9125,'Generic'),(5,5,17737,'Language Gutterspeak'),(5,5,20577,'Cannibalize'),(5,5,20579,'Shadow Resistance'),(5,5,21651,'Opening'),(5,5,21652,'Closing'),(5,5,22027,'Remove Insignia'),(5,5,22810,'Opening - No Text'),(5,5,45927,'Summon Friend'),(5,5,61437,'Opening'),(5,6,81,'Dodge'),(5,6,196,'One-Handed Axes'),(5,6,197,'Two-Handed Axes'),(5,6,200,'Polearms'),(5,6,201,'One-Handed Swords'),(5,6,202,'Two-Handed Swords'),(5,6,203,'Unarmed'),(5,6,204,'Defense'),(5,6,522,'SPELLDEFENSE (DND)'),(5,6,669,'Language Orcish'),(5,6,674,'Dual Wield'),(5,6,750,'Plate Mail'),(5,6,1843,'Disarm'),(5,6,2382,'Generic'),(5,6,2479,'Honorless Target'),(5,6,3050,'Detect'),(5,6,3127,'Parry'),(5,6,3275,'Linen Bandage'),(5,6,3276,'Heavy Linen Bandage'),(5,6,3277,'Wool Bandage'),(5,6,3278,'Heavy Wool Bandage'),(5,6,3365,'Opening'),(5,6,5227,'Underwater Breathing'),(5,6,6233,'Closing'),(5,6,6246,'Closing'),(5,6,6247,'Opening'),(5,6,6477,'Opening'),(5,6,6478,'Opening'),(5,6,6603,'Attack'),(5,6,7266,'Duel'),(5,6,7267,'Grovel'),(5,6,7355,'Stuck'),(5,6,7744,'Will of the Forsaken'),(5,6,7928,'Silk Bandage'),(5,6,7929,'Heavy Silk Bandage'),(5,6,7934,'Anti-Venom'),(5,6,8386,'Attacking'),(5,6,8737,'Mail'),(5,6,9077,'Leather'),(5,6,9078,'Cloth'),(5,6,9125,'Generic'),(5,6,10840,'Mageweave Bandage'),(5,6,10841,'Heavy Mageweave Bandage'),(5,6,10846,'First Aid'),(5,6,17737,'Language Gutterspeak'),(5,6,18629,'Runecloth Bandage'),(5,6,18630,'Heavy Runecloth Bandage'),(5,6,20577,'Cannibalize'),(5,6,20579,'Shadow Resistance'),(5,6,21651,'Opening'),(5,6,21652,'Closing'),(5,6,22027,'Remove Insignia'),(5,6,22810,'Opening - No Text'),(5,6,33391,'Journeyman Riding'),(5,6,45462,'Plague Strike'),(5,6,45477,'Icy Touch'),(5,6,45902,'Blood Strike'),(5,6,45903,'Offensive State (DND)'),(5,6,45927,'Summon Friend'),(5,6,47541,'Death Coil'),(5,6,48266,'Blood Presence'),(5,6,49410,'Forceful Deflection'),(5,6,49576,'Death Grip'),(5,6,52665,'Sigil'),(5,6,59879,'Blood Plague'),(5,6,59921,'Frost Fever'),(5,6,61437,'Opening'),(5,6,61455,'Runic Focus'),(5,8,81,'Dodge'),(5,8,133,'Fireball'),(5,8,168,'Frost Armor'),(5,8,203,'Unarmed'),(5,8,204,'Defense'),(5,8,227,'Staves'),(5,8,522,'SPELLDEFENSE (DND)'),(5,8,669,'Language Orcish'),(5,8,1843,'Disarm'),(5,8,2382,'Generic'),(5,8,2479,'Honorless Target'),(5,8,3050,'Detect'),(5,8,3365,'Opening'),(5,8,5009,'Wands'),(5,8,5019,'Shoot'),(5,8,5227,'Underwater Breathing'),(5,8,6233,'Closing'),(5,8,6246,'Closing'),(5,8,6247,'Opening'),(5,8,6477,'Opening'),(5,8,6478,'Opening'),(5,8,6603,'Attack'),(5,8,7266,'Duel'),(5,8,7267,'Grovel'),(5,8,7355,'Stuck'),(5,8,7744,'Will of the Forsaken'),(5,8,8386,'Attacking'),(5,8,9078,'Cloth'),(5,8,9125,'Generic'),(5,8,17737,'Language Gutterspeak'),(5,8,20577,'Cannibalize'),(5,8,20579,'Shadow Resistance'),(5,8,21651,'Opening'),(5,8,21652,'Closing'),(5,8,22027,'Remove Insignia'),(5,8,22810,'Opening - No Text'),(5,8,45927,'Summon Friend'),(5,8,61437,'Opening'),(5,9,81,'Dodge'),(5,9,203,'Unarmed'),(5,9,204,'Defense'),(5,9,522,'SPELLDEFENSE (DND)'),(5,9,669,'Language Orcish'),(5,9,686,'Shadow Bolt'),(5,9,687,'Demon Skin'),(5,9,1180,'Daggers'),(5,9,1843,'Disarm'),(5,9,2382,'Generic'),(5,9,2479,'Honorless Target'),(5,9,3050,'Detect'),(5,9,3365,'Opening'),(5,9,5009,'Wands'),(5,9,5019,'Shoot'),(5,9,5227,'Underwater Breathing'),(5,9,6233,'Closing'),(5,9,6246,'Closing'),(5,9,6247,'Opening'),(5,9,6477,'Opening'),(5,9,6478,'Opening'),(5,9,6603,'Attack'),(5,9,7266,'Duel'),(5,9,7267,'Grovel'),(5,9,7355,'Stuck'),(5,9,7744,'Will of the Forsaken'),(5,9,8386,'Attacking'),(5,9,9078,'Cloth'),(5,9,9125,'Generic'),(5,9,17737,'Language Gutterspeak'),(5,9,20577,'Cannibalize'),(5,9,20579,'Shadow Resistance'),(5,9,21651,'Opening'),(5,9,21652,'Closing'),(5,9,22027,'Remove Insignia'),(5,9,22810,'Opening - No Text'),(5,9,45927,'Summon Friend'),(1,9,58284,'Chaos Bolt Passive'),(5,9,61437,'Opening'),(6,1,78,'Heroic Strike'),(6,1,81,'Dodge'),(6,1,107,'Block'),(6,1,196,'One-Handed Axes'),(6,1,198,'One-Handed Maces'),(6,1,199,'Two-Handed Maces'),(6,1,203,'Unarmed'),(6,1,204,'Defense'),(6,1,522,'SPELLDEFENSE (DND)'),(6,1,669,'Language Orcish'),(6,1,670,'Language Taurahe'),(6,1,1843,'Disarm'),(6,1,2382,'Generic'),(6,1,2457,'Battle Stance'),(6,1,2479,'Honorless Target'),(6,1,3050,'Detect'),(6,1,3365,'Opening'),(6,1,5301,'Defensive State (DND)'),(6,1,6233,'Closing'),(6,1,6246,'Closing'),(6,1,6247,'Opening'),(6,1,6477,'Opening'),(6,1,6478,'Opening'),(6,1,6603,'Attack'),(6,1,7266,'Duel'),(6,1,7267,'Grovel'),(6,1,7355,'Stuck'),(6,1,8386,'Attacking'),(6,1,8737,'Mail'),(6,1,9077,'Leather'),(6,1,9078,'Cloth'),(6,1,9116,'Shield'),(6,1,9125,'Generic'),(6,1,20549,'War Stomp'),(6,1,20550,'Endurance'),(6,1,20551,'Nature Resistance'),(6,1,20552,'Cultivation'),(6,1,21651,'Opening'),(6,1,21652,'Closing'),(6,1,22027,'Remove Insignia'),(6,1,22810,'Opening - No Text'),(6,1,32215,'Victorious State'),(6,1,45927,'Summon Friend'),(6,1,61437,'Opening'),(6,3,75,'Auto Shot'),(6,3,81,'Dodge'),(6,3,196,'One-Handed Axes'),(6,3,203,'Unarmed'),(6,3,204,'Defense'),(6,3,266,'Guns'),(6,3,522,'SPELLDEFENSE (DND)'),(6,3,669,'Language Orcish'),(6,3,670,'Language Taurahe'),(6,3,1843,'Disarm'),(6,3,2382,'Generic'),(6,3,2479,'Honorless Target'),(6,3,2973,'Raptor Strike'),(6,3,3050,'Detect'),(6,3,3365,'Opening'),(6,3,6233,'Closing'),(6,3,6246,'Closing'),(6,3,6247,'Opening'),(6,3,6477,'Opening'),(6,3,6478,'Opening'),(6,3,6603,'Attack'),(6,3,7266,'Duel'),(6,3,7267,'Grovel'),(6,3,7355,'Stuck'),(6,3,8386,'Attacking'),(6,3,9077,'Leather'),(6,3,9078,'Cloth'),(6,3,9125,'Generic'),(6,3,13358,'Defensive State (DND)'),(6,3,20549,'War Stomp'),(6,3,20550,'Endurance'),(6,3,20551,'Nature Resistance'),(6,3,20552,'Cultivation'),(6,3,21651,'Opening'),(6,3,21652,'Closing'),(6,3,22027,'Remove Insignia'),(6,3,22810,'Opening - No Text'),(6,3,24949,'Defensive State 2 (DND)'),(6,3,34082,'Advantaged State (DND)'),(6,3,45927,'Summon Friend'),(6,3,61437,'Opening'),(6,6,81,'Dodge'),(6,6,196,'One-Handed Axes'),(6,6,197,'Two-Handed Axes'),(6,6,200,'Polearms'),(6,6,201,'One-Handed Swords'),(6,6,202,'Two-Handed Swords'),(6,6,203,'Unarmed'),(6,6,204,'Defense'),(6,6,522,'SPELLDEFENSE (DND)'),(6,6,669,'Language Orcish'),(6,6,670,'Language Taurahe'),(6,6,674,'Dual Wield'),(6,6,750,'Plate Mail'),(6,6,1843,'Disarm'),(6,6,2382,'Generic'),(6,6,2479,'Honorless Target'),(6,6,3050,'Detect'),(6,6,3127,'Parry'),(6,6,3275,'Linen Bandage'),(6,6,3276,'Heavy Linen Bandage'),(6,6,3277,'Wool Bandage'),(6,6,3278,'Heavy Wool Bandage'),(6,6,3365,'Opening'),(6,6,6233,'Closing'),(6,6,6246,'Closing'),(6,6,6247,'Opening'),(6,6,6477,'Opening'),(6,6,6478,'Opening'),(6,6,6603,'Attack'),(6,6,7266,'Duel'),(6,6,7267,'Grovel'),(6,6,7355,'Stuck'),(6,6,7928,'Silk Bandage'),(6,6,7929,'Heavy Silk Bandage'),(6,6,7934,'Anti-Venom'),(6,6,8386,'Attacking'),(6,6,8737,'Mail'),(6,6,9077,'Leather'),(6,6,9078,'Cloth'),(6,6,9125,'Generic'),(6,6,10840,'Mageweave Bandage'),(6,6,10841,'Heavy Mageweave Bandage'),(6,6,10846,'First Aid'),(6,6,18629,'Runecloth Bandage'),(6,6,18630,'Heavy Runecloth Bandage'),(6,6,20549,'War Stomp'),(6,6,20550,'Endurance'),(6,6,20551,'Nature Resistance'),(6,6,20552,'Cultivation'),(6,6,21651,'Opening'),(6,6,21652,'Closing'),(6,6,22027,'Remove Insignia'),(6,6,22810,'Opening - No Text'),(6,6,33391,'Journeyman Riding'),(6,6,45462,'Plague Strike'),(6,6,45477,'Icy Touch'),(6,6,45902,'Blood Strike'),(6,6,45903,'Offensive State (DND)'),(6,6,45927,'Summon Friend'),(6,6,47541,'Death Coil'),(6,6,48266,'Blood Presence'),(6,6,49410,'Forceful Deflection'),(6,6,49576,'Death Grip'),(6,6,52665,'Sigil'),(6,6,59879,'Blood Plague'),(6,6,59921,'Frost Fever'),(6,6,61437,'Opening'),(6,6,61455,'Runic Focus'),(6,7,81,'Dodge'),(6,7,107,'Block'),(6,7,198,'One-Handed Maces'),(6,7,203,'Unarmed'),(6,7,204,'Defense'),(6,7,227,'Staves'),(6,7,331,'Healing Wave'),(6,7,403,'Lightning Bolt'),(6,7,522,'SPELLDEFENSE (DND)'),(6,7,669,'Language Orcish'),(6,7,670,'Language Taurahe'),(6,7,1843,'Disarm'),(6,7,2382,'Generic'),(6,7,2479,'Honorless Target'),(6,7,3050,'Detect'),(6,7,3365,'Opening'),(6,7,6233,'Closing'),(6,7,6246,'Closing'),(6,7,6247,'Opening'),(6,7,6477,'Opening'),(6,7,6478,'Opening'),(6,7,6603,'Attack'),(6,7,7266,'Duel'),(6,7,7267,'Grovel'),(6,7,7355,'Stuck'),(6,7,8386,'Attacking'),(6,7,9077,'Leather'),(6,7,9078,'Cloth'),(6,7,9116,'Shield'),(6,7,9125,'Generic'),(6,7,20549,'War Stomp'),(6,7,20550,'Endurance'),(6,7,20551,'Nature Resistance'),(6,7,20552,'Cultivation'),(6,7,21651,'Opening'),(6,7,21652,'Closing'),(6,7,22027,'Remove Insignia'),(6,7,22810,'Opening - No Text'),(6,7,27763,'Totem'),(6,7,45927,'Summon Friend'),(6,7,61437,'Opening'),(6,11,81,'Dodge'),(6,11,198,'One-Handed Maces'),(6,11,203,'Unarmed'),(6,11,204,'Defense'),(6,11,227,'Staves'),(6,11,522,'SPELLDEFENSE (DND)'),(6,11,669,'Language Orcish'),(6,11,670,'Language Taurahe'),(6,11,1843,'Disarm'),(6,11,2382,'Generic'),(6,11,2479,'Honorless Target'),(6,11,3050,'Detect'),(6,11,3365,'Opening'),(6,11,5176,'Wrath'),(6,11,5185,'Healing Touch'),(6,11,6233,'Closing'),(6,11,6246,'Closing'),(6,11,6247,'Opening'),(6,11,6477,'Opening'),(6,11,6478,'Opening'),(6,11,6603,'Attack'),(6,11,7266,'Duel'),(6,11,7267,'Grovel'),(6,11,7355,'Stuck'),(6,11,8386,'Attacking'),(6,11,9077,'Leather'),(6,11,9078,'Cloth'),(6,11,9125,'Generic'),(6,11,20549,'War Stomp'),(6,11,20550,'Endurance'),(6,11,20551,'Nature Resistance'),(6,11,20552,'Cultivation'),(6,11,21651,'Opening'),(6,11,21652,'Closing'),(6,11,22027,'Remove Insignia'),(6,11,22810,'Opening - No Text'),(6,11,27764,'Fetish'),(6,11,45927,'Summon Friend'),(6,11,61437,'Opening'),(7,1,78,'Heroic Strike'),(7,1,81,'Dodge'),(7,1,107,'Block'),(7,1,198,'One-Handed Maces'),(7,1,201,'One-Handed Swords'),(7,1,203,'Unarmed'),(7,1,204,'Defense'),(7,1,522,'SPELLDEFENSE (DND)'),(7,1,668,'Language Common'),(7,1,1180,'Daggers'),(7,1,1843,'Disarm'),(7,1,2382,'Generic'),(7,1,2457,'Battle Stance'),(7,1,2479,'Honorless Target'),(7,1,3050,'Detect'),(7,1,3365,'Opening'),(7,1,5301,'Defensive State (DND)'),(7,1,6233,'Closing'),(7,1,6246,'Closing'),(7,1,6247,'Opening'),(7,1,6477,'Opening'),(7,1,6478,'Opening'),(7,1,6603,'Attack'),(7,1,7266,'Duel'),(7,1,7267,'Grovel'),(7,1,7340,'Language Gnomish'),(7,1,7355,'Stuck'),(7,1,8386,'Attacking'),(7,1,8737,'Mail'),(7,1,9077,'Leather'),(7,1,9078,'Cloth'),(7,1,9116,'Shield'),(7,1,9125,'Generic'),(7,1,20589,'Escape Artist'),(7,1,20591,'Expansive Mind'),(7,1,20592,'Arcane Resistance'),(7,1,20593,'Engineering Specialization'),(7,1,21651,'Opening'),(7,1,21652,'Closing'),(7,1,22027,'Remove Insignia'),(7,1,22810,'Opening - No Text'),(7,1,32215,'Victorious State'),(7,1,45927,'Summon Friend'),(7,1,61437,'Opening'),(7,4,81,'Dodge'),(7,4,203,'Unarmed'),(7,4,204,'Defense'),(7,4,522,'SPELLDEFENSE (DND)'),(7,4,668,'Language Common'),(7,4,1180,'Daggers'),(7,4,1752,'Sinister Strike'),(7,4,1843,'Disarm'),(7,4,2098,'Eviscerate'),(7,4,2382,'Generic'),(7,4,2479,'Honorless Target'),(7,4,2567,'Thrown'),(7,4,2764,'Throw'),(7,4,3050,'Detect'),(7,4,3365,'Opening'),(7,4,6233,'Closing'),(7,4,6246,'Closing'),(7,4,6247,'Opening'),(7,4,6477,'Opening'),(7,4,6478,'Opening'),(7,4,6603,'Attack'),(7,4,7266,'Duel'),(7,4,7267,'Grovel'),(7,4,7340,'Language Gnomish'),(7,4,7355,'Stuck'),(7,4,8386,'Attacking'),(7,4,9077,'Leather'),(7,4,9078,'Cloth'),(7,4,9125,'Generic'),(7,4,16092,'Defensive State (DND)'),(7,4,20589,'Escape Artist'),(7,4,20591,'Expansive Mind'),(7,4,20592,'Arcane Resistance'),(7,4,20593,'Engineering Specialization'),(7,4,21184,'Rogue Passive (DND)'),(7,4,21651,'Opening'),(7,4,21652,'Closing'),(7,4,22027,'Remove Insignia'),(7,4,22810,'Opening - No Text'),(7,4,45927,'Summon Friend'),(7,4,61437,'Opening'),(7,6,81,'Dodge'),(7,6,196,'One-Handed Axes'),(7,6,197,'Two-Handed Axes'),(7,6,200,'Polearms'),(7,6,201,'One-Handed Swords'),(7,6,202,'Two-Handed Swords'),(7,6,203,'Unarmed'),(7,6,204,'Defense'),(7,6,522,'SPELLDEFENSE (DND)'),(7,6,668,'Language Common'),(7,6,674,'Dual Wield'),(7,6,750,'Plate Mail'),(7,6,1843,'Disarm'),(7,6,2382,'Generic'),(7,6,2479,'Honorless Target'),(7,6,3050,'Detect'),(7,6,3127,'Parry'),(7,6,3275,'Linen Bandage'),(7,6,3276,'Heavy Linen Bandage'),(7,6,3277,'Wool Bandage'),(7,6,3278,'Heavy Wool Bandage'),(7,6,3365,'Opening'),(7,6,6233,'Closing'),(7,6,6246,'Closing'),(7,6,6247,'Opening'),(7,6,6477,'Opening'),(7,6,6478,'Opening'),(7,6,6603,'Attack'),(7,6,7266,'Duel'),(7,6,7267,'Grovel'),(7,6,7340,'Language Gnomish'),(7,6,7355,'Stuck'),(7,6,7928,'Silk Bandage'),(7,6,7929,'Heavy Silk Bandage'),(7,6,7934,'Anti-Venom'),(7,6,8386,'Attacking'),(7,6,8737,'Mail'),(7,6,9077,'Leather'),(7,6,9078,'Cloth'),(7,6,9125,'Generic'),(7,6,10840,'Mageweave Bandage'),(7,6,10841,'Heavy Mageweave Bandage'),(7,6,10846,'First Aid'),(7,6,18629,'Runecloth Bandage'),(7,6,18630,'Heavy Runecloth Bandage'),(7,6,20589,'Escape Artist'),(7,6,20591,'Expansive Mind'),(7,6,20592,'Arcane Resistance'),(7,6,20593,'Engineering Specialization'),(7,6,21651,'Opening'),(7,6,21652,'Closing'),(7,6,22027,'Remove Insignia'),(7,6,22810,'Opening - No Text'),(7,6,33391,'Journeyman Riding'),(7,6,45462,'Plague Strike'),(7,6,45477,'Icy Touch'),(7,6,45902,'Blood Strike'),(7,6,45903,'Offensive State (DND)'),(7,6,45927,'Summon Friend'),(7,6,47541,'Death Coil'),(7,6,48266,'Blood Presence'),(7,6,49410,'Forceful Deflection'),(7,6,49576,'Death Grip'),(7,6,52665,'Sigil'),(7,6,59879,'Blood Plague'),(7,6,59921,'Frost Fever'),(7,6,61437,'Opening'),(7,6,61455,'Runic Focus'),(7,8,81,'Dodge'),(7,8,133,'Fireball'),(7,8,168,'Frost Armor'),(7,8,203,'Unarmed'),(7,8,204,'Defense'),(7,8,227,'Staves'),(7,8,522,'SPELLDEFENSE (DND)'),(7,8,668,'Language Common'),(7,8,1843,'Disarm'),(7,8,2382,'Generic'),(7,8,2479,'Honorless Target'),(7,8,3050,'Detect'),(7,8,3365,'Opening'),(7,8,5009,'Wands'),(7,8,5019,'Shoot'),(7,8,6233,'Closing'),(7,8,6246,'Closing'),(7,8,6247,'Opening'),(7,8,6477,'Opening'),(7,8,6478,'Opening'),(7,8,6603,'Attack'),(7,8,7266,'Duel'),(7,8,7267,'Grovel'),(7,8,7340,'Language Gnomish'),(7,8,7355,'Stuck'),(7,8,8386,'Attacking'),(7,8,9078,'Cloth'),(7,8,9125,'Generic'),(7,8,20589,'Escape Artist'),(7,8,20591,'Expansive Mind'),(7,8,20592,'Arcane Resistance'),(7,8,20593,'Engineering Specialization'),(7,8,21651,'Opening'),(7,8,21652,'Closing'),(7,8,22027,'Remove Insignia'),(7,8,22810,'Opening - No Text'),(7,8,45927,'Summon Friend'),(7,8,61437,'Opening'),(7,9,81,'Dodge'),(7,9,203,'Unarmed'),(7,9,204,'Defense'),(7,9,522,'SPELLDEFENSE (DND)'),(7,9,668,'Language Common'),(7,9,686,'Shadow Bolt'),(7,9,687,'Demon Skin'),(7,9,1180,'Daggers'),(7,9,1843,'Disarm'),(7,9,2382,'Generic'),(7,9,2479,'Honorless Target'),(7,9,3050,'Detect'),(7,9,3365,'Opening'),(7,9,5009,'Wands'),(7,9,5019,'Shoot'),(7,9,6233,'Closing'),(7,9,6246,'Closing'),(7,9,6247,'Opening'),(7,9,6477,'Opening'),(7,9,6478,'Opening'),(7,9,6603,'Attack'),(7,9,7266,'Duel'),(7,9,7267,'Grovel'),(7,9,7340,'Language Gnomish'),(7,9,7355,'Stuck'),(7,9,8386,'Attacking'),(7,9,9078,'Cloth'),(7,9,9125,'Generic'),(7,9,20589,'Escape Artist'),(7,9,20591,'Expansive Mind'),(7,9,20592,'Arcane Resistance'),(7,9,20593,'Engineering Specialization'),(7,9,21651,'Opening'),(7,9,21652,'Closing'),(7,9,22027,'Remove Insignia'),(7,9,22810,'Opening - No Text'),(7,9,45927,'Summon Friend'),(7,9,61437,'Opening'),(8,1,78,'Heroic Strike'),(8,1,81,'Dodge'),(8,1,107,'Block'),(8,1,196,'One-Handed Axes'),(8,1,203,'Unarmed'),(8,1,204,'Defense'),(8,1,522,'SPELLDEFENSE (DND)'),(8,1,669,'Language Orcish'),(8,1,1180,'Daggers'),(8,1,1843,'Disarm'),(8,1,2382,'Generic'),(8,1,2457,'Battle Stance'),(8,1,2479,'Honorless Target'),(8,1,2567,'Thrown'),(8,1,2764,'Throw'),(8,1,3050,'Detect'),(8,1,3365,'Opening'),(8,1,5301,'Defensive State (DND)'),(8,1,6233,'Closing'),(8,1,6246,'Closing'),(8,1,6247,'Opening'),(8,1,6477,'Opening'),(8,1,6478,'Opening'),(8,1,6603,'Attack'),(8,1,7266,'Duel'),(8,1,7267,'Grovel'),(8,1,7341,'Language Troll'),(8,1,7355,'Stuck'),(8,1,8386,'Attacking'),(8,1,8737,'Mail'),(8,1,9077,'Leather'),(8,1,9078,'Cloth'),(8,1,9116,'Shield'),(8,1,9125,'Generic'),(8,1,20555,'Regeneration'),(8,1,20557,'Beast Slaying'),(8,1,20558,'Throwing Specialization'),(8,1,21651,'Opening'),(8,1,21652,'Closing'),(8,1,22027,'Remove Insignia'),(8,1,22810,'Opening - No Text'),(8,1,26290,'Bow Specialization'),(8,1,26297,'Berserking'),(8,1,32215,'Victorious State'),(8,1,45927,'Summon Friend'),(8,1,58943,'Da Voodoo Shuffle'),(8,1,61437,'Opening'),(8,3,75,'Auto Shot'),(8,3,81,'Dodge'),(8,3,196,'One-Handed Axes'),(8,3,203,'Unarmed'),(8,3,204,'Defense'),(8,3,264,'Bows'),(8,3,522,'SPELLDEFENSE (DND)'),(8,3,669,'Language Orcish'),(8,3,1843,'Disarm'),(8,3,2382,'Generic'),(8,3,2479,'Honorless Target'),(8,3,2973,'Raptor Strike'),(8,3,3050,'Detect'),(8,3,3365,'Opening'),(8,3,6233,'Closing'),(8,3,6246,'Closing'),(8,3,6247,'Opening'),(8,3,6477,'Opening'),(8,3,6478,'Opening'),(8,3,6603,'Attack'),(8,3,7266,'Duel'),(8,3,7267,'Grovel'),(8,3,7341,'Language Troll'),(8,3,7355,'Stuck'),(8,3,8386,'Attacking'),(8,3,9077,'Leather'),(8,3,9078,'Cloth'),(8,3,9125,'Generic'),(8,3,13358,'Defensive State (DND)'),(8,3,26297,'Berserking'),(8,3,20555,'Regeneration'),(8,3,20557,'Beast Slaying'),(8,3,20558,'Throwing Specialization'),(8,3,21651,'Opening'),(8,3,21652,'Closing'),(8,3,22027,'Remove Insignia'),(8,3,22810,'Opening - No Text'),(8,3,24949,'Defensive State 2 (DND)'),(8,3,26290,'Bow Specialization'),(8,3,34082,'Advantaged State (DND)'),(8,3,45927,'Summon Friend'),(8,3,58943,'Da Voodoo Shuffle'),(8,3,61437,'Opening'),(8,4,81,'Dodge'),(8,4,203,'Unarmed'),(8,4,204,'Defense'),(8,4,522,'SPELLDEFENSE (DND)'),(8,4,669,'Language Orcish'),(8,4,1180,'Daggers'),(8,4,1752,'Sinister Strike'),(8,4,1843,'Disarm'),(8,4,2098,'Eviscerate'),(8,4,2382,'Generic'),(8,4,2479,'Honorless Target'),(8,4,2567,'Thrown'),(8,4,2764,'Throw'),(8,4,3050,'Detect'),(8,4,3365,'Opening'),(8,4,6233,'Closing'),(8,4,6246,'Closing'),(8,4,6247,'Opening'),(8,4,6477,'Opening'),(8,4,6478,'Opening'),(8,4,6603,'Attack'),(8,4,7266,'Duel'),(8,4,7267,'Grovel'),(8,4,7341,'Language Troll'),(8,4,7355,'Stuck'),(8,4,8386,'Attacking'),(8,4,9077,'Leather'),(8,4,9078,'Cloth'),(8,4,9125,'Generic'),(8,4,16092,'Defensive State (DND)'),(8,4,20555,'Regeneration'),(8,4,20557,'Beast Slaying'),(8,4,20558,'Throwing Specialization'),(8,4,21184,'Rogue Passive (DND)'),(8,4,21651,'Opening'),(8,4,21652,'Closing'),(8,4,22027,'Remove Insignia'),(8,4,22810,'Opening - No Text'),(8,4,26290,'Bow Specialization'),(8,4,26297,'Berserking'),(8,4,45927,'Summon Friend'),(8,4,58943,'Da Voodoo Shuffle'),(8,4,61437,'Opening'),(8,5,81,'Dodge'),(8,5,198,'One-Handed Maces'),(8,5,203,'Unarmed'),(8,5,204,'Defense'),(8,5,522,'SPELLDEFENSE (DND)'),(8,5,585,'Smite'),(8,5,669,'Language Orcish'),(8,5,1843,'Disarm'),(8,5,2050,'Lesser Heal'),(8,5,2382,'Generic'),(8,5,2479,'Honorless Target'),(8,5,3050,'Detect'),(8,5,3365,'Opening'),(8,5,5009,'Wands'),(8,5,5019,'Shoot'),(8,5,6233,'Closing'),(8,5,6246,'Closing'),(8,5,6247,'Opening'),(8,5,6477,'Opening'),(8,5,6478,'Opening'),(8,5,6603,'Attack'),(8,5,7266,'Duel'),(8,5,7267,'Grovel'),(8,5,7341,'Language Troll'),(8,5,7355,'Stuck'),(8,5,8386,'Attacking'),(8,5,9078,'Cloth'),(8,5,9125,'Generic'),(8,5,26297,'Berserking'),(8,5,20555,'Regeneration'),(8,5,20557,'Beast Slaying'),(8,5,20558,'Throwing Specialization'),(8,5,21651,'Opening'),(8,5,21652,'Closing'),(8,5,22027,'Remove Insignia'),(8,5,22810,'Opening - No Text'),(8,5,26290,'Bow Specialization'),(8,5,45927,'Summon Friend'),(8,5,58943,'Da Voodoo Shuffle'),(8,5,61437,'Opening'),(8,6,81,'Dodge'),(8,6,196,'One-Handed Axes'),(8,6,197,'Two-Handed Axes'),(8,6,200,'Polearms'),(8,6,201,'One-Handed Swords'),(8,6,202,'Two-Handed Swords'),(8,6,203,'Unarmed'),(8,6,204,'Defense'),(8,6,522,'SPELLDEFENSE (DND)'),(8,6,669,'Language Orcish'),(8,6,674,'Dual Wield'),(8,6,750,'Plate Mail'),(8,6,1843,'Disarm'),(8,6,2382,'Generic'),(8,6,2479,'Honorless Target'),(8,6,3050,'Detect'),(8,6,3127,'Parry'),(8,6,3275,'Linen Bandage'),(8,6,3276,'Heavy Linen Bandage'),(8,6,3277,'Wool Bandage'),(8,6,3278,'Heavy Wool Bandage'),(8,6,3365,'Opening'),(8,6,6233,'Closing'),(8,6,6246,'Closing'),(8,6,6247,'Opening'),(8,6,6477,'Opening'),(8,6,6478,'Opening'),(8,6,6603,'Attack'),(8,6,7266,'Duel'),(8,6,7267,'Grovel'),(8,6,7341,'Language Troll'),(8,6,7355,'Stuck'),(8,6,7928,'Silk Bandage'),(8,6,7929,'Heavy Silk Bandage'),(8,6,7934,'Anti-Venom'),(8,6,8386,'Attacking'),(8,6,8737,'Mail'),(8,6,9077,'Leather'),(8,6,9078,'Cloth'),(8,6,9125,'Generic'),(8,6,10840,'Mageweave Bandage'),(8,6,10841,'Heavy Mageweave Bandage'),(8,6,10846,'First Aid'),(8,6,18629,'Runecloth Bandage'),(8,6,18630,'Heavy Runecloth Bandage'),(8,6,20555,'Regeneration'),(8,6,20557,'Beast Slaying'),(8,6,20558,'Throwing Specialization'),(8,6,21651,'Opening'),(8,6,21652,'Closing'),(8,6,22027,'Remove Insignia'),(8,6,22810,'Opening - No Text'),(8,6,26290,'Bow Specialization'),(8,6,33391,'Journeyman Riding'),(8,6,45462,'Plague Strike'),(8,6,45477,'Icy Touch'),(8,6,45902,'Blood Strike'),(8,6,45903,'Offensive State (DND)'),(8,6,45927,'Summon Friend'),(8,6,47541,'Death Coil'),(8,6,48266,'Blood Presence'),(8,6,49410,'Forceful Deflection'),(8,6,49576,'Death Grip'),(8,6,26297,'Berserking'),(8,6,52665,'Sigil'),(8,6,58943,'Da Voodoo Shuffle'),(8,6,59879,'Blood Plague'),(8,6,59921,'Frost Fever'),(8,6,61437,'Opening'),(8,6,61455,'Runic Focus'),(8,7,81,'Dodge'),(8,7,107,'Block'),(8,7,198,'One-Handed Maces'),(8,7,203,'Unarmed'),(8,7,204,'Defense'),(8,7,227,'Staves'),(8,7,331,'Healing Wave'),(8,7,403,'Lightning Bolt'),(8,7,522,'SPELLDEFENSE (DND)'),(8,7,669,'Language Orcish'),(8,7,1843,'Disarm'),(8,7,2382,'Generic'),(8,7,2479,'Honorless Target'),(8,7,3050,'Detect'),(8,7,3365,'Opening'),(8,7,6233,'Closing'),(8,7,6246,'Closing'),(8,7,6247,'Opening'),(8,7,6477,'Opening'),(8,7,6478,'Opening'),(8,7,6603,'Attack'),(8,7,7266,'Duel'),(8,7,7267,'Grovel'),(8,7,7341,'Language Troll'),(8,7,7355,'Stuck'),(8,7,8386,'Attacking'),(8,7,9077,'Leather'),(8,7,9078,'Cloth'),(8,7,9116,'Shield'),(8,7,9125,'Generic'),(8,7,26297,'Berserking'),(8,7,20555,'Regeneration'),(8,7,20557,'Beast Slaying'),(8,7,20558,'Throwing Specialization'),(8,7,21651,'Opening'),(8,7,21652,'Closing'),(8,7,22027,'Remove Insignia'),(8,7,22810,'Opening - No Text'),(8,7,26290,'Bow Specialization'),(8,7,27763,'Totem'),(8,7,45927,'Summon Friend'),(8,7,58943,'Da Voodoo Shuffle'),(8,7,61437,'Opening'),(8,8,81,'Dodge'),(8,8,133,'Fireball'),(8,8,168,'Frost Armor'),(8,8,203,'Unarmed'),(8,8,204,'Defense'),(8,8,227,'Staves'),(8,8,522,'SPELLDEFENSE (DND)'),(8,8,669,'Language Orcish'),(8,8,1843,'Disarm'),(8,8,2382,'Generic'),(8,8,2479,'Honorless Target'),(8,8,3050,'Detect'),(8,8,3365,'Opening'),(8,8,5009,'Wands'),(8,8,5019,'Shoot'),(8,8,6233,'Closing'),(8,8,6246,'Closing'),(8,8,6247,'Opening'),(8,8,6477,'Opening'),(8,8,6478,'Opening'),(8,8,6603,'Attack'),(8,8,7266,'Duel'),(8,8,7267,'Grovel'),(8,8,7341,'Language Troll'),(8,8,7355,'Stuck'),(8,8,8386,'Attacking'),(8,8,9078,'Cloth'),(8,8,9125,'Generic'),(8,8,26297,'Berserking'),(8,8,20555,'Regeneration'),(8,8,20557,'Beast Slaying'),(8,8,20558,'Throwing Specialization'),(8,8,21651,'Opening'),(8,8,21652,'Closing'),(8,8,22027,'Remove Insignia'),(8,8,22810,'Opening - No Text'),(8,8,26290,'Bow Specialization'),(8,8,45927,'Summon Friend'),(8,8,58943,'Da Voodoo Shuffle'),(8,8,61437,'Opening'),(10,2,81,'Dodge'),(10,2,107,'Block'),(10,2,201,'One-Handed Swords'),(10,2,202,'Two-Handed Swords'),(10,2,203,'Unarmed'),(10,2,204,'Defense'),(10,2,522,'SPELLDEFENSE (DND)'),(10,2,635,'Holy Light'),(10,2,669,'Language Orcish'),(10,2,813,'Language Thalassian'),(10,2,822,'Magic Resistance'),(10,2,2382,'Generic'),(10,2,2479,'Honorless Target'),(10,2,3050,'Detect'),(10,2,3365,'Opening'),(10,2,6233,'Closing'),(10,2,6246,'Closing'),(10,2,6247,'Opening'),(10,2,6477,'Opening'),(10,2,6478,'Opening'),(10,2,6603,'Attack'),(10,2,7266,'Duel'),(10,2,7267,'Grovel'),(10,2,7355,'Stuck'),(10,2,8386,'Attacking'),(10,2,8737,'Mail'),(10,2,9077,'Leather'),(10,2,9078,'Cloth'),(10,2,9116,'Shield'),(10,2,9125,'Generic'),(10,2,21084,'Seal of Righteousness'),(10,2,21651,'Opening'),(10,2,21652,'Closing'),(10,2,22027,'Remove Insignia'),(10,2,22810,'Opening - No Text'),(10,2,27762,'Libram'),(10,2,28730,'Arcane Torrent'),(10,2,28877,'Arcane Affinity'),(10,3,75,'Auto Shot'),(10,3,81,'Dodge'),(10,3,203,'Unarmed'),(10,3,204,'Defense'),(10,3,264,'Bows'),(10,3,522,'SPELLDEFENSE (DND)'),(10,3,669,'Language Orcish'),(10,3,813,'Language Thalassian'),(10,3,822,'Magic Resistance'),(10,3,1180,'Daggers'),(10,3,2382,'Generic'),(10,3,2479,'Honorless Target'),(10,3,2973,'Raptor Strike'),(10,3,3050,'Detect'),(10,3,3365,'Opening'),(10,3,6233,'Closing'),(10,3,6246,'Closing'),(10,3,6247,'Opening'),(10,3,6477,'Opening'),(10,3,6478,'Opening'),(10,3,6603,'Attack'),(10,3,7266,'Duel'),(10,3,7267,'Grovel'),(10,3,7355,'Stuck'),(10,3,8386,'Attacking'),(10,3,9077,'Leather'),(10,3,9078,'Cloth'),(10,3,9125,'Generic'),(10,3,13358,'Defensive State (DND)'),(10,3,21651,'Opening'),(10,3,21652,'Closing'),(10,3,22027,'Remove Insignia'),(10,3,22810,'Opening - No Text'),(10,3,24949,'Defensive State 2 (DND)'),(10,3,28730,'Arcane Torrent'),(10,3,28877,'Arcane Affinity'),(10,3,34082,'Advantaged State (DND)'),(10,4,81,'Dodge'),(10,4,203,'Unarmed'),(10,4,204,'Defense'),(10,4,522,'SPELLDEFENSE (DND)'),(10,4,669,'Language Orcish'),(10,4,813,'Language Thalassian'),(10,4,822,'Magic Resistance'),(10,4,1180,'Daggers'),(10,4,1752,'Sinister Strike'),(10,4,2098,'Eviscerate'),(10,4,2382,'Generic'),(10,4,2479,'Honorless Target'),(10,4,2567,'Thrown'),(10,4,2764,'Throw'),(10,4,3050,'Detect'),(10,4,3365,'Opening'),(10,4,6233,'Closing'),(10,4,6246,'Closing'),(10,4,6247,'Opening'),(10,4,6477,'Opening'),(10,4,6478,'Opening'),(10,4,6603,'Attack'),(10,4,7266,'Duel'),(10,4,7267,'Grovel'),(10,4,7355,'Stuck'),(10,4,8386,'Attacking'),(10,4,9077,'Leather'),(10,4,9078,'Cloth'),(10,4,9125,'Generic'),(10,4,16092,'Defensive State (DND)'),(10,4,21184,'Rogue Passive (DND)'),(10,4,21651,'Opening'),(10,4,21652,'Closing'),(10,4,22027,'Remove Insignia'),(10,4,22810,'Opening - No Text'),(10,4,25046,'Arcane Torrent'),(10,4,28877,'Arcane Affinity'),(10,5,81,'Dodge'),(10,5,198,'One-Handed Maces'),(10,5,203,'Unarmed'),(10,5,204,'Defense'),(10,5,522,'SPELLDEFENSE (DND)'),(10,5,585,'Smite'),(10,5,669,'Language Orcish'),(10,5,813,'Language Thalassian'),(10,5,822,'Magic Resistance'),(10,5,2050,'Lesser Heal'),(10,5,2382,'Generic'),(10,5,2479,'Honorless Target'),(10,5,3050,'Detect'),(10,5,3365,'Opening'),(10,5,5009,'Wands'),(10,5,5019,'Shoot'),(10,5,6233,'Closing'),(10,5,6246,'Closing'),(10,5,6247,'Opening'),(10,5,6477,'Opening'),(10,5,6478,'Opening'),(10,5,6603,'Attack'),(10,5,7266,'Duel'),(10,5,7267,'Grovel'),(10,5,7355,'Stuck'),(10,5,8386,'Attacking'),(10,5,9078,'Cloth'),(10,5,9125,'Generic'),(10,5,21651,'Opening'),(10,5,21652,'Closing'),(10,5,22027,'Remove Insignia'),(10,5,22810,'Opening - No Text'),(10,5,28730,'Arcane Torrent'),(10,5,28877,'Arcane Affinity'),(10,6,81,'Dodge'),(10,6,196,'One-Handed Axes'),(10,6,197,'Two-Handed Axes'),(10,6,200,'Polearms'),(10,6,201,'One-Handed Swords'),(10,6,202,'Two-Handed Swords'),(10,6,203,'Unarmed'),(10,6,204,'Defense'),(10,6,522,'SPELLDEFENSE (DND)'),(10,6,669,'Language Orcish'),(10,6,674,'Dual Wield'),(10,6,750,'Plate Mail'),(10,6,813,'Language Thalassian'),(10,6,822,'Magic Resistance'),(10,6,1843,'Disarm'),(10,6,2382,'Generic'),(10,6,2479,'Honorless Target'),(10,6,3050,'Detect'),(10,6,3127,'Parry'),(10,6,3275,'Linen Bandage'),(10,6,3276,'Heavy Linen Bandage'),(10,6,3277,'Wool Bandage'),(10,6,3278,'Heavy Wool Bandage'),(10,6,3365,'Opening'),(10,6,6233,'Closing'),(10,6,6246,'Closing'),(10,6,6247,'Opening'),(10,6,6477,'Opening'),(10,6,6478,'Opening'),(10,6,6603,'Attack'),(10,6,7266,'Duel'),(10,6,7267,'Grovel'),(10,6,7355,'Stuck'),(10,6,7928,'Silk Bandage'),(10,6,7929,'Heavy Silk Bandage'),(10,6,7934,'Anti-Venom'),(10,6,8386,'Attacking'),(10,6,8737,'Mail'),(10,6,9077,'Leather'),(10,6,9078,'Cloth'),(10,6,9125,'Generic'),(10,6,10840,'Mageweave Bandage'),(10,6,10841,'Heavy Mageweave Bandage'),(10,6,10846,'First Aid'),(10,6,18629,'Runecloth Bandage'),(10,6,18630,'Heavy Runecloth Bandage'),(10,6,21651,'Opening'),(10,6,21652,'Closing'),(10,6,22027,'Remove Insignia'),(10,6,22810,'Opening - No Text'),(10,6,28877,'Arcane Affinity'),(10,6,33391,'Journeyman Riding'),(10,6,45462,'Plague Strike'),(10,6,45477,'Icy Touch'),(10,6,45902,'Blood Strike'),(10,6,45903,'Offensive State (DND)'),(10,6,45927,'Summon Friend'),(10,6,47541,'Death Coil'),(10,6,48266,'Blood Presence'),(10,6,49410,'Forceful Deflection'),(10,6,49576,'Death Grip'),(10,6,50613,'Arcane Torrent'),(10,6,52665,'Sigil'),(10,6,59879,'Blood Plague'),(10,6,59921,'Frost Fever'),(10,6,61437,'Opening'),(10,6,61455,'Runic Focus'),(10,8,81,'Dodge'),(10,8,133,'Fireball'),(10,8,168,'Frost Armor'),(10,8,203,'Unarmed'),(10,8,204,'Defense'),(10,8,227,'Staves'),(10,8,522,'SPELLDEFENSE (DND)'),(10,8,669,'Language Orcish'),(10,8,813,'Language Thalassian'),(10,8,822,'Magic Resistance'),(10,8,2382,'Generic'),(10,8,2479,'Honorless Target'),(10,8,3050,'Detect'),(10,8,3365,'Opening'),(10,8,5009,'Wands'),(10,8,5019,'Shoot'),(10,8,6233,'Closing'),(10,8,6246,'Closing'),(10,8,6247,'Opening'),(10,8,6477,'Opening'),(10,8,6478,'Opening'),(10,8,6603,'Attack'),(10,8,7266,'Duel'),(10,8,7267,'Grovel'),(10,8,7355,'Stuck'),(10,8,8386,'Attacking'),(10,8,9078,'Cloth'),(10,8,9125,'Generic'),(10,8,21651,'Opening'),(10,8,21652,'Closing'),(10,8,22027,'Remove Insignia'),(10,8,22810,'Opening - No Text'),(10,8,28730,'Arcane Torrent'),(10,8,28877,'Arcane Affinity'),(10,9,81,'Dodge'),(10,9,203,'Unarmed'),(10,9,204,'Defense'),(10,9,522,'SPELLDEFENSE (DND)'),(10,9,669,'Language Orcish'),(10,9,686,'Shadow Bolt'),(10,9,687,'Demon Skin'),(10,9,813,'Language Thalassian'),(10,9,822,'Magic Resistance'),(10,9,1180,'Daggers'),(10,9,2382,'Generic'),(10,9,2479,'Honorless Target'),(10,9,3050,'Detect'),(10,9,3365,'Opening'),(10,9,5009,'Wands'),(10,9,5019,'Shoot'),(10,9,6233,'Closing'),(10,9,6246,'Closing'),(10,9,6247,'Opening'),(10,9,6477,'Opening'),(10,9,6478,'Opening'),(10,9,6603,'Attack'),(10,9,7266,'Duel'),(10,9,7267,'Grovel'),(10,9,7355,'Stuck'),(10,9,8386,'Attacking'),(10,9,9078,'Cloth'),(10,9,9125,'Generic'),(10,9,21651,'Opening'),(10,9,21652,'Closing'),(10,9,22027,'Remove Insignia'),(10,9,22810,'Opening - No Text'),(10,9,28730,'Arcane Torrent'),(10,9,28877,'Arcane Affinity'),(11,1,78,'Heroic Strike'),(11,1,81,'Dodge'),(11,1,107,'Block'),(11,1,198,'One-Handed Maces'),(11,1,201,'One-Handed Swords'),(11,1,202,'Two-Handed Swords'),(11,1,203,'Unarmed'),(11,1,204,'Defense'),(11,1,522,'SPELLDEFENSE (DND)'),(11,1,668,'Language Common'),(11,1,1843,'Disarm'),(11,1,2382,'Generic'),(11,1,2457,'Battle Stance'),(11,1,2479,'Honorless Target'),(11,1,3050,'Detect'),(11,1,3365,'Opening'),(11,1,5301,'Defensive State (DND)'),(11,1,6233,'Closing'),(11,1,6246,'Closing'),(11,1,6247,'Opening'),(11,1,6477,'Opening'),(11,1,6478,'Opening'),(11,1,6562,'Heroic Presence'),(11,1,6603,'Attack'),(11,1,7266,'Duel'),(11,1,7267,'Grovel'),(11,1,7355,'Stuck'),(11,1,8386,'Attacking'),(11,1,8737,'Mail'),(11,1,9077,'Leather'),(11,1,9078,'Cloth'),(11,1,9116,'Shield'),(11,1,9125,'Generic'),(11,1,21651,'Opening'),(11,1,21652,'Closing'),(11,1,22027,'Remove Insignia'),(11,1,22810,'Opening - No Text'),(11,1,28875,'Gemcutting'),(11,1,28880,'Gift of the Naaru'),(11,1,29932,'Language Draenei'),(11,1,32215,'Victorious State'),(11,1,45927,'Summon Friend'),(11,1,59221,'Shadow Resistance'),(11,1,61437,'Opening'),(11,2,81,'Dodge'),(11,2,107,'Block'),(11,2,198,'One-Handed Maces'),(11,2,199,'Two-Handed Maces'),(11,2,203,'Unarmed'),(11,2,204,'Defense'),(11,2,522,'SPELLDEFENSE (DND)'),(11,2,635,'Holy Light'),(11,2,668,'Language Common'),(11,2,1843,'Disarm'),(11,2,2382,'Generic'),(11,2,2479,'Honorless Target'),(11,2,3050,'Detect'),(11,2,3365,'Opening'),(11,2,6233,'Closing'),(11,2,6246,'Closing'),(11,2,6247,'Opening'),(11,2,6477,'Opening'),(11,2,6478,'Opening'),(11,2,6562,'Heroic Presence'),(11,2,6603,'Attack'),(11,2,7266,'Duel'),(11,2,7267,'Grovel'),(11,2,7355,'Stuck'),(11,2,8386,'Attacking'),(11,2,8737,'Mail'),(11,2,9077,'Leather'),(11,2,9078,'Cloth'),(11,2,9116,'Shield'),(11,2,9125,'Generic'),(11,2,21084,'Seal of Righteousness'),(11,2,21651,'Opening'),(11,2,21652,'Closing'),(11,2,22027,'Remove Insignia'),(11,2,22810,'Opening - No Text'),(11,2,27762,'Libram'),(11,2,28875,'Gemcutting'),(11,2,29932,'Language Draenei'),(11,2,45927,'Summon Friend'),(11,2,59221,'Shadow Resistance'),(11,2,59542,'Gift of the Naaru'),(11,2,61437,'Opening'),(11,3,75,'Auto Shot'),(11,3,81,'Dodge'),(11,3,201,'One-Handed Swords'),(11,3,203,'Unarmed'),(11,3,204,'Defense'),(11,3,522,'SPELLDEFENSE (DND)'),(11,3,668,'Language Common'),(11,3,1843,'Disarm'),(11,3,2382,'Generic'),(11,3,2479,'Honorless Target'),(11,3,2973,'Raptor Strike'),(11,3,3050,'Detect'),(11,3,3365,'Opening'),(11,3,5011,'Crossbows'),(11,3,6233,'Closing'),(11,3,6246,'Closing'),(11,3,6247,'Opening'),(11,3,6477,'Opening'),(11,3,6478,'Opening'),(11,3,6562,'Heroic Presence'),(11,3,6603,'Attack'),(11,3,7266,'Duel'),(11,3,7267,'Grovel'),(11,3,7355,'Stuck'),(11,3,8386,'Attacking'),(11,3,9077,'Leather'),(11,3,9078,'Cloth'),(11,3,9125,'Generic'),(11,3,13358,'Defensive State (DND)'),(11,3,21651,'Opening'),(11,3,21652,'Closing'),(11,3,22027,'Remove Insignia'),(11,3,22810,'Opening - No Text'),(11,3,24949,'Defensive State 2 (DND)'),(11,3,28875,'Gemcutting'),(11,3,29932,'Language Draenei'),(11,3,34082,'Advantaged State (DND)'),(11,3,45927,'Summon Friend'),(11,3,59221,'Shadow Resistance'),(11,3,59543,'Gift of the Naaru'),(11,3,61437,'Opening'),(11,5,81,'Dodge'),(11,5,198,'One-Handed Maces'),(11,5,203,'Unarmed'),(11,5,204,'Defense'),(11,5,522,'SPELLDEFENSE (DND)'),(11,5,585,'Smite'),(11,5,668,'Language Common'),(11,5,1843,'Disarm'),(11,5,2050,'Lesser Heal'),(11,5,2382,'Generic'),(11,5,2479,'Honorless Target'),(11,5,3050,'Detect'),(11,5,3365,'Opening'),(11,5,5009,'Wands'),(11,5,5019,'Shoot'),(11,5,6233,'Closing'),(11,5,6246,'Closing'),(11,5,6247,'Opening'),(11,5,6477,'Opening'),(11,5,6478,'Opening'),(11,5,6603,'Attack'),(11,5,7266,'Duel'),(11,5,7267,'Grovel'),(11,5,7355,'Stuck'),(11,5,8386,'Attacking'),(11,5,9078,'Cloth'),(11,5,9125,'Generic'),(11,5,21651,'Opening'),(11,5,21652,'Closing'),(11,5,22027,'Remove Insignia'),(11,5,22810,'Opening - No Text'),(11,5,28875,'Gemcutting'),(11,5,28878,'Inspiring Presence'),(11,5,29932,'Language Draenei'),(11,5,45927,'Summon Friend'),(11,5,59221,'Shadow Resistance'),(11,5,59544,'Gift of the Naaru'),(11,5,61437,'Opening'),(11,6,81,'Dodge'),(11,6,196,'One-Handed Axes'),(11,6,197,'Two-Handed Axes'),(11,6,200,'Polearms'),(11,6,201,'One-Handed Swords'),(11,6,202,'Two-Handed Swords'),(11,6,203,'Unarmed'),(11,6,204,'Defense'),(11,6,522,'SPELLDEFENSE (DND)'),(11,6,668,'Language Common'),(11,6,674,'Dual Wield'),(11,6,750,'Plate Mail'),(11,6,1843,'Disarm'),(11,6,2382,'Generic'),(11,6,2479,'Honorless Target'),(11,6,3050,'Detect'),(11,6,3127,'Parry'),(11,6,3275,'Linen Bandage'),(11,6,3276,'Heavy Linen Bandage'),(11,6,3277,'Wool Bandage'),(11,6,3278,'Heavy Wool Bandage'),(11,6,3365,'Opening'),(11,6,6233,'Closing'),(11,6,6246,'Closing'),(11,6,6247,'Opening'),(11,6,6477,'Opening'),(11,6,6478,'Opening'),(11,6,6562,'Heroic Presence'),(11,6,6603,'Attack'),(11,6,7266,'Duel'),(11,6,7267,'Grovel'),(11,6,7355,'Stuck'),(11,6,7928,'Silk Bandage'),(11,6,7929,'Heavy Silk Bandage'),(11,6,7934,'Anti-Venom'),(11,6,8386,'Attacking'),(11,6,8737,'Mail'),(11,6,9077,'Leather'),(11,6,9078,'Cloth'),(11,6,9125,'Generic'),(11,6,10840,'Mageweave Bandage'),(11,6,10841,'Heavy Mageweave Bandage'),(11,6,10846,'First Aid'),(11,6,18629,'Runecloth Bandage'),(11,6,18630,'Heavy Runecloth Bandage'),(11,6,21651,'Opening'),(11,6,21652,'Closing'),(11,6,22027,'Remove Insignia'),(11,6,22810,'Opening - No Text'),(11,6,28875,'Gemcutting'),(11,6,29932,'Language Draenei'),(11,6,33391,'Journeyman Riding'),(11,6,45462,'Plague Strike'),(11,6,45477,'Icy Touch'),(11,6,45902,'Blood Strike'),(11,6,45903,'Offensive State (DND)'),(11,6,45927,'Summon Friend'),(11,6,47541,'Death Coil'),(11,6,48266,'Blood Presence'),(11,6,49410,'Forceful Deflection'),(11,6,49576,'Death Grip'),(11,6,52665,'Sigil'),(11,6,59221,'Shadow Resistance'),(11,6,59539,'Shadow Resistance'),(11,6,59545,'Gift of the Naaru'),(11,6,59879,'Blood Plague'),(11,6,59921,'Frost Fever'),(11,6,61437,'Opening'),(11,6,61455,'Runic Focus'),(11,7,81,'Dodge'),(11,7,107,'Block'),(11,7,198,'One-Handed Maces'),(11,7,203,'Unarmed'),(11,7,204,'Defense'),(11,7,227,'Staves'),(11,7,331,'Healing Wave'),(11,7,403,'Lightning Bolt'),(11,7,522,'SPELLDEFENSE (DND)'),(11,7,668,'Language Common'),(11,7,1843,'Disarm'),(11,7,2382,'Generic'),(11,7,2479,'Honorless Target'),(11,7,3050,'Detect'),(11,7,3365,'Opening'),(11,7,6233,'Closing'),(11,7,6246,'Closing'),(11,7,6247,'Opening'),(11,7,6477,'Opening'),(11,7,6478,'Opening'),(11,7,6603,'Attack'),(11,7,7266,'Duel'),(11,7,7267,'Grovel'),(11,7,7355,'Stuck'),(11,7,8386,'Attacking'),(11,7,9077,'Leather'),(11,7,9078,'Cloth'),(11,7,9116,'Shield'),(11,7,9125,'Generic'),(11,7,21651,'Opening'),(11,7,21652,'Closing'),(11,7,22027,'Remove Insignia'),(11,7,22810,'Opening - No Text'),(11,7,27763,'Totem'),(11,7,28875,'Gemcutting'),(11,7,28878,'Inspiring Presence'),(11,7,29932,'Language Draenei'),(11,7,45927,'Summon Friend'),(11,7,59221,'Shadow Resistance'),(11,7,59547,'Gift of the Naaru'),(11,7,61437,'Opening'),(11,8,81,'Dodge'),(11,8,133,'Fireball'),(11,8,168,'Frost Armor'),(11,8,203,'Unarmed'),(11,8,204,'Defense'),(11,8,227,'Staves'),(11,8,522,'SPELLDEFENSE (DND)'),(11,8,668,'Language Common'),(11,8,1843,'Disarm'),(11,8,2382,'Generic'),(11,8,2479,'Honorless Target'),(11,8,3050,'Detect'),(11,8,3365,'Opening'),(11,8,5009,'Wands'),(11,8,5019,'Shoot'),(11,8,6233,'Closing'),(11,8,6246,'Closing'),(11,8,6247,'Opening'),(11,8,6477,'Opening'),(11,8,6478,'Opening'),(11,8,6603,'Attack'),(11,8,7266,'Duel'),(11,8,7267,'Grovel'),(11,8,7355,'Stuck'),(11,8,8386,'Attacking'),(11,8,9078,'Cloth'),(11,8,9125,'Generic'),(11,8,21651,'Opening'),(11,8,21652,'Closing'),(11,8,22027,'Remove Insignia'),(11,8,22810,'Opening - No Text'),(11,8,28875,'Gemcutting'),(11,8,28878,'Inspiring Presence'),(11,8,29932,'Language Draenei'),(11,8,45927,'Summon Friend'),(11,8,59221,'Shadow Resistance'),(11,8,59548,'Gift of the Naaru'),(11,8,61437,'Opening'),(7,9,58284,'Chaos Bolt Passive'),(10,9,58284,'Chaos Bolt Passive'),(11,2,60091,'Judgement Anti-Parry/Dodge Passive'),(10,2,60091,'Judgement Anti-Parry/Dodge Passive'),(3,2,60091,'Judgement Anti-Parry/Dodge Passive'),(1,2,60091,'Judgement Anti-Parry/Dodge Passive'),(0,6,56816,'Rune Strike');
diff --git a/sql/world.sql b/sql/world.sql
index d8a20c724b0..8b24229629e 100644
--- a/sql/world.sql
+++ b/sql/world.sql
@@ -491,9 +491,11 @@ SET @saved_cs_client = @@character_set_client;
SET character_set_client = utf8;
CREATE TABLE `creature_template` (
`entry` mediumint(8) unsigned NOT NULL default '0',
- `heroic_entry` mediumint(8) unsigned NOT NULL default '0',
- `unk1` int(11) unsigned NOT NULL default '0',
- `unk2` int(11) unsigned NOT NULL default '0',
+ `difficulty_entry_1` mediumint(8) unsigned NOT NULL default '0',
+ `difficulty_entry_2` mediumint(8) unsigned NOT NULL default '0',
+ `difficulty_entry_3` mediumint(8) unsigned NOT NULL default '0',
+ `KillCredit1` int(11) unsigned NOT NULL default '0',
+ `KillCredit2` int(11) unsigned NOT NULL default '0',
`modelid1` mediumint(8) unsigned NOT NULL default '0',
`modelid2` mediumint(8) unsigned NOT NULL default '0',
`modelid3` mediumint(8) unsigned NOT NULL default '0',
@@ -1178,10 +1180,8 @@ SET character_set_client = utf8;
CREATE TABLE `instance_template` (
`map` smallint(5) unsigned NOT NULL,
`parent` int(10) unsigned NOT NULL,
- `maxPlayers` tinyint(3) unsigned NOT NULL default '0',
- `maxPlayersHeroic` tinyint(3) unsigned NOT NULL default '0',
- `reset_delay` int(10) unsigned NOT NULL default '0',
- `access_id` bigint(20) unsigned NOT NULL default '0',
+ `levelMin` tinyint(3) unsigned NOT NULL default '0',
+ `levelMax` tinyint(3) unsigned NOT NULL default '0',
`startLocX` float default NULL,
`startLocY` float default NULL,
`startLocZ` float default NULL,
@@ -1258,13 +1258,14 @@ CREATE TABLE `item_template` (
`displayid` mediumint(8) unsigned NOT NULL default '0',
`Quality` tinyint(3) unsigned NOT NULL default '0',
`Flags` int(10) unsigned NOT NULL default '0',
+ `Faction` int(11) UNSIGNED NOT NULL default '0',
`BuyCount` tinyint(3) unsigned NOT NULL default '1',
`BuyPrice` int(10) unsigned NOT NULL default '0',
`SellPrice` int(10) unsigned NOT NULL default '0',
`InventoryType` tinyint(3) unsigned NOT NULL default '0',
`AllowableClass` int signed NOT NULL default '-1',
`AllowableRace` int signed NOT NULL default '-1',
- `ItemLevel` tinyint(3) unsigned NOT NULL default '0',
+ `ItemLevel` smallint(5) unsigned NOT NULL default '0',
`RequiredLevel` tinyint(3) unsigned NOT NULL default '0',
`RequiredSkill` smallint(5) unsigned NOT NULL default '0',
`RequiredSkillRank` smallint(5) unsigned NOT NULL default '0',
@@ -2485,10 +2486,14 @@ CREATE TABLE `quest_template` (
`ReqItemId2` mediumint(8) unsigned NOT NULL default '0',
`ReqItemId3` mediumint(8) unsigned NOT NULL default '0',
`ReqItemId4` mediumint(8) unsigned NOT NULL default '0',
+ `ReqItemId5` mediumint(8) unsigned NOT NULL default '0',
+ `ReqItemId6` mediumint(8) unsigned NOT NULL default '0',
`ReqItemCount1` smallint(5) unsigned NOT NULL default '0',
`ReqItemCount2` smallint(5) unsigned NOT NULL default '0',
`ReqItemCount3` smallint(5) unsigned NOT NULL default '0',
`ReqItemCount4` smallint(5) unsigned NOT NULL default '0',
+ `ReqItemCount5` smallint(5) unsigned NOT NULL default '0',
+ `ReqItemCount6` smallint(5) unsigned NOT NULL default '0',
`ReqSourceId1` mediumint(8) unsigned NOT NULL default '0',
`ReqSourceId2` mediumint(8) unsigned NOT NULL default '0',
`ReqSourceId3` mediumint(8) unsigned NOT NULL default '0',
@@ -2750,7 +2755,7 @@ SET character_set_client = @saved_cs_client;
DROP TABLE IF EXISTS `spell_bonus_data`;
CREATE TABLE `spell_bonus_data` (
- `entry` smallint(5) unsigned NOT NULL,
+ `entry` mediumint(8) unsigned NOT NULL,
`direct_bonus` float NOT NULL default '0',
`dot_bonus` float NOT NULL default '0',
`ap_bonus` float NOT NULL default '0',
@@ -2982,7 +2987,7 @@ DROP TABLE IF EXISTS `spell_proc_event`;
SET @saved_cs_client = @@character_set_client;
SET character_set_client = utf8;
CREATE TABLE `spell_proc_event` (
- `entry` smallint(5) unsigned NOT NULL default '0',
+ `entry` mediumint(8) unsigned NOT NULL default '0',
`SchoolMask` tinyint(4) NOT NULL default '0',
`SpellFamilyName` smallint(5) unsigned NOT NULL default '0',
`SpellFamilyMask0` int(10) unsigned NOT NULL default '0',
diff --git a/src/bindings/scripts/scripts/eastern_kingdoms/stormwind_city.cpp b/src/bindings/scripts/scripts/eastern_kingdoms/stormwind_city.cpp
index 6ea696e7ae3..7ee1ad34a6a 100644
--- a/src/bindings/scripts/scripts/eastern_kingdoms/stormwind_city.cpp
+++ b/src/bindings/scripts/scripts/eastern_kingdoms/stormwind_city.cpp
@@ -454,7 +454,7 @@ struct TRINITY_DLL_DECL npc_marzon_silent_bladeAI : public ScriptedAI
{
CAST_AI(npc_lord_gregor_lescovarAI, CAST_CRE(pSummoner)->AI())->uiTimer = 2000;
CAST_AI(npc_lord_gregor_lescovarAI, CAST_CRE(pSummoner)->AI())->uiPhase = 5;
- m_creature->ChangeOrient(0.0f, pSummoner);
+ //m_creature->ChangeOrient(0.0f, pSummoner);
}
}
}
@@ -514,8 +514,6 @@ struct TRINITY_DLL_DECL npc_tyrion_spybotAI : public npc_escortAI
switch(uiPointId)
{
case 1:
- if (pTyrion = m_creature->FindNearestCreature(NPC_TYRION, 10.0f, true))
- m_creature->ChangeOrient(0.0f, pTyrion);
SetEscortPaused(true);
uiTimer = 2000;
uiPhase = 1;
@@ -528,8 +526,6 @@ struct TRINITY_DLL_DECL npc_tyrion_spybotAI : public npc_escortAI
break;
case 17:
SetEscortPaused(true);
- if (pLescovar = m_creature->FindNearestCreature(NPC_LORD_GREGOR_LESCOVAR, 20.0f, true))
- pLescovar->ChangeOrient(0.0f, m_creature);
DoScriptText(SAY_SPYBOT_3, m_creature);
uiTimer = 3000;
uiPhase = 8;
diff --git a/src/game/AchievementMgr.cpp b/src/game/AchievementMgr.cpp
index d03bb5f4211..afd51d1f55e 100644
--- a/src/game/AchievementMgr.cpp
+++ b/src/game/AchievementMgr.cpp
@@ -196,10 +196,10 @@ bool AchievementCriteriaData::IsValid(AchievementCriteriaEntry const* criteria)
}
return true;
case ACHIEVEMENT_CRITERIA_DATA_TYPE_MAP_DIFFICULTY:
- if (difficalty.difficalty >= TOTAL_DIFFICULTIES)
+ if (difficulty.difficulty >= MAX_DIFFICULTY)
{
sLog.outErrorDb( "Table `achievement_criteria_data` (Entry: %u Type: %u) for data type ACHIEVEMENT_CRITERIA_DATA_TYPE_MAP_DIFFICULTY (%u) have wrong difficulty in value1 (%u), ignore.",
- criteria->ID, criteria->requiredType,dataType,difficalty.difficalty);
+ criteria->ID, criteria->requiredType,dataType,difficulty.difficulty);
return false;
}
return true;
@@ -294,7 +294,7 @@ bool AchievementCriteriaData::Meets(Player const* source, Unit const* target, ui
case ACHIEVEMENT_CRITERIA_DATA_TYPE_DISABLED:
return false; // always fail
case ACHIEVEMENT_CRITERIA_DATA_TYPE_MAP_DIFFICULTY:
- return source->GetMap()->GetSpawnMode()==difficalty.difficalty;
+ return source->GetMap()->GetSpawnMode()==difficulty.difficulty;
case ACHIEVEMENT_CRITERIA_DATA_TYPE_MAP_PLAYER_COUNT:
return source->GetMap()->GetPlayersCountExceptGMs() <= map_players.maxcount;
case ACHIEVEMENT_CRITERIA_DATA_TYPE_T_TEAM:
@@ -592,7 +592,8 @@ void AchievementMgr::SendAchievementEarned(AchievementEntry const* achievement)
data << uint32(0); // 1=link supplied string as player name, 0=display plain string
sWorld.SendGlobalMessage(&data);
}
- else
+ // if player is in world he can tell his friends about new achievement
+ else if (GetPlayer()->IsInWorld())
{
CellPair p = MaNGOS::ComputeCellPair(GetPlayer()->GetPositionX(), GetPlayer()->GetPositionY());
@@ -902,7 +903,7 @@ void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, ui
if(!achievIdForDangeon[j][2])
break; // for
}
- else if(GetPlayer()->GetDifficulty()==DIFFICULTY_NORMAL)
+ else if(GetPlayer()->GetDungeonDifficulty()==DUNGEON_DIFFICULTY_NORMAL)
{
// dungeon in normal mode accepted
if(!achievIdForDangeon[j][1])
diff --git a/src/game/AchievementMgr.h b/src/game/AchievementMgr.h
index d031672f2a5..ceaa4bde65b 100644
--- a/src/game/AchievementMgr.h
+++ b/src/game/AchievementMgr.h
@@ -125,8 +125,8 @@ struct AchievementCriteriaData
// ACHIEVEMENT_CRITERIA_DATA_TYPE_MAP_DIFFICULTY = 12
struct
{
- uint32 difficalty;
- } difficalty;
+ uint32 difficulty;
+ } difficulty;
// ACHIEVEMENT_CRITERIA_DATA_TYPE_MAP_PLAYER_COUNT = 13
struct
{
diff --git a/src/game/ArenaTeam.cpp b/src/game/ArenaTeam.cpp
index feeae849bae..1d9669007fc 100644
--- a/src/game/ArenaTeam.cpp
+++ b/src/game/ArenaTeam.cpp
@@ -24,11 +24,12 @@
void ArenaTeamMember::ModifyPersonalRating(Player* plr, int32 mod, uint32 slot)
{
- int32 memberRating = int32(personal_rating) + mod;
- personal_rating = memberRating > 0 ? memberRating : 0;
- if(plr)
- plr->SetUInt32Value(PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + (slot*6) + 5, personal_rating);
- //sLog.outArena("Modify personal rating for player %s: personal rating %u, mod %d, rating %d", plr->GetName(), personal_rating, mod, rating);
+ if (int32(personal_rating) + mod < 0)
+ personal_rating = 0;
+ else
+ personal_rating += mod;
+ if(plr)
+ plr->SetUInt32Value(PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + (slot * ARENA_TEAM_END) + ARENA_TEAM_PERSONAL_RATING, personal_rating);
}
ArenaTeam::ArenaTeam()
@@ -109,7 +110,7 @@ bool ArenaTeam::AddMember(const uint64& PlayerGuid)
return false;
}
- plClass = (uint8)pl->getClass();
+ plClass = pl->getClass();
plName = pl->GetName();
}
else
@@ -146,7 +147,7 @@ bool ArenaTeam::AddMember(const uint64& PlayerGuid)
if (sWorld.getConfig(CONFIG_ARENA_SEASON_ID) >= 6)
{
if (m_stats.rating < 1000)
- newmember.personal_rating = m_stats.rating;
+ newmember.personal_rating = 0;
else
newmember.personal_rating = 1000;
}
@@ -160,13 +161,13 @@ bool ArenaTeam::AddMember(const uint64& PlayerGuid)
if(pl)
{
- pl->SetInArenaTeam(m_TeamId, GetSlot());
+ pl->SetInArenaTeam(m_TeamId, GetSlot(), GetType());
pl->SetArenaTeamIdInvited(0);
- pl->SetUInt32Value(PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + (GetSlot()*6) + 5, newmember.personal_rating );
+ pl->SetUInt32Value(PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + (GetSlot() * ARENA_TEAM_END) + ARENA_TEAM_PERSONAL_RATING, newmember.personal_rating );
// hide promote/remove buttons
if(m_CaptainGuid != PlayerGuid)
- pl->SetUInt32Value(PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + (GetSlot() * 6) + 1, 1);
+ pl->SetUInt32Value(PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + (GetSlot() * ARENA_TEAM_END) + ARENA_TEAM_MEMBER, 1);
sLog.outArena("Player: %s [GUID: %u] joined arena team type: %u [Id: %u].", pl->GetName(), pl->GetGUIDLow(), GetType(), GetId());
}
return true;
@@ -263,7 +264,7 @@ void ArenaTeam::SetCaptain(const uint64& guid)
// disable remove/promote buttons
Player *oldcaptain = objmgr.GetPlayer(GetCaptain());
if(oldcaptain)
- oldcaptain->SetUInt32Value(PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + 1 + (GetSlot() * 6), 1);
+ oldcaptain->SetUInt32Value(PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + (GetSlot() * ARENA_TEAM_END) + ARENA_TEAM_MEMBER, 1);
// set new captain
m_CaptainGuid = guid;
@@ -275,7 +276,7 @@ void ArenaTeam::SetCaptain(const uint64& guid)
Player *newcaptain = objmgr.GetPlayer(guid);
if(newcaptain)
{
- newcaptain->SetUInt32Value(PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + 1 + (GetSlot() * 6), 0);
+ newcaptain->SetUInt32Value(PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + (GetSlot() * ARENA_TEAM_END) + ARENA_TEAM_MEMBER, 0);
sLog.outArena("Player: %s [GUID: %u] promoted player: %s [GUID: %u] to leader of arena team [Id: %u] [Type: %u].", oldcaptain->GetName(), oldcaptain->GetGUIDLow(), newcaptain->GetName(), newcaptain->GetGUIDLow(), GetId(), GetType());
}
}
@@ -291,17 +292,12 @@ void ArenaTeam::DelMember(uint64 guid)
}
}
- Player *player = objmgr.GetPlayer(guid);
-
- if(player)
+ if(Player *player = objmgr.GetPlayer(guid))
{
- player->SetInArenaTeam(0, GetSlot());
player->GetSession()->SendArenaTeamCommandResult(ERR_ARENA_TEAM_QUIT_S, GetName(), "", 0);
// delete all info regarding this team
- for (uint8 i = 0; i < 6; ++i)
- {
- player->SetUInt32Value(PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + (GetSlot() * 6) + i, 0);
- }
+ for(uint32 i = 0; i < ARENA_TEAM_END; ++i)
+ player->SetUInt32Value(PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + (GetSlot() * ARENA_TEAM_END) + i, 0);
sLog.outArena("Player: %s [GUID: %u] left arena team type: %u [Id: %u].", player->GetName(), player->GetGUIDLow(), GetType(), GetId());
}
CharacterDatabase.PExecute("DELETE FROM arena_team_member WHERE arenateamid = '%u' AND guid = '%u'", GetId(), GUID_LOPART(guid));
@@ -513,8 +509,7 @@ uint32 ArenaTeam::GetPoints(uint32 MemberRating)
uint32 rating = MemberRating + 150 < m_stats.rating ? MemberRating : m_stats.rating;
if(rating<=1500)
- // points = (float)1500 * 0.22f + 14.0f;
- points = 344.0f; // 3.1 change - teams with rating below 1500 get arena points for 1500 rating
+ points = (float)rating * 0.22f + 14.0f;
else
points = 1511.26f / (1.0f + 1639.28f * exp(-0.00412f * (float)rating));
@@ -533,8 +528,8 @@ float ArenaTeam::GetChanceAgainst(uint32 own_rating, uint32 enemy_rating)
// ELO system
if (sWorld.getConfig(CONFIG_ARENA_SEASON_ID) >= 6)
- if (enemy_rating < 1300)
- enemy_rating = 1300;
+ if (enemy_rating < 1000)
+ enemy_rating = 1000;
return 1.0f/(1.0f+exp(log(10.0f)*(float)((float)enemy_rating - (float)own_rating)/400.0f));
}
@@ -560,10 +555,12 @@ void ArenaTeam::FinishGame(int32 mod)
int32 ArenaTeam::WonAgainst(uint32 againstRating)
{
// called when the team has won
- //'chance' calculation - to beat the opponent
+ // 'chance' calculation - to beat the opponent
float chance = GetChanceAgainst(m_stats.rating, againstRating);
- // calculate the rating modification (ELO system with k=32)
- int32 mod = (int32)floor(32.0f * (1.0f - chance));
+ float K = (m_stats.rating < 1000) ? 48.0f : 32.0f;
+ // calculate the rating modification (ELO system with k=32 or k=48 if rating<1000)
+ int32 mod = (int32)floor(K* (1.0f - chance));
+
// modify the team stats accordingly
FinishGame(mod);
m_stats.wins_week += 1;
@@ -578,8 +575,9 @@ int32 ArenaTeam::LostAgainst(uint32 againstRating)
// called when the team has lost
//'chance' calculation - to loose to the opponent
float chance = GetChanceAgainst(m_stats.rating, againstRating);
- // calculate the rating modification (ELO system with k=32)
- int32 mod = (int32)ceil(32.0f * (0.0f - chance));
+ float K = (m_stats.rating < 1000) ? 48.0f : 32.0f;
+ // calculate the rating modification (ELO system with k=32 or k=48 if rating<1000)
+ int32 mod = (int32)ceil(K * (0.0f - chance));
// modify the team stats accordingly
FinishGame(mod);
@@ -596,14 +594,16 @@ void ArenaTeam::MemberLost(Player * plr, uint32 againstRating)
{
// update personal rating
float chance = GetChanceAgainst(itr->personal_rating, againstRating);
- int32 mod = (int32)ceil(32.0f * (0.0f - chance));
+ float K = (itr->personal_rating < 1000) ? 48.0f : 32.0f;
+ // calculate the rating modification (ELO system with k=32 or k=48 if rating<1000)
+ int32 mod = (int32)ceil(K * (0.0f - chance));
itr->ModifyPersonalRating(plr, mod, GetSlot());
// update personal played stats
itr->games_week +=1;
itr->games_season +=1;
// update the unit fields
- plr->SetUInt32Value(PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + 6 * GetSlot() + 2, itr->games_week);
- plr->SetUInt32Value(PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + 6 * GetSlot() + 3, itr->games_season);
+ plr->SetUInt32Value(PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + (GetSlot() * ARENA_TEAM_END) + ARENA_TEAM_GAMES_WEEK, itr->games_week);
+ plr->SetUInt32Value(PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + (GetSlot() * ARENA_TEAM_END) + ARENA_TEAM_GAMES_SEASON, itr->games_season);
return;
}
}
@@ -618,7 +618,9 @@ void ArenaTeam::OfflineMemberLost(uint64 guid, uint32 againstRating)
{
// update personal rating
float chance = GetChanceAgainst(itr->personal_rating, againstRating);
- int32 mod = (int32)ceil(32.0f * (0.0f - chance));
+ float K = (itr->personal_rating < 1000) ? 48.0f : 32.0f;
+ // calculate the rating modification (ELO system with k=32 or k=48 if rating<1000)
+ int32 mod = (int32)ceil(K * (0.0f - chance));
if (int32(itr->personal_rating) + mod < 0)
itr->personal_rating = 0;
else
@@ -640,7 +642,9 @@ void ArenaTeam::MemberWon(Player * plr, uint32 againstRating)
{
// update personal rating
float chance = GetChanceAgainst(itr->personal_rating, againstRating);
- int32 mod = (int32)floor(32.0f * (1.0f - chance));
+ float K = (itr->personal_rating < 1000) ? 48.0f : 32.0f;
+ // calculate the rating modification (ELO system with k=32 or k=48 if rating<1000)
+ int32 mod = (int32)floor(K* (1.0f - chance));
itr->ModifyPersonalRating(plr, mod, GetSlot());
// update personal stats
itr->games_week +=1;
@@ -648,8 +652,8 @@ void ArenaTeam::MemberWon(Player * plr, uint32 againstRating)
itr->wins_season += 1;
itr->wins_week += 1;
// update unit fields
- plr->SetUInt32Value(PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + 6 * GetSlot() + 2, itr->games_week);
- plr->SetUInt32Value(PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + 6 * GetSlot() + 3, itr->games_season);
+ plr->SetUInt32Value(PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + (GetSlot() * ARENA_TEAM_END) + ARENA_TEAM_GAMES_WEEK, itr->games_week);
+ plr->SetUInt32Value(PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + (GetSlot() * ARENA_TEAM_END) + ARENA_TEAM_GAMES_SEASON, itr->games_season);
return;
}
}
@@ -720,26 +724,3 @@ bool ArenaTeam::IsFighting() const
}
return false;
}
-
-/*
-arenateam fields (id from 2.3.3 client):
-1414 - arena team id 2v2
-1415 - 0=captain, 1=member
-1416 - played this week
-1417 - played this season
-1418 - unk - rank?
-1419 - personal arena rating
-1420 - arena team id 3v3
-1421 - 0=captain, 1=member
-1422 - played this week
-1423 - played this season
-1424 - unk - rank?
-1425 - personal arena rating
-1426 - arena team id 5v5
-1427 - 0=captain, 1=member
-1428 - played this week
-1429 - played this season
-1430 - unk - rank?
-1431 - personal arena rating
-*/
-
diff --git a/src/game/ArenaTeamHandler.cpp b/src/game/ArenaTeamHandler.cpp
index c7ecf5b1d80..edcfeed0f99 100644
--- a/src/game/ArenaTeamHandler.cpp
+++ b/src/game/ArenaTeamHandler.cpp
@@ -57,12 +57,11 @@ void WorldSession::HandleArenaTeamQueryOpcode(WorldPacket & recv_data)
uint32 ArenaTeamId;
recv_data >> ArenaTeamId;
- ArenaTeam *arenateam = objmgr.GetArenaTeamById(ArenaTeamId);
- if(!arenateam) // arena team not found
- return;
-
- arenateam->Query(this);
- arenateam->Stats(this);
+ if(ArenaTeam *arenateam = objmgr.GetArenaTeamById(ArenaTeamId))
+ {
+ arenateam->Query(this);
+ arenateam->Stats(this);
+ }
}
void WorldSession::HandleArenaTeamRosterOpcode(WorldPacket & recv_data)
@@ -72,11 +71,8 @@ void WorldSession::HandleArenaTeamRosterOpcode(WorldPacket & recv_data)
uint32 ArenaTeamId; // arena team id
recv_data >> ArenaTeamId;
- ArenaTeam *arenateam = objmgr.GetArenaTeamById(ArenaTeamId);
- if(!arenateam)
- return;
-
- arenateam->Roster(this);
+ if(ArenaTeam *arenateam = objmgr.GetArenaTeamById(ArenaTeamId))
+ arenateam->Roster(this);
}
void WorldSession::HandleArenaTeamInviteOpcode(WorldPacket & recv_data)
@@ -206,12 +202,14 @@ void WorldSession::HandleArenaTeamLeaveOpcode(WorldPacket & recv_data)
ArenaTeam *at = objmgr.GetArenaTeamById(ArenaTeamId);
if(!at)
return;
+
if(_player->GetGUID() == at->GetCaptain() && at->GetMembersSize() > 1)
{
// check for correctness
SendArenaTeamCommandResult(ERR_ARENA_TEAM_QUIT_S, "", "", ERR_ARENA_TEAM_LEADER_LEAVE_S);
return;
}
+
// arena team has only one member (=captain)
if(_player->GetGUID() == at->GetCaptain())
{
@@ -238,18 +236,17 @@ void WorldSession::HandleArenaTeamDisbandOpcode(WorldPacket & recv_data)
uint32 ArenaTeamId; // arena team id
recv_data >> ArenaTeamId;
- ArenaTeam *at = objmgr.GetArenaTeamById(ArenaTeamId);
- if(!at)
- return;
-
- if(at->GetCaptain() != _player->GetGUID())
- return;
+ if(ArenaTeam *at = objmgr.GetArenaTeamById(ArenaTeamId))
+ {
+ if(at->GetCaptain() != _player->GetGUID())
+ return;
- if (at->IsFighting())
- return;
+ if(at->IsFighting())
+ return;
- at->Disband(this);
- delete at;
+ at->Disband(this);
+ delete at;
+ }
}
void WorldSession::HandleArenaTeamRemoveOpcode(WorldPacket & recv_data)
@@ -422,4 +419,3 @@ ERR_ARENA_TEAM_TOO_MANY_MEMBERS_S "%s is full"
ERR_ARENA_TEAM_LEVEL_TOO_LOW_I "You must be level %d to form an arena team"
*/
-
diff --git a/src/game/BattleGround.cpp b/src/game/BattleGround.cpp
index d6558e3bb4f..bdbcfc63bac 100644
--- a/src/game/BattleGround.cpp
+++ b/src/game/BattleGround.cpp
@@ -156,6 +156,7 @@ BattleGround::BattleGround()
m_MinPlayers = 0;
m_MapId = 0;
+ m_Map = NULL;
m_TeamStartLocX[BG_TEAM_ALLIANCE] = 0;
m_TeamStartLocX[BG_TEAM_HORDE] = 0;
@@ -224,9 +225,8 @@ BattleGround::~BattleGround()
sBattleGroundMgr.RemoveBattleGround(GetInstanceID(), GetTypeID());
// unload map
- if (Map * map = MapManager::Instance().FindMap(GetMapId(), GetInstanceID()))
- if (map->IsBattleGroundOrArena())
- ((BattleGroundMap*)map)->SetUnload();
+ if (m_Map)
+ m_Map->SetUnload();
// remove from bg free slot queue
this->RemoveFromBGFreeSlotQueue();
@@ -784,6 +784,7 @@ void BattleGround::EndBattleGround(uint32 winner)
else if(winner)
RewardMark(plr,ITEM_LOSER_COUNT);
+
plr->SetHealth(plr->GetMaxHealth());
plr->SetPower(POWER_MANA, plr->GetMaxPower(POWER_MANA));
plr->CombatStopWithPets(true);
@@ -1277,7 +1278,9 @@ void BattleGround::EventPlayerLoggedOut(Player* player)
if (GetAlivePlayersCountByTeam(player->GetTeam()) <= 1 && GetPlayersCountByTeam(GetOtherTeam(player->GetTeam())))
EndBattleGround(GetOtherTeam(player->GetTeam()));
}
+ return;
}
+ player->LeaveBattleground();
}
/* This method should be called only once ... it adds pointer to queue */
@@ -1445,15 +1448,14 @@ void BattleGround::RemovePlayerFromResurrectQueue(uint64 player_guid)
bool BattleGround::AddObject(uint32 type, uint32 entry, float x, float y, float z, float o, float rotation0, float rotation1, float rotation2, float rotation3, uint32 respawnTime)
{
- Map * map = MapManager::Instance().FindMap(GetMapId(),GetInstanceID());
+ Map *map = GetBgMap();
if (!map)
return false;
-
// must be created this way, adding to godatamap would add it to the base map of the instance
// and when loading it (in go::LoadFromDB()), a new guid would be assigned to the object, and a new object would be created
// so we must create it specific for this instance
GameObject * go = new GameObject;
- if(!go->Create(objmgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT),entry, map,
+ if(!go->Create(objmgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT),entry, GetBgMap(),
PHASEMASK_NORMAL, x,y,z,o,rotation0,rotation1,rotation2,rotation3,100,GO_STATE_READY))
{
sLog.outErrorDb("Gameobject template %u not found in database! BattleGround not created!", entry);
@@ -1493,7 +1495,7 @@ bool BattleGround::AddObject(uint32 type, uint32 entry, float x, float y, float
//it would be nice to correctly implement GO_ACTIVATED state and open/close doors in gameobject code
void BattleGround::DoorClose(uint32 type)
{
- GameObject *obj = HashMapHolder<GameObject>::Find(m_BgObjects[type]);
+ GameObject *obj = GetBgMap()->GetGameObject(m_BgObjects[type]);
if (obj)
{
//if doors are open, close it
@@ -1512,7 +1514,7 @@ void BattleGround::DoorClose(uint32 type)
void BattleGround::DoorOpen(uint32 type)
{
- GameObject *obj = HashMapHolder<GameObject>::Find(m_BgObjects[type]);
+ GameObject *obj = GetBgMap()->GetGameObject(m_BgObjects[type]);
if (obj)
{
//change state to be sure they will be opened
@@ -1527,7 +1529,7 @@ void BattleGround::DoorOpen(uint32 type)
GameObject* BattleGround::GetBGObject(uint32 type)
{
- GameObject *obj = HashMapHolder<GameObject>::Find(m_BgObjects[type]);
+ GameObject *obj = GetBgMap()->GetGameObject(m_BgObjects[type]);
if(!obj)
sLog.outError("couldn't get gameobject %i",type);
return obj;
@@ -1535,7 +1537,7 @@ GameObject* BattleGround::GetBGObject(uint32 type)
Creature* BattleGround::GetBGCreature(uint32 type)
{
- Creature *creature = HashMapHolder<Creature>::Find(m_BgCreatures[type]);
+ Creature *creature = GetBgMap()->GetCreature(m_BgCreatures[type]);
if(!creature)
sLog.outError("couldn't get creature %i",type);
return creature;
@@ -1543,12 +1545,12 @@ Creature* BattleGround::GetBGCreature(uint32 type)
void BattleGround::SpawnBGObject(uint32 type, uint32 respawntime)
{
- Map * map = MapManager::Instance().FindMap(GetMapId(),GetInstanceID());
+ Map * map = GetBgMap();
if (!map)
return;
if (respawntime == 0)
{
- GameObject *obj = HashMapHolder<GameObject>::Find(m_BgObjects[type]);
+ GameObject *obj = map->GetGameObject(m_BgObjects[type]);
if (obj)
{
//we need to change state from GO_JUST_DEACTIVATED to GO_READY in case battleground is starting again
@@ -1560,7 +1562,7 @@ void BattleGround::SpawnBGObject(uint32 type, uint32 respawntime)
}
else
{
- GameObject *obj = HashMapHolder<GameObject>::Find(m_BgObjects[type]);
+ GameObject *obj = map->GetGameObject(m_BgObjects[type]);
if (obj)
{
map->Add(obj);
@@ -1572,7 +1574,7 @@ void BattleGround::SpawnBGObject(uint32 type, uint32 respawntime)
Creature* BattleGround::AddCreature(uint32 entry, uint32 type, uint32 teamval, float x, float y, float z, float o, uint32 respawntime)
{
- Map * map = MapManager::Instance().FindMap(GetMapId(),GetInstanceID());
+ Map * map = GetBgMap();
if (!map)
return NULL;
@@ -1628,7 +1630,7 @@ bool BattleGround::DelCreature(uint32 type)
if (!m_BgCreatures[type])
return true;
- Creature *cr = HashMapHolder<Creature>::Find(m_BgCreatures[type]);
+ Creature *cr = GetBgMap()->GetCreature(m_BgCreatures[type]);
if (!cr)
{
sLog.outError("Can't find creature guid: %u",GUID_LOPART(m_BgCreatures[type]));
@@ -1644,7 +1646,7 @@ bool BattleGround::DelObject(uint32 type)
if (!m_BgObjects[type])
return true;
- GameObject *obj = HashMapHolder<GameObject>::Find(m_BgObjects[type]);
+ GameObject *obj = GetBgMap()->GetGameObject(m_BgObjects[type]);
if (!obj)
{
sLog.outError("Can't find gobject guid: %u",GUID_LOPART(m_BgObjects[type]));
@@ -1679,10 +1681,6 @@ bool BattleGround::AddSpiritGuide(uint32 type, float x, float y, float z, float
// aura
//TODO: Fix display here
//pCreature->SetVisibleAura(0, SPELL_SPIRIT_HEAL_CHANNEL);
-
- //pCreature->SetUInt32Value(UNIT_FIELD_AURAFLAGS, 0x00000009);
- //pCreature->SetUInt32Value(UNIT_FIELD_AURALEVELS, 0x0000003C);
- //pCreature->SetUInt32Value(UNIT_FIELD_AURAAPPLICATIONS, 0x000000FF);
// casting visual effect
pCreature->SetUInt32Value(UNIT_CHANNEL_SPELL, SPELL_SPIRIT_HEAL_CHANNEL);
// correct cast speed
@@ -1740,7 +1738,7 @@ buffs are in their positions when battleground starts
*/
void BattleGround::HandleTriggerBuff(uint64 const& go_guid)
{
- GameObject *obj = HashMapHolder<GameObject>::Find(go_guid);
+ GameObject *obj = GetBgMap()->GetGameObject(go_guid);
if (!obj || obj->GetGoType() != GAMEOBJECT_TYPE_TRAP || !obj->isSpawned())
return;
@@ -1887,10 +1885,10 @@ void BattleGround::CheckArenaWinConditions()
EndBattleGround(ALLIANCE);
}
-void BattleGround::UpdateArenaUnitWorldState()
+void BattleGround::UpdateArenaWorldState()
{
- UpdateWorldState(HORDE_WORLD_STATE, GetAlivePlayersCountByTeam(HORDE));
- UpdateWorldState(ALLIANCE_WORLD_STATE, GetAlivePlayersCountByTeam(ALLIANCE));
+ UpdateWorldState(0xe10, GetAlivePlayersCountByTeam(HORDE));
+ UpdateWorldState(0xe11, GetAlivePlayersCountByTeam(ALLIANCE));
}
void BattleGround::SetBgRaid( uint32 TeamID, Group *bg_raid )
diff --git a/src/game/BattleGround.h b/src/game/BattleGround.h
index 275085f4ca7..7a1bcbc58ea 100644
--- a/src/game/BattleGround.h
+++ b/src/game/BattleGround.h
@@ -29,6 +29,7 @@ class GameObject;
class Group;
class Player;
class WorldPacket;
+class BattleGroundMap;
struct WorldSafeLocsEntry;
@@ -97,9 +98,9 @@ enum BattleGroundSpells
enum BattleGroundTimeIntervals
{
RESURRECTION_INTERVAL = 30000, // ms
- REMIND_INTERVAL = 30000, // ms
- INVITATION_REMIND_TIME = 60000, // ms
- INVITE_ACCEPT_WAIT_TIME = 80000, // ms
+ //REMIND_INTERVAL = 10000, // ms
+ INVITATION_REMIND_TIME = 20000, // ms
+ INVITE_ACCEPT_WAIT_TIME = 40000, // ms
TIME_TO_AUTOREMOVE = 120000, // ms
MAX_OFFLINE_TIME = 300, // secs
RESPAWN_ONE_DAY = 86400, // secs
@@ -158,11 +159,12 @@ enum BattleGroundQueueTypeId
BATTLEGROUND_QUEUE_AB = 3,
BATTLEGROUND_QUEUE_EY = 4,
BATTLEGROUND_QUEUE_SA = 5,
- BATTLEGROUND_QUEUE_2v2 = 6,
- BATTLEGROUND_QUEUE_3v3 = 7,
- BATTLEGROUND_QUEUE_5v5 = 8
+ BATTLEGROUND_QUEUE_IC = 6,
+ BATTLEGROUND_QUEUE_2v2 = 7,
+ BATTLEGROUND_QUEUE_3v3 = 8,
+ BATTLEGROUND_QUEUE_5v5 = 9,
+ MAX_BATTLEGROUND_QUEUE_TYPES
};
-#define MAX_BATTLEGROUND_QUEUE_TYPES 9
enum BGQueueIdBasedOnLevel // queue_id for level ranges
{
@@ -210,12 +212,6 @@ enum ArenaType
ARENA_TYPE_5v5 = 5
};
-enum ArenaWorldUnitState
-{
- HORDE_WORLD_STATE = 0xE10,
- ALLIANCE_WORLD_STATE = 0xE11
-};
-
enum BattleGroundType
{
TYPE_BATTLEGROUND = 3,
@@ -420,6 +416,14 @@ class BattleGround
void SetMapId(uint32 MapID) { m_MapId = MapID; }
uint32 GetMapId() const { return m_MapId; }
+ /* Map pointers */
+ void SetBgMap(BattleGroundMap* map) { m_Map = map; }
+ BattleGroundMap* GetBgMap()
+ {
+ ASSERT(m_Map);
+ return m_Map;
+ }
+
void SetTeamStartLoc(uint32 TeamID, float X, float Y, float Z, float O);
void GetTeamStartLoc(uint32 TeamID, float &X, float &Y, float &Z, float &O) const
{
@@ -484,7 +488,7 @@ class BattleGround
void SetArenaTeamRatingChangeForTeam(uint32 Team, int32 RatingChange) { m_ArenaTeamRatingChanges[GetTeamIndexByTeamId(Team)] = RatingChange; }
int32 GetArenaTeamRatingChangeForTeam(uint32 Team) const { return m_ArenaTeamRatingChanges[GetTeamIndexByTeamId(Team)]; }
void CheckArenaWinConditions();
- void UpdateArenaUnitWorldState();
+ void UpdateArenaWorldState();
/* Triggers handle */
// must be implemented in BG subclass
@@ -623,6 +627,7 @@ class BattleGround
/* Start location */
uint32 m_MapId;
+ BattleGroundMap* m_Map;
float m_TeamStartLocX[BG_TEAMS_COUNT];
float m_TeamStartLocY[BG_TEAMS_COUNT];
float m_TeamStartLocZ[BG_TEAMS_COUNT];
diff --git a/src/game/BattleGroundAB.cpp b/src/game/BattleGroundAB.cpp
index b684f4523e1..0fea16bfcbd 100644
--- a/src/game/BattleGroundAB.cpp
+++ b/src/game/BattleGroundAB.cpp
@@ -420,11 +420,11 @@ void BattleGroundAB::EventPlayerClickedOnFlag(Player *source, GameObject* /*targ
return;
uint8 node = BG_AB_NODE_STABLES;
- GameObject* obj=HashMapHolder<GameObject>::Find(m_BgObjects[node*8+7]);
+ GameObject* obj=GetBgMap()->GetGameObject(m_BgObjects[node*8+7]);
while ( (node < BG_AB_DYNAMIC_NODES_COUNT) && ((!obj) || (!source->IsWithinDistInMap(obj,10))))
{
++node;
- obj=HashMapHolder<GameObject>::Find(m_BgObjects[node*8+BG_AB_OBJECT_AURA_CONTESTED]);
+ obj=GetBgMap()->GetGameObject(m_BgObjects[node*8+BG_AB_OBJECT_AURA_CONTESTED]);
}
if (node == BG_AB_DYNAMIC_NODES_COUNT)
diff --git a/src/game/BattleGroundAB.h b/src/game/BattleGroundAB.h
index ef151ad187b..bdc073f6ec8 100644
--- a/src/game/BattleGroundAB.h
+++ b/src/game/BattleGroundAB.h
@@ -130,8 +130,8 @@ enum BG_AB_Timers
enum BG_AB_Score
{
- BG_AB_WARNING_NEAR_VICTORY_SCORE = 1800,
- BG_AB_MAX_TEAM_SCORE = 2000
+ BG_AB_WARNING_NEAR_VICTORY_SCORE = 1400,
+ BG_AB_MAX_TEAM_SCORE = 1600
};
/* do NOT change the order, else wrong behaviour */
diff --git a/src/game/BattleGroundABG.cpp b/src/game/BattleGroundABG.cpp
new file mode 100644
index 00000000000..f0ae47482f1
--- /dev/null
+++ b/src/game/BattleGroundABG.cpp
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "Player.h"
+#include "BattleGround.h"
+#include "BattleGroundABG.h"
+#include "Language.h"
+
+BattleGroundABG::BattleGroundABG()
+{
+ //TODO FIX ME!
+ m_StartMessageIds[BG_STARTING_EVENT_FIRST] = LANG_BG_WS_START_TWO_MINUTES;
+ m_StartMessageIds[BG_STARTING_EVENT_SECOND] = LANG_BG_WS_START_ONE_MINUTE;
+ m_StartMessageIds[BG_STARTING_EVENT_THIRD] = LANG_BG_WS_START_HALF_MINUTE;
+ m_StartMessageIds[BG_STARTING_EVENT_FOURTH] = LANG_BG_WS_HAS_BEGUN;
+}
+
+BattleGroundABG::~BattleGroundABG()
+{
+
+}
+
+void BattleGroundABG::Update(uint32 diff)
+{
+ BattleGround::Update(diff);
+}
+
+void BattleGroundABG::StartingEventCloseDoors()
+{
+}
+
+void BattleGroundABG::StartingEventOpenDoors()
+{
+}
+
+void BattleGroundABG::AddPlayer(Player *plr)
+{
+ BattleGround::AddPlayer(plr);
+ //create score and add it to map, default values are set in constructor
+ BattleGroundABGScore* sc = new BattleGroundABGScore;
+
+ m_PlayerScores[plr->GetGUID()] = sc;
+}
+
+void BattleGroundABG::RemovePlayer(Player* /*plr*/,uint64 /*guid*/)
+{
+
+}
+
+void BattleGroundABG::HandleAreaTrigger(Player * /*Source*/, uint32 /*Trigger*/)
+{
+ // this is wrong way to implement these things. On official it done by gameobject spell cast.
+ if (GetStatus() != STATUS_IN_PROGRESS)
+ return;
+}
+
+void BattleGroundABG::UpdatePlayerScore(Player* Source, uint32 type, uint32 value)
+{
+
+ std::map<uint64, BattleGroundScore*>::iterator itr = m_PlayerScores.find(Source->GetGUID());
+
+ if(itr == m_PlayerScores.end()) // player not found...
+ return;
+
+ BattleGround::UpdatePlayerScore(Source,type,value);
+} \ No newline at end of file
diff --git a/src/game/BattleGroundABG.h b/src/game/BattleGroundABG.h
new file mode 100644
index 00000000000..478e8ffaf46
--- /dev/null
+++ b/src/game/BattleGroundABG.h
@@ -0,0 +1,54 @@
+/*
+ * 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
+ */
+
+#ifndef __BATTLEGROUNDABG_H
+#define __BATTLEGROUNDABG_H
+
+class BattleGround;
+
+class BattleGroundABGScore : public BattleGroundScore
+{
+ public:
+ BattleGroundABGScore() {};
+ virtual ~BattleGroundABGScore() {};
+};
+
+class BattleGroundABG : public BattleGround
+{
+ friend class BattleGroundMgr;
+
+ public:
+ BattleGroundABG();
+ ~BattleGroundABG();
+ void Update(uint32 diff);
+
+ /* inherited from BattlegroundClass */
+ virtual void AddPlayer(Player *plr);
+ virtual void StartingEventCloseDoors();
+ virtual void StartingEventOpenDoors();
+
+ void RemovePlayer(Player *plr,uint64 guid);
+ void HandleAreaTrigger(Player *Source, uint32 Trigger);
+ //bool SetupBattleGround();
+
+ /* Scorekeeping */
+ void UpdatePlayerScore(Player *Source, uint32 type, uint32 value);
+
+ private:
+};
+#endif \ No newline at end of file
diff --git a/src/game/BattleGroundBE.cpp b/src/game/BattleGroundBE.cpp
index c20af53e013..057846285bd 100644
--- a/src/game/BattleGroundBE.cpp
+++ b/src/game/BattleGroundBE.cpp
@@ -82,7 +82,7 @@ void BattleGroundBE::AddPlayer(Player *plr)
m_PlayerScores[plr->GetGUID()] = sc;
- UpdateArenaUnitWorldState();
+ UpdateArenaWorldState();
}
void BattleGroundBE::RemovePlayer(Player* /*plr*/, uint64 /*guid*/)
@@ -90,7 +90,7 @@ void BattleGroundBE::RemovePlayer(Player* /*plr*/, uint64 /*guid*/)
if (GetStatus() == STATUS_WAIT_LEAVE)
return;
- UpdateArenaUnitWorldState();
+ UpdateArenaWorldState();
CheckArenaWinConditions();
}
@@ -107,7 +107,7 @@ void BattleGroundBE::HandleKillPlayer(Player *player, Player *killer)
BattleGround::HandleKillPlayer(player,killer);
- UpdateArenaUnitWorldState();
+ UpdateArenaWorldState();
CheckArenaWinConditions();
}
@@ -146,8 +146,7 @@ void BattleGroundBE::HandleAreaTrigger(Player *Source, uint32 Trigger)
void BattleGroundBE::FillInitialWorldStates(WorldPacket &data)
{
data << uint32(0x9f3) << uint32(1); // 9
-
- UpdateArenaUnitWorldState();
+ UpdateArenaWorldState();
}
void BattleGroundBE::Reset()
@@ -200,4 +199,3 @@ spell 32725 - Green Team
35774 Gold Team
35775 Green Team
*/
-
diff --git a/src/game/BattleGroundBE.h b/src/game/BattleGroundBE.h
index e75e332f44f..7e48a3998c0 100644
--- a/src/game/BattleGroundBE.h
+++ b/src/game/BattleGroundBE.h
@@ -76,4 +76,3 @@ class BattleGroundBE : public BattleGround
void UpdatePlayerScore(Player *Source, uint32 type, uint32 value);
};
#endif
-
diff --git a/src/game/BattleGroundDS.cpp b/src/game/BattleGroundDS.cpp
index 0be870be175..9036ef83f93 100644
--- a/src/game/BattleGroundDS.cpp
+++ b/src/game/BattleGroundDS.cpp
@@ -20,9 +20,13 @@
#include "BattleGroundDS.h"
#include "Language.h"
#include "Player.h"
+#include "Object.h"
+#include "ObjectMgr.h"
+#include "WorldPacket.h"
BattleGroundDS::BattleGroundDS()
{
+ m_BgObjects.resize(BG_DS_OBJECT_MAX);
m_StartDelayTimes[BG_STARTING_EVENT_FIRST] = BG_START_DELAY_1M;
m_StartDelayTimes[BG_STARTING_EVENT_SECOND] = BG_START_DELAY_30S;
@@ -43,14 +47,46 @@ BattleGroundDS::~BattleGroundDS()
void BattleGroundDS::Update(uint32 diff)
{
BattleGround::Update(diff);
+ if (getWaterFallTimer() < diff)
+ {
+ if (isWaterFallActive())
+ {
+ setWaterFallTimer(urand(BG_DS_WATERFALL_TIMER_MIN, BG_DS_WATERFALL_TIMER_MAX));
+ for (uint32 i = BG_DS_OBJECT_WATER_1; i <= BG_DS_OBJECT_WATER_2; ++i)
+ SpawnBGObject(i, getWaterFallTimer());
+ setWaterFallActive(false);
+ }
+ else
+ {
+ setWaterFallTimer(BG_DS_WATERFALL_DURATION);
+ for (uint32 i = BG_DS_OBJECT_WATER_1; i <= BG_DS_OBJECT_WATER_2; ++i)
+ SpawnBGObject(i, RESPAWN_IMMEDIATELY);
+ setWaterFallActive(true);
+ }
+ }
+ else
+ setWaterFallTimer(getWaterFallTimer() - diff);
}
void BattleGroundDS::StartingEventCloseDoors()
{
+ for (uint32 i = BG_DS_OBJECT_DOOR_1; i <= BG_DS_OBJECT_DOOR_2; ++i)
+ SpawnBGObject(i, RESPAWN_IMMEDIATELY);
}
void BattleGroundDS::StartingEventOpenDoors()
{
+ for (uint32 i = BG_DS_OBJECT_DOOR_1; i <= BG_DS_OBJECT_DOOR_2; ++i)
+ DoorOpen(i);
+
+ for (uint32 i = BG_DS_OBJECT_BUFF_1; i <= BG_DS_OBJECT_BUFF_2; ++i)
+ SpawnBGObject(i, 60);
+
+ setWaterFallTimer(urand(BG_DS_WATERFALL_TIMER_MIN, BG_DS_WATERFALL_TIMER_MAX));
+ setWaterFallActive(false);
+
+ for (uint32 i = BG_DS_OBJECT_WATER_1; i <= BG_DS_OBJECT_WATER_2; ++i)
+ SpawnBGObject(i, getWaterFallTimer());
}
void BattleGroundDS::AddPlayer(Player *plr)
@@ -60,22 +96,87 @@ void BattleGroundDS::AddPlayer(Player *plr)
BattleGroundDSScore* sc = new BattleGroundDSScore;
m_PlayerScores[plr->GetGUID()] = sc;
+
+ UpdateArenaWorldState();
}
void BattleGroundDS::RemovePlayer(Player * /*plr*/, uint64 /*guid*/)
{
+ if (GetStatus() == STATUS_WAIT_LEAVE)
+ return;
+
+ UpdateArenaWorldState();
+ CheckArenaWinConditions();
}
void BattleGroundDS::HandleKillPlayer(Player* player, Player* killer)
{
- BattleGround::HandleKillPlayer(player, killer);
+ if (GetStatus() != STATUS_IN_PROGRESS)
+ return;
+
+ if (!killer)
+ {
+ sLog.outError("BattleGroundDS: Killer player not found");
+ return;
+ }
+
+ BattleGround::HandleKillPlayer(player,killer);
+
+ UpdateArenaWorldState();
+ CheckArenaWinConditions();
}
-void BattleGroundDS::HandleAreaTrigger(Player * /*Source*/, uint32 /*Trigger*/)
+void BattleGroundDS::HandleAreaTrigger(Player *Source, uint32 Trigger)
{
+ if (GetStatus() != STATUS_IN_PROGRESS)
+ return;
+
+ switch(Trigger)
+ {
+ case 5347:
+ case 5348:
+ break;
+ default:
+ sLog.outError("WARNING: Unhandled AreaTrigger in Battleground: %u", Trigger);
+ Source->GetSession()->SendAreaTriggerMessage("Warning: Unhandled AreaTrigger in Battleground: %u", Trigger);
+ break;
+ }
}
+bool BattleGroundDS::HandlePlayerUnderMap(Player *player)
+{
+ player->TeleportTo(GetMapId(), 1299.046, 784.825, 9.338, 2.422, false);
+ return true;
+}
+
+void BattleGroundDS::FillInitialWorldStates(WorldPacket &data)
+{
+ data << uint32(3610) << uint32(1); // 9 show
+ UpdateArenaWorldState();
+}
+
+void BattleGroundDS::Reset()
+{
+ //call parent's class reset
+ BattleGround::Reset();
+}
+
+
bool BattleGroundDS::SetupBattleGround()
{
+ // gates
+ if (!AddObject(BG_DS_OBJECT_DOOR_1, BG_DS_OBJECT_TYPE_DOOR_1, 1350.95, 817.2, 20.8096, 3.15, 0, 0, 0.99627, 0.0862864, RESPAWN_IMMEDIATELY)
+ || !AddObject(BG_DS_OBJECT_DOOR_2, BG_DS_OBJECT_TYPE_DOOR_2, 1232.65, 764.913, 20.0729, 6.3, 0, 0, 0.0310211, -0.999519, RESPAWN_IMMEDIATELY)
+ // water
+ || !AddObject(BG_DS_OBJECT_WATER_1, BG_DS_OBJECT_TYPE_WATER_1, 1291.56, 790.837, 7.1, 3.14238, 0, 0, 0.694215, -0.719768, 120)
+ || !AddObject(BG_DS_OBJECT_WATER_2, BG_DS_OBJECT_TYPE_WATER_2, 1291.56, 790.837, 7.1, 3.14238, 0, 0, 0.694215, -0.719768, 120)
+ // buffs
+ || !AddObject(BG_DS_OBJECT_BUFF_1, BG_DS_OBJECT_TYPE_BUFF_1, 1291.7, 813.424, 7.11472, 4.64562, 0, 0, 0.730314, -0.683111, 120)
+ || !AddObject(BG_DS_OBJECT_BUFF_2, BG_DS_OBJECT_TYPE_BUFF_2, 1291.7, 768.911, 7.11472, 1.55194, 0, 0, 0.700409, 0.713742, 120))
+ {
+ sLog.outErrorDb("BatteGroundDS: Failed to spawn some object!");
+ return false;
+ }
+
return true;
}
diff --git a/src/game/BattleGroundDS.h b/src/game/BattleGroundDS.h
index 44a6cfbd33a..2ced5c88fd1 100644
--- a/src/game/BattleGroundDS.h
+++ b/src/game/BattleGroundDS.h
@@ -20,6 +20,34 @@
class BattleGround;
+enum BattleGroundDSObjectTypes
+{
+ BG_DS_OBJECT_DOOR_1 = 0,
+ BG_DS_OBJECT_DOOR_2 = 1,
+ BG_DS_OBJECT_WATER_1 = 2,
+ BG_DS_OBJECT_WATER_2 = 3,
+ BG_DS_OBJECT_BUFF_1 = 4,
+ BG_DS_OBJECT_BUFF_2 = 5,
+ BG_DS_OBJECT_MAX = 6
+};
+
+enum BattleGroundDSObjects
+{
+ BG_DS_OBJECT_TYPE_DOOR_1 = 192642,
+ BG_DS_OBJECT_TYPE_DOOR_2 = 192643,
+ BG_DS_OBJECT_TYPE_WATER_1 = 194395,
+ BG_DS_OBJECT_TYPE_WATER_2 = 191877,
+ BG_DS_OBJECT_TYPE_BUFF_1 = 184663,
+ BG_DS_OBJECT_TYPE_BUFF_2 = 184664
+};
+
+enum BattleGroundDSData
+{ // These values are NOT blizzlike... need the correct data!
+ BG_DS_WATERFALL_TIMER_MIN = 30000,
+ BG_DS_WATERFALL_TIMER_MAX = 60000,
+ BG_DS_WATERFALL_DURATION = 10000,
+};
+
class BattleGroundDSScore : public BattleGroundScore
{
public:
@@ -45,6 +73,17 @@ class BattleGroundDS : public BattleGround
void RemovePlayer(Player *plr, uint64 guid);
void HandleAreaTrigger(Player *Source, uint32 Trigger);
bool SetupBattleGround();
+ virtual void Reset();
+ virtual void FillInitialWorldStates(WorldPacket &d);
void HandleKillPlayer(Player* player, Player *killer);
+ bool HandlePlayerUnderMap(Player * plr);
+ private:
+ uint32 m_waterTimer;
+ bool m_waterfallActive;
+ protected:
+ bool isWaterFallActive() { return m_waterfallActive; };
+ void setWaterFallActive(bool active) { m_waterfallActive = active; };
+ void setWaterFallTimer(uint32 timer) { m_waterTimer = timer; };
+ uint32 getWaterFallTimer() { return m_waterTimer; };
};
#endif
diff --git a/src/game/BattleGroundHandler.cpp b/src/game/BattleGroundHandler.cpp
index 8413198272e..3944d4e0bfc 100644
--- a/src/game/BattleGroundHandler.cpp
+++ b/src/game/BattleGroundHandler.cpp
@@ -285,7 +285,10 @@ void WorldSession::HandleBattlefieldListOpcode( WorldPacket &recv_data )
recv_data >> bgTypeId; // id from DBC
uint8 fromWhere;
- recv_data >> fromWhere; // 0 - battlemaster, 1 - UI
+ recv_data >> fromWhere; // 0 - battlemaster (lua: ShowBattlefieldList), 1 - UI (lua: RequestBattlegroundInstanceInfo)
+
+ uint8 unk1;
+ recv_data >> unk1; // Unknown 3.2.2
BattlemasterListEntry const* bl = sBattlemasterListStore.LookupEntry(bgTypeId);
if (!bl)
@@ -742,7 +745,7 @@ void WorldSession::HandleBattlemasterJoinArena( WorldPacket & recv_data )
Player *member = itr->getSource();
// calc avg personal rating
- avg_pers_rating += member->GetUInt32Value(PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + (arenaslot*6) + 5);
+ avg_pers_rating += member->GetUInt32Value(PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + (arenaslot * ARENA_TEAM_END) + ARENA_TEAM_PERSONAL_RATING);
}
if (arenatype)
diff --git a/src/game/BattleGroundIC.cpp b/src/game/BattleGroundIC.cpp
new file mode 100644
index 00000000000..216b7cbe727
--- /dev/null
+++ b/src/game/BattleGroundIC.cpp
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "Player.h"
+#include "BattleGround.h"
+#include "BattleGroundIC.h"
+#include "Language.h"
+
+BattleGroundIC::BattleGroundIC()
+{
+ //TODO FIX ME!
+ m_StartMessageIds[BG_STARTING_EVENT_FIRST] = LANG_BG_WS_START_TWO_MINUTES;
+ m_StartMessageIds[BG_STARTING_EVENT_SECOND] = LANG_BG_WS_START_ONE_MINUTE;
+ m_StartMessageIds[BG_STARTING_EVENT_THIRD] = LANG_BG_WS_START_HALF_MINUTE;
+ m_StartMessageIds[BG_STARTING_EVENT_FOURTH] = LANG_BG_WS_HAS_BEGUN;
+}
+
+BattleGroundIC::~BattleGroundIC()
+{
+
+}
+
+void BattleGroundIC::Update(uint32 diff)
+{
+ BattleGround::Update(diff);
+}
+
+void BattleGroundIC::StartingEventCloseDoors()
+{
+}
+
+void BattleGroundIC::StartingEventOpenDoors()
+{
+}
+
+void BattleGroundIC::AddPlayer(Player *plr)
+{
+ BattleGround::AddPlayer(plr);
+ //create score and add it to map, default values are set in constructor
+ BattleGroundICScore* sc = new BattleGroundICScore;
+
+ m_PlayerScores[plr->GetGUID()] = sc;
+}
+
+void BattleGroundIC::RemovePlayer(Player* /*plr*/,uint64 /*guid*/)
+{
+
+}
+
+void BattleGroundIC::HandleAreaTrigger(Player * /*Source*/, uint32 /*Trigger*/)
+{
+ // this is wrong way to implement these things. On official it done by gameobject spell cast.
+ if (GetStatus() != STATUS_IN_PROGRESS)
+ return;
+}
+
+void BattleGroundIC::UpdatePlayerScore(Player* Source, uint32 type, uint32 value)
+{
+
+ std::map<uint64, BattleGroundScore*>::iterator itr = m_PlayerScores.find(Source->GetGUID());
+
+ if(itr == m_PlayerScores.end()) // player not found...
+ return;
+
+ BattleGround::UpdatePlayerScore(Source,type,value);
+} \ No newline at end of file
diff --git a/src/game/BattleGroundIC.h b/src/game/BattleGroundIC.h
new file mode 100644
index 00000000000..5c4b17cc926
--- /dev/null
+++ b/src/game/BattleGroundIC.h
@@ -0,0 +1,54 @@
+/*
+ * 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
+ */
+
+#ifndef __BATTLEGROUNDIC_H
+#define __BATTLEGROUNDIC_H
+
+class BattleGround;
+
+class BattleGroundICScore : public BattleGroundScore
+{
+ public:
+ BattleGroundICScore() {};
+ virtual ~BattleGroundICScore() {};
+};
+
+class BattleGroundIC : public BattleGround
+{
+ friend class BattleGroundMgr;
+
+ public:
+ BattleGroundIC();
+ ~BattleGroundIC();
+ void Update(uint32 diff);
+
+ /* inherited from BattlegroundClass */
+ virtual void AddPlayer(Player *plr);
+ virtual void StartingEventCloseDoors();
+ virtual void StartingEventOpenDoors();
+
+ void RemovePlayer(Player *plr,uint64 guid);
+ void HandleAreaTrigger(Player *Source, uint32 Trigger);
+ //bool SetupBattleGround();
+
+ /* Scorekeeping */
+ void UpdatePlayerScore(Player *Source, uint32 type, uint32 value);
+
+ private:
+};
+#endif \ No newline at end of file
diff --git a/src/game/BattleGroundMgr.cpp b/src/game/BattleGroundMgr.cpp
index 926759c0373..56fbf772aea 100644
--- a/src/game/BattleGroundMgr.cpp
+++ b/src/game/BattleGroundMgr.cpp
@@ -37,6 +37,8 @@
#include "BattleGroundSA.h"
#include "BattleGroundDS.h"
#include "BattleGroundRV.h"
+#include "BattleGroundIC.h"
+#include "BattleGroundABG.h"
#include "Chat.h"
#include "Map.h"
#include "MapInstanced.h"
@@ -155,7 +157,7 @@ GroupQueueInfo * BattleGroundQueue::AddGroup(Player *leader, BattleGroundTypeId
// create new ginfo
// cannot use the method like in addplayer, because that could modify an in-queue group's stats
// (e.g. leader leaving queue then joining as individual again)
- GroupQueueInfo* ginfo = new GroupQueueInfo;
+ GroupQueueInfo* ginfo = new GroupQueueInfo;
ginfo->BgTypeId = BgTypeId;
ginfo->ArenaType = ArenaType;
ginfo->ArenaTeamId = arenateamid;
@@ -1423,6 +1425,8 @@ void BattleGroundMgr::BuildPvpLogDataPacket(WorldPacket *data, BattleGround *bg)
case BATTLEGROUND_SA: // wotlk
case BATTLEGROUND_DS: // wotlk
case BATTLEGROUND_RV: // wotlk
+ case BATTLEGROUND_IC: // wotlk
+ case BATTLEGROUND_ABG: // wotlk
*data << (int32)0; // 0
break;
default:
@@ -1602,6 +1606,12 @@ BattleGround * BattleGroundMgr::CreateNewBattleGround(BattleGroundTypeId bgTypeI
case BATTLEGROUND_RV:
bg = new BattleGroundRV(*(BattleGroundRV*)bg_template);
break;
+ case BATTLEGROUND_IC:
+ bg = new BattleGroundIC(*(BattleGroundIC*)bg_template);
+ break;
+ case BATTLEGROUND_ABG:
+ bg = new BattleGroundABG(*(BattleGroundABG*)bg_template);
+ break;
default:
//error, but it is handled few lines above
return 0;
@@ -1641,7 +1651,11 @@ uint32 BattleGroundMgr::CreateBattleGround(BattleGroundTypeId bgTypeId, bool IsA
case BATTLEGROUND_SA: bg = new BattleGroundSA; break;
case BATTLEGROUND_DS: bg = new BattleGroundDS; break;
case BATTLEGROUND_RV: bg = new BattleGroundRV; break;
- default:bg = new BattleGround; break; // placeholder for non implemented BG
+ case BATTLEGROUND_IC: bg = new BattleGroundIC; break;
+ case BATTLEGROUND_ABG: bg = new BattleGroundABG; break;
+ default:
+ bg = new BattleGround;
+ break;
}
bg->SetMapId(MapID);
@@ -1735,7 +1749,7 @@ void BattleGroundMgr::CreateInitialBattleGrounds()
AStartLoc[2] = start->z;
AStartLoc[3] = fields[6].GetFloat();
}
- else if (bgTypeID == BATTLEGROUND_AA)
+ else if (bgTypeID == BATTLEGROUND_AA || bgTypeID == BATTLEGROUND_ABG)
{
AStartLoc[0] = 0;
AStartLoc[1] = 0;
@@ -1758,7 +1772,7 @@ void BattleGroundMgr::CreateInitialBattleGrounds()
HStartLoc[2] = start->z;
HStartLoc[3] = fields[8].GetFloat();
}
- else if (bgTypeID == BATTLEGROUND_AA)
+ else if (bgTypeID == BATTLEGROUND_AA || bgTypeID == BATTLEGROUND_ABG)
{
HStartLoc[0] = 0;
HStartLoc[1] = 0;
@@ -1931,7 +1945,8 @@ bool BattleGroundMgr::IsArenaType(BattleGroundTypeId bgTypeId)
bgTypeId == BATTLEGROUND_NA ||
bgTypeId == BATTLEGROUND_DS ||
bgTypeId == BATTLEGROUND_RV ||
- bgTypeId == BATTLEGROUND_RL );
+ bgTypeId == BATTLEGROUND_RL ||
+ bgTypeId == BATTLEGROUND_DS );
}
BattleGroundQueueTypeId BattleGroundMgr::BGQueueTypeId(BattleGroundTypeId bgTypeId, uint8 arenaType)
@@ -1948,6 +1963,10 @@ BattleGroundQueueTypeId BattleGroundMgr::BGQueueTypeId(BattleGroundTypeId bgType
return BATTLEGROUND_QUEUE_EY;
case BATTLEGROUND_SA:
return BATTLEGROUND_QUEUE_SA;
+ case BATTLEGROUND_IC:
+ return BATTLEGROUND_QUEUE_IC;
+ case BATTLEGROUND_ABG:
+ return BATTLEGROUND_QUEUE_NONE;
case BATTLEGROUND_AA:
case BATTLEGROUND_NA:
case BATTLEGROUND_RL:
@@ -1984,6 +2003,8 @@ BattleGroundTypeId BattleGroundMgr::BGTemplateId(BattleGroundQueueTypeId bgQueue
return BATTLEGROUND_EY;
case BATTLEGROUND_QUEUE_SA:
return BATTLEGROUND_SA;
+ case BATTLEGROUND_QUEUE_IC:
+ return BATTLEGROUND_IC;
case BATTLEGROUND_QUEUE_2v2:
case BATTLEGROUND_QUEUE_3v3:
case BATTLEGROUND_QUEUE_5v5:
@@ -2134,3 +2155,24 @@ bool BattleGroundMgr::IsBGWeekend(BattleGroundTypeId bgTypeId)
return false;
}
}
+
+void BattleGroundMgr::DoCompleteAchievement(uint32 achievement, Player * player)
+{
+ AchievementEntry const* AE = GetAchievementStore()->LookupEntry(achievement);
+
+ if(!player)
+ {
+ //Map::PlayerList const &PlayerList = this->GetPlayers();
+ //GroupsQueueType::iterator group = SelectedGroups.begin();
+
+ //if (!PlayerList.isEmpty())
+ //for (Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i)
+ // for (GroupsQueueType::iterator itr = group; itr != SelectedGroups.end(); ++itr)
+ // if (Player *pPlayer = itr->getSource())
+ // pPlayer->CompletedAchievement(AE);
+ }
+ else
+ {
+ player->CompletedAchievement(AE);
+ }
+}
diff --git a/src/game/BattleGroundMgr.h b/src/game/BattleGroundMgr.h
index 9100142ebd0..95b45640b69 100644
--- a/src/game/BattleGroundMgr.h
+++ b/src/game/BattleGroundMgr.h
@@ -250,6 +250,7 @@ class BattleGroundMgr
static uint8 BGArenaType(BattleGroundQueueTypeId bgQueueTypeId);
static bool IsBGWeekend(BattleGroundTypeId bgTypeId);
+ void DoCompleteAchievement(uint32 achievement, Player * player = NULL);
private:
BattleMastersMap mBattleMastersMap;
diff --git a/src/game/BattleGroundNA.cpp b/src/game/BattleGroundNA.cpp
index b08cdd1196e..da370de7136 100644
--- a/src/game/BattleGroundNA.cpp
+++ b/src/game/BattleGroundNA.cpp
@@ -79,7 +79,7 @@ void BattleGroundNA::AddPlayer(Player *plr)
m_PlayerScores[plr->GetGUID()] = sc;
- UpdateArenaUnitWorldState();
+ UpdateArenaWorldState();
}
void BattleGroundNA::RemovePlayer(Player* /*plr*/, uint64 /*guid*/)
@@ -87,7 +87,7 @@ void BattleGroundNA::RemovePlayer(Player* /*plr*/, uint64 /*guid*/)
if (GetStatus() == STATUS_WAIT_LEAVE)
return;
- UpdateArenaUnitWorldState();
+ UpdateArenaWorldState();
CheckArenaWinConditions();
}
@@ -104,7 +104,7 @@ void BattleGroundNA::HandleKillPlayer(Player *player, Player *killer)
BattleGround::HandleKillPlayer(player,killer);
- UpdateArenaUnitWorldState();
+ UpdateArenaWorldState();
CheckArenaWinConditions();
}
@@ -138,9 +138,8 @@ void BattleGroundNA::HandleAreaTrigger(Player *Source, uint32 Trigger)
void BattleGroundNA::FillInitialWorldStates(WorldPacket &data)
{
- data << uint32(0xa11) << uint32(1);
-
- UpdateArenaUnitWorldState();
+ data << uint32(0xa11) << uint32(1); // 9
+ UpdateArenaWorldState();
}
void BattleGroundNA::Reset()
@@ -176,4 +175,3 @@ bool BattleGroundNA::SetupBattleGround()
0040: 00 00 00 00 00 00 d5 08 00 00 00 00 00 00 d3 08 | ................
0050: 00 00 00 00 00 00 | ......
*/
-
diff --git a/src/game/BattleGroundNA.h b/src/game/BattleGroundNA.h
index 56e2cf373c4..57654bc0c60 100644
--- a/src/game/BattleGroundNA.h
+++ b/src/game/BattleGroundNA.h
@@ -74,4 +74,3 @@ class BattleGroundNA : public BattleGround
bool HandlePlayerUnderMap(Player * plr);
};
#endif
-
diff --git a/src/game/BattleGroundRL.cpp b/src/game/BattleGroundRL.cpp
index 8ed8fd1b5b7..4c072713162 100644
--- a/src/game/BattleGroundRL.cpp
+++ b/src/game/BattleGroundRL.cpp
@@ -79,7 +79,7 @@ void BattleGroundRL::AddPlayer(Player *plr)
m_PlayerScores[plr->GetGUID()] = sc;
- UpdateArenaUnitWorldState();
+ UpdateArenaWorldState();
}
void BattleGroundRL::RemovePlayer(Player* /*plr*/, uint64 /*guid*/)
@@ -87,7 +87,7 @@ void BattleGroundRL::RemovePlayer(Player* /*plr*/, uint64 /*guid*/)
if (GetStatus() == STATUS_WAIT_LEAVE)
return;
- UpdateArenaUnitWorldState();
+ UpdateArenaWorldState();
CheckArenaWinConditions();
}
@@ -104,7 +104,7 @@ void BattleGroundRL::HandleKillPlayer(Player *player, Player *killer)
BattleGround::HandleKillPlayer(player,killer);
- UpdateArenaUnitWorldState();
+ UpdateArenaWorldState();
CheckArenaWinConditions();
}
@@ -139,9 +139,8 @@ void BattleGroundRL::HandleAreaTrigger(Player *Source, uint32 Trigger)
void BattleGroundRL::FillInitialWorldStates(WorldPacket &data)
{
- data << uint32(0xbba) << uint32(1);
-
- UpdateArenaUnitWorldState();
+ data << uint32(0xbba) << uint32(1); // 9
+ UpdateArenaWorldState();
}
void BattleGroundRL::Reset()
@@ -175,4 +174,3 @@ Packet S->C, id 600, SMSG_INIT_WORLD_STATES (706), len 86
0040: 00 00 00 00 00 00 D3 08 00 00 00 00 00 00 D4 08 | ................
0050: 00 00 00 00 00 00 | ......
*/
-
diff --git a/src/game/BattleGroundRL.h b/src/game/BattleGroundRL.h
index 772c9dd0879..137ae751bca 100644
--- a/src/game/BattleGroundRL.h
+++ b/src/game/BattleGroundRL.h
@@ -70,4 +70,3 @@ class BattleGroundRL : public BattleGround
bool HandlePlayerUnderMap(Player * plr);
};
#endif
-
diff --git a/src/game/BattleGroundRV.cpp b/src/game/BattleGroundRV.cpp
index 16bdd54ade1..39ff09fe521 100644
--- a/src/game/BattleGroundRV.cpp
+++ b/src/game/BattleGroundRV.cpp
@@ -120,7 +120,8 @@ void BattleGroundRV::AddPlayer(Player *plr)
m_PlayerScores[plr->GetGUID()] = sc;
- UpdateArenaUnitWorldState();
+ UpdateWorldState(BG_RV_WORLD_STATE_A, GetAlivePlayersCountByTeam(ALLIANCE));
+ UpdateWorldState(BG_RV_WORLD_STATE_H, GetAlivePlayersCountByTeam(HORDE));
}
void BattleGroundRV::RemovePlayer(Player * /*plr*/, uint64 /*guid*/)
@@ -128,7 +129,9 @@ void BattleGroundRV::RemovePlayer(Player * /*plr*/, uint64 /*guid*/)
if (GetStatus() == STATUS_WAIT_LEAVE)
return;
- UpdateArenaUnitWorldState();
+ UpdateWorldState(BG_RV_WORLD_STATE_A, GetAlivePlayersCountByTeam(ALLIANCE));
+ UpdateWorldState(BG_RV_WORLD_STATE_H, GetAlivePlayersCountByTeam(HORDE));
+
CheckArenaWinConditions();
}
@@ -145,7 +148,9 @@ void BattleGroundRV::HandleKillPlayer(Player *player, Player *killer)
BattleGround::HandleKillPlayer(player, killer);
- UpdateArenaUnitWorldState();
+ UpdateWorldState(BG_RV_WORLD_STATE_A, GetAlivePlayersCountByTeam(ALLIANCE));
+ UpdateWorldState(BG_RV_WORLD_STATE_H, GetAlivePlayersCountByTeam(HORDE));
+
CheckArenaWinConditions();
}
@@ -175,9 +180,9 @@ void BattleGroundRV::HandleAreaTrigger(Player *Source, uint32 Trigger)
void BattleGroundRV::FillInitialWorldStates(WorldPacket &data)
{
+ data << uint32(BG_RV_WORLD_STATE_A) << uint32(GetAlivePlayersCountByTeam(ALLIANCE));
+ data << uint32(BG_RV_WORLD_STATE_H) << uint32(GetAlivePlayersCountByTeam(HORDE));
data << uint32(BG_RV_WORLD_STATE) << uint32(1);
-
- UpdateArenaUnitWorldState();
}
void BattleGroundRV::Reset()
diff --git a/src/game/BattleGroundRV.h b/src/game/BattleGroundRV.h
index 4cc368901dd..c4309ae93cf 100644
--- a/src/game/BattleGroundRV.h
+++ b/src/game/BattleGroundRV.h
@@ -92,7 +92,9 @@ enum BattleGroundRVData
BG_RV_FIRE_TO_PILAR_TIMER = 20000,
BG_RV_PILAR_TO_FIRE_TIMER = 5000,
BG_RV_FIRST_TIMER = 20133,
- BG_RV_WORLD_STATE = 0xE1A,
+ BG_RV_WORLD_STATE_A = 0xe10,
+ BG_RV_WORLD_STATE_H = 0xe11,
+ BG_RV_WORLD_STATE = 0xe1a,
};
class BattleGroundRVScore : public BattleGroundScore
diff --git a/src/game/BattleGroundWS.cpp b/src/game/BattleGroundWS.cpp
index 63dd2f48a0b..0071e2c615c 100644
--- a/src/game/BattleGroundWS.cpp
+++ b/src/game/BattleGroundWS.cpp
@@ -67,9 +67,32 @@ BattleGroundWS::~BattleGroundWS()
void BattleGroundWS::Update(uint32 diff)
{
BattleGround::Update(diff);
-
+
if (GetStatus() == STATUS_IN_PROGRESS)
{
+ if( GetStartTime() >= 25*MINUTE*1000 ) // Òàéìåð òèêàòü íà÷èíàåò ïîñëå 25 ìèíóò
+ {
+ if( GetTeamScore(ALLIANCE) == 0 )
+ {
+ if ( GetTeamScore(HORDE) == 0 ) // No one scored - result is tie
+ EndBattleGround(NULL);
+
+ else // Horde has more points and thus wins
+ EndBattleGround(HORDE);
+ }
+
+ else if( GetTeamScore(HORDE) == 0 )
+ EndBattleGround(ALLIANCE); // Alliance has >0, Horde has 0, alliance wins
+
+ else if( GetTeamScore(HORDE) == GetTeamScore(ALLIANCE) ) // Team score equal, winner is team that scored the first flag
+ EndBattleGround(m_FirstFlagCaptureTeam);
+
+ else if( GetTeamScore(HORDE) > GetTeamScore(ALLIANCE) ) // Last but not least, check who has the higher score
+ EndBattleGround(HORDE);
+ else
+ EndBattleGround(ALLIANCE);
+ }
+
if (m_FlagState[BG_TEAM_ALLIANCE] == BG_WS_FLAG_STATE_WAIT_RESPAWN)
{
m_FlagsTimer[BG_TEAM_ALLIANCE] -= diff;
@@ -225,7 +248,7 @@ void BattleGroundWS::RespawnFlagAfterDrop(uint32 team)
PlaySoundToAll(BG_WS_SOUND_FLAGS_RESPAWNED);
- GameObject *obj = HashMapHolder<GameObject>::Find(GetDroppedFlagGUID(team));
+ GameObject *obj = GetBgMap()->GetGameObject(GetDroppedFlagGUID(team));
if (obj)
obj->Delete();
else
@@ -294,6 +317,9 @@ void BattleGroundWS::EventPlayerCapturedFlag(Player *Source)
UpdateTeamScore(Source->GetTeam());
// only flag capture should be updated
UpdatePlayerScore(Source, SCORE_FLAG_CAPTURES, 1); // +1 flag captures
+
+ if(!m_FirstFlagCaptureTeam)
+ SetFirstFlagCapture(Source->GetTeam());
if (GetTeamScore(ALLIANCE) == BG_WS_MAX_TEAM_SCORE)
winner = ALLIANCE;
diff --git a/src/game/BattleGroundWS.h b/src/game/BattleGroundWS.h
index 16631afecdc..1a98f0623c5 100644
--- a/src/game/BattleGroundWS.h
+++ b/src/game/BattleGroundWS.h
@@ -189,6 +189,7 @@ class BattleGroundWS : public BattleGround
virtual WorldSafeLocsEntry const* GetClosestGraveYard(Player* player);
void UpdateFlagState(uint32 team, uint32 value);
+ void SetFirstFlagCapture(uint32 team) { m_FirstFlagCaptureTeam = team; }
void UpdateTeamScore(uint32 team);
void UpdatePlayerScore(Player *Source, uint32 type, uint32 value);
void SetDroppedFlagGUID(uint64 guid, uint32 TeamID) { m_DroppedFlagGUID[GetTeamIndexByTeamId(TeamID)] = guid;}
@@ -206,7 +207,8 @@ class BattleGroundWS : public BattleGround
uint8 m_FlagState[2]; // for checking flag state
int32 m_FlagsTimer[2];
int32 m_FlagsDropTimer[2];
-
+ uint32 m_FirstFlagCaptureTeam; // Winner is based on this if score is equal
+
uint32 m_ReputationCapture;
uint32 m_HonorWinKills;
uint32 m_HonorEndKills;
diff --git a/src/game/CMakeLists.txt b/src/game/CMakeLists.txt
index 0131437b732..a4d656cf7f6 100644
--- a/src/game/CMakeLists.txt
+++ b/src/game/CMakeLists.txt
@@ -23,10 +23,12 @@ SET(game_STAT_SRCS
BattleGround.cpp
BattleGroundAA.cpp
BattleGroundAB.cpp
+ BattleGroundABG.cpp
BattleGroundAV.cpp
BattleGroundBE.cpp
BattleGroundDS.cpp
BattleGroundEY.cpp
+ BattleGroundIC.cpp
BattleGroundNA.cpp
BattleGroundRL.cpp
BattleGroundRV.cpp
@@ -35,10 +37,12 @@ SET(game_STAT_SRCS
BattleGround.h
BattleGroundAA.h
BattleGroundAB.h
+ BattleGroundABG.h
BattleGroundAV.h
BattleGroundBE.h
BattleGroundDS.h
BattleGroundEY.h
+ BattleGroundIC.h
BattleGroundNA.h
BattleGroundRL.h
BattleGroundRV.h
diff --git a/src/game/CalendarHandler.cpp b/src/game/CalendarHandler.cpp
index 8d7bd63a9a9..5860f4acaec 100644
--- a/src/game/CalendarHandler.cpp
+++ b/src/game/CalendarHandler.cpp
@@ -45,7 +45,7 @@ void WorldSession::HandleCalendarGetCalendar(WorldPacket &recv_data)
size_t p_counter = data.wpos();
data << uint32(counter); // instance save count
- for (int i = 0; i < TOTAL_DIFFICULTIES; ++i)
+ for (int i = 0; i < MAX_DIFFICULTY; ++i)
{
for (Player::BoundInstancesMap::const_iterator itr = _player->m_boundInstances[i].begin(); itr != _player->m_boundInstances[i].end(); ++itr)
{
diff --git a/src/game/Channel.cpp b/src/game/Channel.cpp
index 768b8865eb0..fe6af918a79 100644
--- a/src/game/Channel.cpp
+++ b/src/game/Channel.cpp
@@ -298,6 +298,7 @@ void Channel::KickOrBan(uint64 good, const char *badname, bool ban)
banned.insert(bad->GetGUID());
MakePlayerBanned(&data, bad->GetGUID(), good);
_UpdateBanListInDB();
+
}
else
MakePlayerKicked(&data, bad->GetGUID(), good);
@@ -351,6 +352,7 @@ void Channel::UnBan(uint64 good, const char *badname)
WorldPacket data;
MakePlayerUnbanned(&data, bad->GetGUID(), good);
SendToAll(&data);
+ //save banlist
_UpdateBanListInDB();
}
}
@@ -592,6 +594,7 @@ void Channel::Announce(uint64 p)
SendToAll(&data);
if (m_IsSaved && _UpdateIntInDB("m_announce", m_announce ? 1 : 0))
sLog.outDebug("Channel(%s) announce saved", m_name.c_str());
+
}
}
@@ -624,8 +627,8 @@ void Channel::Moderate(uint64 p)
else
MakeModerationOff(&data, p);
SendToAll(&data);
- if (m_IsSaved && _UpdateIntInDB("m_moderate", m_moderate ? 1 : 0))
- sLog.outDebug("Channel(%s) moderate saved", m_name.c_str());
+ if (m_IsSaved && _UpdateIntInDB("m_announce", m_announce ? 1 : 0))
+ sLog.outDebug("Channel(%s) announce saved", m_name.c_str());
}
}
@@ -754,15 +757,8 @@ void Channel::SetOwner(uint64 guid, bool exclaim)
MakeOwnerChanged(&data, m_ownerGUID);
SendToAll(&data);
}
- /*if(m_IsSaved)
- {
- std::ostringstream ss;
- ss << "UPDATE channels SET m_ownerGUID = '" << guid << "' WHERE m_name = '"<<m_name.c_str()<<"' AND m_team = '"<<m_Team<<"'";
- if(CharacterDatabase.PExecute( ss.str( ).c_str( ) ))
- {
- sLog.outDebug("Channel(%s) owner saved", m_name.c_str());
- }
- }*/
+ if (m_IsSaved && _UpdateIntInDB("m_moderate", m_moderate ? 1 : 0))
+ sLog.outDebug("Channel(%s) moderate saved", m_name.c_str());
}
}
diff --git a/src/game/CharacterHandler.cpp b/src/game/CharacterHandler.cpp
index ca2561f4771..3ef302c2f79 100644
--- a/src/game/CharacterHandler.cpp
+++ b/src/game/CharacterHandler.cpp
@@ -84,7 +84,7 @@ bool LoginQueryHolder::Initialize()
res &= SetPQuery(PLAYER_LOGIN_QUERY_LOADDECLINEDNAMES, "SELECT genitive, dative, accusative, instrumental, prepositional FROM character_declinedname WHERE guid = '%u'",GUID_LOPART(m_guid));
// in other case still be dummy query
res &= SetPQuery(PLAYER_LOGIN_QUERY_LOADGUILD, "SELECT guildid,rank FROM guild_member WHERE guid = '%u'", GUID_LOPART(m_guid));
- res &= SetPQuery(PLAYER_LOGIN_QUERY_LOADARENAINFO, "SELECT arenateamid, played_week, played_season, personal_rating FROM arena_team_member WHERE guid='%u'", GUID_LOPART(m_guid));
+ res &= SetPQuery(PLAYER_LOGIN_QUERY_LOADARENAINFO, "SELECT arenateamid, played_week, played_season, wons_season, personal_rating FROM arena_team_member WHERE guid='%u'", GUID_LOPART(m_guid));
res &= SetPQuery(PLAYER_LOGIN_QUERY_LOADACHIEVEMENTS, "SELECT achievement, date FROM character_achievement WHERE guid = '%u'", GUID_LOPART(m_guid));
res &= SetPQuery(PLAYER_LOGIN_QUERY_LOADCRITERIAPROGRESS,"SELECT criteria, counter, date FROM character_achievement_progress WHERE guid = '%u'", GUID_LOPART(m_guid));
res &= SetPQuery(PLAYER_LOGIN_QUERY_LOADEQUIPMENTSETS, "SELECT setguid, setindex, name, iconname, item0, item1, item2, item3, item4, item5, item6, item7, item8, item9, item10, item11, item12, item13, item14, item15, item16, item17, item18 FROM character_equipmentsets WHERE guid = '%u' ORDER BY setindex", GUID_LOPART(m_guid));
@@ -102,6 +102,7 @@ bool LoginQueryHolder::Initialize()
// instead pass an account id to this handler
class CharacterHandler
{
+
public:
void HandleCharEnumCallback(QueryResult * result, uint32 account)
{
@@ -229,19 +230,19 @@ void WorldSession::HandleCharCreateOpcode( WorldPacket & recv_data )
}
// prevent character creating Expansion race without Expansion account
- if (raceEntry->addon > Expansion())
+ if (raceEntry->expansion > Expansion())
{
data << (uint8)CHAR_CREATE_EXPANSION;
- sLog.outError("Expansion %u account:[%d] tried to Create character with expansion %u race (%u)",Expansion(),GetAccountId(),raceEntry->addon,race_);
+ sLog.outError("Expansion %u account:[%d] tried to Create character with expansion %u race (%u)",Expansion(),GetAccountId(),raceEntry->expansion,race_);
SendPacket( &data );
return;
}
// prevent character creating Expansion class without Expansion account
- if (classEntry->addon > Expansion())
+ if (classEntry->expansion > Expansion())
{
data << (uint8)CHAR_CREATE_EXPANSION_CLASS;
- sLog.outError("Expansion %u account:[%d] tried to Create character with expansion %u class (%u)",Expansion(),GetAccountId(),classEntry->addon,class_);
+ sLog.outError("Expansion %u account:[%d] tried to Create character with expansion %u class (%u)",Expansion(),GetAccountId(),classEntry->expansion,class_);
SendPacket( &data );
return;
}
@@ -437,13 +438,8 @@ void WorldSession::HandleCharCreateOpcode( WorldPacket & recv_data )
// extract other data required for player creating
uint8 gender, skin, face, hairStyle, hairColor, facialHair, outfitId;
- recv_data >> gender;
- recv_data >> skin;
- recv_data >> face;
- recv_data >> hairStyle;
- recv_data >> hairColor;
- recv_data >> facialHair;
- recv_data >> outfitId;
+ recv_data >> gender >> skin >> face;
+ recv_data >> hairStyle >> hairColor >> facialHair >> outfitId;
if(recv_data.rpos() < recv_data.wpos())
{
@@ -604,7 +600,7 @@ void WorldSession::HandlePlayerLogin(LoginQueryHolder * holder)
// load player specific part before send times
LoadAccountData(holder->GetResult(PLAYER_LOGIN_QUERY_LOADACCOUNTDATA),PER_CHARACTER_CACHE_MASK);
- SendAccountDataTimes();
+ SendAccountDataTimes(PER_CHARACTER_CACHE_MASK);
data.Initialize(SMSG_FEATURE_SYSTEM_STATUS, 2); // added in 2.2.0
data << uint8(2); // unknown value
@@ -649,11 +645,6 @@ void WorldSession::HandlePlayerLogin(LoginQueryHolder * holder)
DEBUG_LOG( "WORLD: Sent server info" );
}
- data.Initialize(SMSG_LEARNED_DANCE_MOVES, 4+4);
- data << uint32(0);
- data << uint32(0);
- SendPacket(&data);
-
//QueryResult *result = CharacterDatabase.PQuery("SELECT guildid,rank FROM guild_member WHERE guid = '%u'",pCurrChar->GetGUIDLow());
QueryResult *resultGuild = holder->GetResult(PLAYER_LOGIN_QUERY_LOADGUILD);
@@ -701,6 +692,11 @@ void WorldSession::HandlePlayerLogin(LoginQueryHolder * holder)
}
}
+ data.Initialize(SMSG_LEARNED_DANCE_MOVES, 4+4);
+ data << uint32(0);
+ data << uint32(0);
+ SendPacket(&data);
+
if(!pCurrChar->isAlive())
pCurrChar->SendCorpseReclaimDelay(true);
@@ -1102,8 +1098,8 @@ void WorldSession::HandleAlterAppearance( WorldPacket & recv_data )
{
sLog.outDebug("CMSG_ALTER_APPEARANCE");
- uint32 Hair, Color, FacialHair;
- recv_data >> Hair >> Color >> FacialHair;
+ uint32 Hair, Color, FacialHair, SkinColor;
+ recv_data >> Hair >> Color >> FacialHair >> SkinColor;
BarberShopStyleEntry const* bs_hair = sBarberShopStyleStore.LookupEntry(Hair);
@@ -1115,7 +1111,12 @@ void WorldSession::HandleAlterAppearance( WorldPacket & recv_data )
if(!bs_facialHair || bs_facialHair->type != 2 || bs_facialHair->race != _player->getRace() || bs_facialHair->gender != _player->getGender())
return;
- uint32 Cost = _player->GetBarberShopCost(bs_hair->hair_id, Color, bs_facialHair->hair_id);
+ BarberShopStyleEntry const* bs_skinColor = sBarberShopStyleStore.LookupEntry(SkinColor);
+
+ if( bs_skinColor && (bs_skinColor->type != 3 || bs_skinColor->race != _player->getRace() || bs_skinColor->gender != _player->getGender()))
+ return;
+
+ uint32 Cost = _player->GetBarberShopCost(bs_hair->hair_id, Color, bs_facialHair->hair_id, bs_skinColor);
// 0 - ok
// 1,3 - not enough money
@@ -1140,6 +1141,8 @@ void WorldSession::HandleAlterAppearance( WorldPacket & recv_data )
_player->SetByteValue(PLAYER_BYTES, 2, uint8(bs_hair->hair_id));
_player->SetByteValue(PLAYER_BYTES, 3, uint8(Color));
_player->SetByteValue(PLAYER_BYTES_2, 0, uint8(bs_facialHair->hair_id));
+ if (bs_skinColor)
+ _player->SetByteValue(PLAYER_BYTES, 0, uint8(bs_skinColor->hair_id));
_player->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_VISIT_BARBER_SHOP, 1);
diff --git a/src/game/Chat.cpp b/src/game/Chat.cpp
index 80f75ccffa6..a96086bdba0 100644
--- a/src/game/Chat.cpp
+++ b/src/game/Chat.cpp
@@ -165,11 +165,12 @@ ChatCommand * ChatHandler::getCommandTable()
{ "getitemstate", SEC_ADMINISTRATOR, false, &ChatHandler::HandleDebugGetItemStateCommand, "", NULL },
{ "lootrecipient", SEC_GAMEMASTER, false, &ChatHandler::HandleDebugGetLootRecipientCommand, "", NULL },
{ "getvalue", SEC_ADMINISTRATOR, false, &ChatHandler::HandleDebugGetValueCommand, "", NULL },
+ { "getitemvalue", SEC_ADMINISTRATOR, false, &ChatHandler::HandleDebugGetItemValueCommand, "", NULL },
{ "Mod32Value", SEC_ADMINISTRATOR, false, &ChatHandler::HandleDebugMod32ValueCommand, "", NULL },
{ "play", SEC_MODERATOR, false, NULL, "", debugPlayCommandTable },
{ "send", SEC_ADMINISTRATOR, false, NULL, "", debugSendCommandTable },
{ "setaurastate", SEC_ADMINISTRATOR, false, &ChatHandler::HandleDebugSetAuraStateCommand, "", NULL },
- { "setitemflag", SEC_ADMINISTRATOR, false, &ChatHandler::HandleDebugSetItemFlagCommand, "", NULL },
+ { "setitemvalue", SEC_ADMINISTRATOR, false, &ChatHandler::HandleDebugSetItemValueCommand, "", NULL },
{ "setvalue", SEC_ADMINISTRATOR, false, &ChatHandler::HandleDebugSetValueCommand, "", NULL },
{ "spawnvehicle", SEC_ADMINISTRATOR, false, &ChatHandler::HandleDebugSpawnVehicle, "", NULL },
{ "setvid", SEC_ADMINISTRATOR, false, &ChatHandler::HandleDebugSetVehicleId, "", NULL },
@@ -1164,6 +1165,8 @@ valid examples:
Quest const* linkedQuest;
SpellEntry const *linkedSpell;
AchievementEntry const* linkedAchievement;
+ ItemRandomPropertiesEntry const* itemProperty;
+ ItemRandomSuffixEntry const* itemSuffix;
while(!reader.eof())
{
@@ -1173,6 +1176,8 @@ valid examples:
linkedQuest = NULL;
linkedSpell = NULL;
linkedAchievement = NULL;
+ itemProperty = NULL;
+ itemSuffix = NULL;
reader.ignore(255, '|');
}
@@ -1289,9 +1294,47 @@ valid examples:
return false;
}
- char c = reader.peek();
+ // the itementry is followed by several integers which describe an instance of this item
+
+ // position relative after itemEntry
+ const uint8 randomPropertyPosition = 6;
- // ignore enchants etc.
+ int32 propertyId = 0;
+ bool negativeNumber = false;
+ char c;
+ for(uint8 i=0; i<randomPropertyPosition; ++i)
+ {
+ propertyId = 0;
+ negativeNumber = false;
+ while((c = reader.get())!=':')
+ {
+ if(c >='0' && c<='9')
+ {
+ propertyId*=10;
+ propertyId += c-'0';
+ } else if(c == '-')
+ negativeNumber = true;
+ else
+ return false;
+ }
+ }
+ if (negativeNumber)
+ propertyId *= -1;
+
+ if (propertyId > 0)
+ {
+ itemProperty = sItemRandomPropertiesStore.LookupEntry(propertyId);
+ if (!itemProperty)
+ return false;
+ }
+ else if(propertyId < 0)
+ {
+ itemSuffix = sItemRandomSuffixStore.LookupEntry(-propertyId);
+ if (!itemSuffix)
+ return false;
+ }
+
+ // ignore other integers
while((c >='0' && c <='9') || c==':')
{
reader.ignore(1);
@@ -1560,22 +1603,34 @@ valid examples:
}
else if (linkedItem)
{
- if (strcmp(linkedItem->Name1, buffer) != 0)
+ char* const* suffix = itemSuffix?itemSuffix->nameSuffix:(itemProperty?itemProperty->nameSuffix:NULL);
+
+ std::string expectedName = std::string(linkedItem->Name1);
+ if (suffix)
{
- ItemLocale const *il = objmgr.GetItemLocale(linkedItem->ItemId);
+ expectedName += " ";
+ expectedName += suffix[LOCALE_enUS];
+ }
- if (!il)
- {
-#ifdef MANGOS_DEBUG
- sLog.outBasic("ChatHandler::isValidChatMessage linked item name doesn't is wrong and there is no localization");
-#endif
- return false;
- }
+ if (expectedName != buffer)
+ {
+ ItemLocale const *il = objmgr.GetItemLocale(linkedItem->ItemId);
bool foundName = false;
- for (uint8 i=0; i<il->Name.size(); ++i)
+ for(uint8 i=LOCALE_koKR; i<MAX_LOCALE; ++i)
{
- if (il->Name[i] == buffer)
+ int8 dbIndex = objmgr.GetIndexForLocale(LocaleConstant(i));
+ if (dbIndex == -1 || il == NULL || dbIndex >= il->Name.size())
+ // using strange database/client combinations can lead to this case
+ expectedName = linkedItem->Name1;
+ else
+ expectedName = il->Name[dbIndex];
+ if (suffix)
+ {
+ expectedName += " ";
+ expectedName += suffix[i];
+ }
+ if ( expectedName == buffer)
{
foundName = true;
break;
diff --git a/src/game/Chat.h b/src/game/Chat.h
index d0d9a6112fc..c799252f4b0 100644
--- a/src/game/Chat.h
+++ b/src/game/Chat.h
@@ -144,9 +144,10 @@ class TRINITY_DLL_SPEC ChatHandler
bool HandleDebugGetItemStateCommand(const char * args);
bool HandleDebugGetLootRecipientCommand(const char * args);
bool HandleDebugGetValueCommand(const char* args);
+ bool HandleDebugGetItemValueCommand(const char* args);
bool HandleDebugMod32ValueCommand(const char* args);
bool HandleDebugSetAuraStateCommand(const char * args);
- bool HandleDebugSetItemFlagCommand(const char * args);
+ bool HandleDebugSetItemValueCommand(const char * args);
bool HandleDebugItemExpireCommand(const char * args);
bool HandleDebugSetVehicleId(const char * args);
bool HandleDebugEnterVehicle(const char * args);
diff --git a/src/game/Creature.cpp b/src/game/Creature.cpp
index 03068041f23..72a4449d5a5 100644
--- a/src/game/Creature.cpp
+++ b/src/game/Creature.cpp
@@ -261,19 +261,24 @@ bool Creature::InitEntry(uint32 Entry, uint32 team, const CreatureData *data )
return false;
}
- // get heroic mode entry
+ // get difficulty 1 mode entry
uint32 actualEntry = Entry;
CreatureInfo const *cinfo = normalInfo;
- if(normalInfo->HeroicEntry)
+ // TODO correctly implement spawnmodes for non-bg maps
+ for (uint32 diff = 0; diff < MAX_DIFFICULTY - 1; ++diff)
{
- //we already have valid Map pointer for current creature!
- if(GetMap()->IsHeroic())
+ if (normalInfo->DifficultyEntry[diff])
{
- cinfo = objmgr.GetCreatureTemplate(normalInfo->HeroicEntry);
- if(!cinfo)
+ // we already have valid Map pointer for current creature!
+ if (GetMap()->GetSpawnMode() > diff)
{
- sLog.outErrorDb("Creature::UpdateEntry creature heroic entry %u does not exist.", actualEntry);
- return false;
+ cinfo = objmgr.GetCreatureTemplate(normalInfo->DifficultyEntry[diff]);
+ if (!cinfo)
+ {
+ // maybe check such things already at startup
+ sLog.outErrorDb("Creature::UpdateEntry creature difficulty %u entry %u does not exist.", diff + 1, actualEntry);
+ return false;
+ }
}
}
}
@@ -1565,7 +1570,7 @@ bool Creature::LoadFromDB(uint32 guid, Map *map)
m_deathState = DEAD;
if(canFly())
{
- float tz = GetMap()->GetHeight(data->posX,data->posY,data->posZ,false);
+ float tz = map->GetHeight(data->posX,data->posY,data->posZ,false);
if(data->posZ - tz > 0.1)
Relocate(data->posX,data->posY,tz);
}
@@ -1899,7 +1904,7 @@ void Creature::Respawn(bool force)
uint16 poolid = poolhandler.IsPartOfAPool(GetGUIDLow(), GetTypeId());
if (poolid)
- poolhandler.UpdatePool(poolid, GetGUIDLow(), GetTypeId());
+ poolhandler.UpdatePool(poolid, GetGUIDLow(), TYPEID_UNIT);
}
SetToNotify();
@@ -2265,7 +2270,7 @@ CreatureDataAddon const* Creature::GetCreatureAddon() const
return addon;
}
- // dependent from heroic mode entry
+ // dependent from difficulty mode entry
return ObjectMgr::GetCreatureTemplateAddon(GetCreatureInfo()->Entry);
}
@@ -2671,4 +2676,3 @@ time_t Creature::GetLinkedCreatureRespawnTime() const
return 0;
}
-
diff --git a/src/game/Creature.h b/src/game/Creature.h
index ab9915c0bda..d1c08bb13e2 100644
--- a/src/game/Creature.h
+++ b/src/game/Creature.h
@@ -167,7 +167,7 @@ enum CreatureFlagsExtra
struct CreatureInfo
{
uint32 Entry;
- uint32 HeroicEntry;
+ uint32 DifficultyEntry[MAX_DIFFICULTY - 1];
uint32 KillCredit[MAX_KILL_CREDIT];
uint32 Modelid1;
uint32 Modelid2;
@@ -783,7 +783,7 @@ class TRINITY_DLL_SPEC Creature : public Unit
bool DisableReputationGain;
- CreatureInfo const* m_creatureInfo; // in heroic mode can different from ObjMgr::GetCreatureTemplate(GetEntry())
+ CreatureInfo const* m_creatureInfo; // in difficulty mode > 0 can different from ObjMgr::GetCreatureTemplate(GetEntry())
CreatureData const* m_creatureData;
uint16 m_LootMode; // bitmask, default DEFAULT_LOOT_MODE, determines what loot will be lootable
@@ -814,4 +814,3 @@ class AssistDelayEvent : public BasicEvent
};
#endif
-
diff --git a/src/game/CreatureEventAI.cpp b/src/game/CreatureEventAI.cpp
index f50f7e4128b..07de3fa0efc 100644
--- a/src/game/CreatureEventAI.cpp
+++ b/src/game/CreatureEventAI.cpp
@@ -71,10 +71,9 @@ CreatureEventAI::CreatureEventAI(Creature *c ) : CreatureAI(c)
if ((*i).event_flags & EFLAG_DEBUG_ONLY)
continue;
#endif
- if(((*i).event_flags & (EFLAG_HEROIC | EFLAG_NORMAL)) && m_creature->GetMap()->IsDungeon() )
+ if(m_creature->GetMap()->IsDungeon())
{
- if( (m_creature->GetMap()->IsHeroic() && (*i).event_flags & EFLAG_HEROIC) ||
- (!m_creature->GetMap()->IsHeroic() && (*i).event_flags & EFLAG_NORMAL))
+ if ((1 << (m_creature->GetMap()->GetSpawnMode()+1)) & (*i).event_flags)
{
//event flagged for instance mode
CreatureEventAIList.push_back(CreatureEventAIHolder(*i));
diff --git a/src/game/CreatureEventAI.h b/src/game/CreatureEventAI.h
index 55ae1e20bf3..e51b74a9602 100644
--- a/src/game/CreatureEventAI.h
+++ b/src/game/CreatureEventAI.h
@@ -160,13 +160,15 @@ enum CastFlags
enum EventFlags
{
EFLAG_REPEATABLE = 0x01, //Event repeats
- EFLAG_NORMAL = 0x02, //Event only occurs in Normal instance difficulty
- EFLAG_HEROIC = 0x04, //Event only occurs in Heroic instance difficulty
- EFLAG_RESERVED_3 = 0x08,
- EFLAG_RESERVED_4 = 0x10,
+ EFLAG_DIFFICULTY_0 = 0x02, //Event only occurs in instance difficulty 0
+ EFLAG_DIFFICULTY_1 = 0x04, //Event only occurs in instance difficulty 1
+ EFLAG_DIFFICULTY_2 = 0x08, //Event only occurs in instance difficulty 2
+ EFLAG_DIFFICULTY_3 = 0x10, //Event only occurs in instance difficulty 3
EFLAG_RESERVED_5 = 0x20,
EFLAG_RESERVED_6 = 0x40,
EFLAG_DEBUG_ONLY = 0x80, //Event only occurs in debug build
+
+ EFLAG_DIFFICULTY_ALL = (EFLAG_DIFFICULTY_0|EFLAG_DIFFICULTY_1|EFLAG_DIFFICULTY_2|EFLAG_DIFFICULTY_3)
};
enum SpawnedEventMode
diff --git a/src/game/CreatureEventAIMgr.cpp b/src/game/CreatureEventAIMgr.cpp
index 462a284a17d..2d4c92ad7bf 100644
--- a/src/game/CreatureEventAIMgr.cpp
+++ b/src/game/CreatureEventAIMgr.cpp
@@ -640,14 +640,14 @@ void CreatureEventAIMgr::LoadCreatureEventAI_Scripts()
sLog.outErrorDb("CreatureEventAI: Event %u Action %u uses incorrect Target type", i, j+1);
break;
case ACTION_T_SET_INST_DATA:
- if (!(temp.event_flags & EFLAG_NORMAL) && !(temp.event_flags & EFLAG_HEROIC))
- sLog.outErrorDb("CreatureEventAI: Event %u Action %u. Cannot set instance data without event flags (normal/heroic).", i, j+1);
+ if (!(temp.event_flags & EFLAG_DIFFICULTY_ALL))
+ sLog.outErrorDb("CreatureEventAI: Event %u Action %u. Cannot set instance data without difficulty event flags.", i, j+1);
if (action.set_inst_data.value > 4/*SPECIAL*/)
sLog.outErrorDb("CreatureEventAI: Event %u Action %u attempts to set instance data above encounter state 4. Custom case?", i, j+1);
break;
case ACTION_T_SET_INST_DATA64:
- if (!(temp.event_flags & EFLAG_NORMAL) && !(temp.event_flags & EFLAG_HEROIC))
- sLog.outErrorDb("CreatureEventAI: Event %u Action %u. Cannot set instance data without event flags (normal/heroic).", i, j+1);
+ if (!(temp.event_flags & EFLAG_DIFFICULTY_ALL))
+ sLog.outErrorDb("CreatureEventAI: Event %u Action %u. Cannot set instance data without difficulty event flags.", i, j+1);
if (action.set_inst_data64.target >= TARGET_T_END)
sLog.outErrorDb("CreatureEventAI: Event %u Action %u uses incorrect Target type", i, j+1);
break;
diff --git a/src/game/DBCEnums.h b/src/game/DBCEnums.h
index a0e030bf7cb..97cc6f4798c 100644
--- a/src/game/DBCEnums.h
+++ b/src/game/DBCEnums.h
@@ -232,6 +232,42 @@ enum AreaFlags
AREA_FLAG_OUTDOOR_PVP2 = 0x08000000 // Wintergrasp and it's subzones
};
+enum Difficulty
+{
+ REGULAR_DIFFICULTY = 0,
+
+ DUNGEON_DIFFICULTY_NORMAL = 0,
+ DUNGEON_DIFFICULTY_HEROIC = 1,
+
+ RAID_DIFFICULTY_10MAN_NORMAL = 0,
+ RAID_DIFFICULTY_25MAN_NORMAL = 1,
+ RAID_DIFFICULTY_10MAN_HEROIC = 2,
+ RAID_DIFFICULTY_25MAN_HEROIC = 3,
+};
+
+#define MAX_DUNGEON_DIFFICULTY 2
+#define MAX_RAID_DIFFICULTY 4
+#define MAX_DIFFICULTY 4
+
+enum SpawnMask
+{
+ SPAWNMASK_CONTINENT = (1 << REGULAR_DIFFICULTY),// any any maps without spawn modes
+
+ SPAWNMASK_DUNGEON_NORMAL = (1 << DUNGEON_DIFFICULTY_NORMAL),
+ SPAWNMASK_DUNGEON_HEROIC = (1 << DUNGEON_DIFFICULTY_HEROIC),
+ SPAWNMASK_DUNGEON_ALL = (SPAWNMASK_DUNGEON_NORMAL | SPAWNMASK_DUNGEON_HEROIC),
+
+ SPAWNMASK_RAID_10MAN_NORMAL = (1 << RAID_DIFFICULTY_10MAN_NORMAL),
+ SPAWNMASK_RAID_25MAN_NORMAL = (1 << RAID_DIFFICULTY_25MAN_NORMAL),
+ SPAWNMASK_RAID_NORMAL_ALL = (SPAWNMASK_RAID_10MAN_NORMAL | SPAWNMASK_RAID_25MAN_NORMAL),
+
+ SPAWNMASK_RAID_10MAN_HEROIC = (1 << RAID_DIFFICULTY_10MAN_HEROIC),
+ SPAWNMASK_RAID_25MAN_HEROIC = (1 << RAID_DIFFICULTY_25MAN_HEROIC),
+ SPAWNMASK_RAID_HEROIC_ALL = (SPAWNMASK_RAID_10MAN_HEROIC | SPAWNMASK_RAID_25MAN_HEROIC),
+
+ SPAWNMASK_RAID_ALL = (SPAWNMASK_RAID_NORMAL_ALL | SPAWNMASK_RAID_HEROIC_ALL),
+};
+
enum FactionTemplateFlags
{
FACTION_TEMPLATE_FLAG_CONTESTED_GUARD = 0x00001000, // faction will attack players that were involved in PvP combats
@@ -333,4 +369,3 @@ enum SummonPropFlags
};
#endif
-
diff --git a/src/game/DBCStores.cpp b/src/game/DBCStores.cpp
index ba89cb69215..c9832a830eb 100644
--- a/src/game/DBCStores.cpp
+++ b/src/game/DBCStores.cpp
@@ -100,6 +100,11 @@ DBCStorage <LockEntry> sLockStore(LockEntryfmt);
DBCStorage <MailTemplateEntry> sMailTemplateStore(MailTemplateEntryfmt);
DBCStorage <MapEntry> sMapStore(MapEntryfmt);
+
+// DBC used only for initialization sMapDifficultyMap at startup.
+DBCStorage <MapDifficultyEntry> sMapDifficultyStore(MapDifficultyEntryfmt); // only for loading
+MapDifficultyMap sMapDifficultyMap;
+
DBCStorage <MovieEntry> sMovieStore(MovieEntryfmt);
DBCStorage <QuestSortEntry> sQuestSortStore(QuestSortEntryfmt);
@@ -133,7 +138,7 @@ TalentSpellPosMap sTalentSpellPosMap;
DBCStorage <TalentTabEntry> sTalentTabStore(TalentTabEntryfmt);
// store absolute bit position for first rank for talent inspect
-static uint32 sTalentTabPages[12/*MAX_CLASSES*/][3];
+static uint32 sTalentTabPages[MAX_CLASSES][3];
DBCStorage <TaxiNodesEntry> sTaxiNodesStore(TaxiNodesEntryfmt);
TaxiMask sTaxiNodesMask;
@@ -143,10 +148,10 @@ TaxiMask sOldContinentsNodesMask;
TaxiPathSetBySource sTaxiPathSetBySource;
DBCStorage <TaxiPathEntry> sTaxiPathStore(TaxiPathEntryfmt);
-// DBC used only for initialization sTaxiPathSetBySource at startup.
+// DBC used only for initialization sTaxiPathNodeStore at startup.
TaxiPathNodesByPath sTaxiPathNodesByPath;
-
static DBCStorage <TaxiPathNodeEntry> sTaxiPathNodeStore(TaxiPathNodeEntryfmt);
+
DBCStorage <TotemCategoryEntry> sTotemCategoryStore(TotemCategoryEntryfmt);
DBCStorage <VehicleEntry> sVehicleStore(VehicleEntryfmt);
DBCStorage <VehicleSeatEntry> sVehicleSeatStore(VehicleSeatEntryfmt);
@@ -210,7 +215,7 @@ void LoadDBCStores(const std::string& dataPath)
{
std::string dbcPath = dataPath+"dbc/";
- const uint32 DBCFilesCount = 79;
+ const uint32 DBCFilesCount = 80;
barGoLink bar( DBCFilesCount );
@@ -243,7 +248,6 @@ void LoadDBCStores(const std::string& dataPath)
LoadDBC(availableDbcLocales,bar,bad_dbc_files,sBattlemasterListStore, dbcPath,"BattlemasterList.dbc");
LoadDBC(availableDbcLocales,bar,bad_dbc_files,sBarberShopStyleStore, dbcPath,"BarberShopStyle.dbc");
LoadDBC(availableDbcLocales,bar,bad_dbc_files,sCharStartOutfitStore, dbcPath,"CharStartOutfit.dbc");
-
LoadDBC(availableDbcLocales,bar,bad_dbc_files,sCharTitlesStore, dbcPath,"CharTitles.dbc");
LoadDBC(availableDbcLocales,bar,bad_dbc_files,sChatChannelsStore, dbcPath,"ChatChannels.dbc");
LoadDBC(availableDbcLocales,bar,bad_dbc_files,sChrClassesStore, dbcPath,"ChrClasses.dbc");
@@ -314,6 +318,14 @@ void LoadDBCStores(const std::string& dataPath)
LoadDBC(availableDbcLocales,bar,bad_dbc_files,sLockStore, dbcPath,"Lock.dbc");
LoadDBC(availableDbcLocales,bar,bad_dbc_files,sMailTemplateStore, dbcPath,"MailTemplate.dbc");
LoadDBC(availableDbcLocales,bar,bad_dbc_files,sMapStore, dbcPath,"Map.dbc");
+
+ LoadDBC(availableDbcLocales,bar,bad_dbc_files,sMapDifficultyStore, dbcPath,"MapDifficulty.dbc");
+ // fill data
+ for(uint32 i = 1; i < sMapDifficultyStore.GetNumRows(); ++i)
+ if(MapDifficultyEntry const* entry = sMapDifficultyStore.LookupEntry(i))
+ sMapDifficultyMap[MAKE_PAIR32(entry->MapId,entry->Difficulty)] = MapDifficulty(entry->resetTime,entry->maxPlayers);
+ sMapDifficultyStore.Clear();
+
LoadDBC(availableDbcLocales,bar,bad_dbc_files,sMovieStore, dbcPath,"Movie.dbc");
LoadDBC(availableDbcLocales,bar,bad_dbc_files,sQuestSortStore, dbcPath,"QuestSort.dbc");
LoadDBC(availableDbcLocales,bar,bad_dbc_files,sRandomPropertiesPointsStore, dbcPath,"RandPropPoints.dbc");
@@ -322,7 +334,7 @@ void LoadDBCStores(const std::string& dataPath)
LoadDBC(availableDbcLocales,bar,bad_dbc_files,sSkillLineStore, dbcPath,"SkillLine.dbc");
LoadDBC(availableDbcLocales,bar,bad_dbc_files,sSkillLineAbilityStore, dbcPath,"SkillLineAbility.dbc");
LoadDBC(availableDbcLocales,bar,bad_dbc_files,sSoundEntriesStore, dbcPath,"SoundEntries.dbc");
- LoadDBC(availableDbcLocales,bar,bad_dbc_files,sSpellStore, dbcPath,"Spell.dbc", &CustomSpellEntryfmt, &CustomSpellEntryIndex);
+ LoadDBC(availableDbcLocales,bar,bad_dbc_files,sSpellStore, dbcPath,"Spell.dbc", &CustomSpellEntryfmt, &CustomSpellEntryIndex);
for (uint32 i = 1; i < sSpellStore.GetNumRows(); ++i)
{
SpellEntry const * spell = sSpellStore.LookupEntry(i);
@@ -506,18 +518,17 @@ void LoadDBCStores(const std::string& dataPath)
}
// Check loaded DBC files proper version
- if( !sSpellStore.LookupEntry(66530) || // last added spell in 3.1.3
- !sMapStore.LookupEntry(624) || // last map added in 3.1.3
- !sGemPropertiesStore.LookupEntry(1609) || // last gem property added in 3.1.3
- !sItemExtendedCostStore.LookupEntry(2671) || // last item extended cost added in 3.1.3
- !sCharTitlesStore.LookupEntry(166) || // last char title added in 3.1.3
- !sAreaStore.LookupEntry(2905) || // last area (areaflag) added in 3.1.3
- !sItemStore.LookupEntry(46894) ) // last client known item added in 3.1.3
+ if( !sSpellStore.LookupEntry(69599) || // last added spell in 3.2.2
+ !sMapStore.LookupEntry(650) || // last map added in 3.2.2
+ !sGemPropertiesStore.LookupEntry(1629) || // last gem property added in 3.2.2
+ !sItemExtendedCostStore.LookupEntry(2723) || // last item extended cost added in 3.2.2
+ !sCharTitlesStore.LookupEntry(171) || // last char title added in 3.2.2
+ !sAreaStore.LookupEntry(3091) || // last area (areaflag) added in 3.2.2
+ !sItemStore.LookupEntry(49667) ) // last client known item added in 3.2.2
{
sLog.outError("\nYou have _outdated_ DBC files. Please extract correct versions from current using client.");
exit(1);
}
-
sLog.outString();
sLog.outString( ">> Initialized %d data stores", DBCFilesCount );
}
@@ -695,6 +706,12 @@ void Map2ZoneCoordinates(float& x,float& y,uint32 zone)
std::swap(x,y); // client have map coords swapped
}
+MapDifficulty const* GetMapDifficultyData(uint32 mapId, Difficulty difficulty)
+{
+ MapDifficultyMap::const_iterator itr = sMapDifficultyMap.find(MAKE_PAIR32(mapId,difficulty));
+ return itr != sMapDifficultyMap.end() ? &itr->second : NULL;
+}
+
uint32 const* GetTalentTabPages(uint8 cls)
{
return sTalentTabPages[cls];
diff --git a/src/game/DBCStores.h b/src/game/DBCStores.h
index 20de8f997d9..dbe94d941db 100644
--- a/src/game/DBCStores.h
+++ b/src/game/DBCStores.h
@@ -54,6 +54,9 @@ bool IsTotemCategoryCompatiableWith(uint32 itemTotemCategoryId, uint32 requiredT
void Zone2MapCoordinates(float &x, float &y, uint32 zone);
void Map2ZoneCoordinates(float &x, float &y, uint32 zone);
+typedef std::map<uint32/*pair32(map,diff)*/,MapDifficulty> MapDifficultyMap;
+MapDifficulty const* GetMapDifficultyData(uint32 mapId, Difficulty difficulty);
+
uint32 const* /*[3]*/ GetTalentTabPages(uint8 cls);
extern DBCStorage <AchievementEntry> sAchievementStore;
@@ -110,6 +113,8 @@ extern DBCStorage <ItemSetEntry> sItemSetStore;
extern DBCStorage <LockEntry> sLockStore;
extern DBCStorage <MailTemplateEntry> sMailTemplateStore;
extern DBCStorage <MapEntry> sMapStore;
+//extern DBCStorage <MapDifficultyEntry> sMapDifficultyStore; -- use GetMapDifficultyData insteed
+extern MapDifficultyMap sMapDifficultyMap;
extern DBCStorage <MovieEntry> sMovieStore;
extern DBCStorage <QuestSortEntry> sQuestSortStore;
extern DBCStorage <RandomPropertiesPointsEntry> sRandomPropertiesPointsStore;
diff --git a/src/game/DBCStructure.h b/src/game/DBCStructure.h
index a139c4efa51..71fedfe242a 100644
--- a/src/game/DBCStructure.h
+++ b/src/game/DBCStructure.h
@@ -658,7 +658,7 @@ struct ChrClassesEntry
uint32 spellfamily; // 56
// 57, unused
uint32 CinematicSequence; // 58 id from CinematicSequences.dbc
- uint32 addon; // 59 (0 - original race, 1 - tbc addon, ...)
+ uint32 expansion; // 59 (0 - original race, 1 - tbc addon, ...)
};
struct ChrRacesEntry
@@ -669,10 +669,11 @@ struct ChrRacesEntry
// 3 unused
uint32 model_m; // 4
uint32 model_f; // 5
- // 6-7 unused
- uint32 TeamID; // 8 (7-Alliance 1-Horde)
- // 9-12 unused
- uint32 CinematicSequence; // 13 id from CinematicSequences.dbc
+ // 6 unused
+ uint32 TeamID; // 7 (7-Alliance 1-Horde)
+ // 8-11 unused
+ uint32 CinematicSequence; // 12 id from CinematicSequences.dbc
+ //uint32 unk_322; // 13 faction (0 alliance, 1 horde, 2 not available?)
char* name[16]; // 14-29 used for DBC language detection/selection
// 30 string flags, unused
//char* nameFemale[16]; // 31-46, if different from base (male) case
@@ -680,7 +681,7 @@ struct ChrRacesEntry
//char* nameNeutralGender[16]; // 48-63, if different from base (male) case
// 64 string flags, unused
// 65-67 unused
- uint32 addon; // 68 (0 - original race, 1 - tbc addon, ...)
+ uint32 expansion; // 68 (0 - original race, 1 - tbc addon, ...)
};
/* not used
@@ -1043,9 +1044,10 @@ struct ItemExtendedCostEntry
uint32 ID; // 0 extended-cost entry id
uint32 reqhonorpoints; // 1 required honor points
uint32 reqarenapoints; // 2 required arena points
- uint32 reqitem[5]; // 3-7 required item id
- uint32 reqitemcount[5]; // 8-12 required count of 1st item
- uint32 reqpersonalarenarating; // 13 required personal arena rating
+ //uint32 unk1; // 4 probably indicates new 2v2 bracket restrictions
+ uint32 reqitem[5]; // 5-8 required item id
+ uint32 reqitemcount[5]; // 9-13 required count of 1st item
+ uint32 reqpersonalarenarating; // 14 required personal arena rating};
};
struct ItemLimitCategoryEntry
@@ -1062,14 +1064,14 @@ struct ItemRandomPropertiesEntry
uint32 ID; // 0 m_ID
//char* internalName // 1 m_Name
uint32 enchant_id[5]; // 2-6 m_Enchantment
- //char* nameSuffix[16] // 7-22 m_name_lang
+ char* nameSuffix[16]; // 7-22 m_name_lang
// 23 name flags
};
struct ItemRandomSuffixEntry
{
uint32 ID; // 0 m_ID
- //char* name[16] // 1-16 m_name_lang
+ char* nameSuffix[16]; // 1-16 m_name_lang
// 17, name flags
// 18 m_internalName
uint32 enchant_id[5]; // 19-21 m_enchantment
@@ -1104,7 +1106,7 @@ struct MailTemplateEntry
uint32 ID; // 0
//char* subject[16]; // 1-16
// 17 name flags, unused
- char* content[16]; // 18-33
+ char* content[16]; // 18-33
};
struct MapEntry
@@ -1122,21 +1124,13 @@ struct MapEntry
// 55 intro text flags
uint32 multimap_id; // 56
// 57
- //chat* unknownText1[16]; // 58-73 unknown empty text fields, possible normal Intro text.
- // 74 text flags
- //chat* heroicIntroText[16]; // 75-90 heroic mode requirement text
- // 91 text flags
- //chat* unknownText2[16]; // 92-107 unknown empty text fields
- // 108 text flags
- int32 entrance_map; // 109 map_id of entrance map
- float entrance_x; // 110 entrance x coordinate (if exist single entry)
- float entrance_y; // 111 entrance y coordinate (if exist single entry)
- uint32 resetTimeRaid; // 112
- uint32 resetTimeHeroic; // 113
- // 114 all 0
- // 115 -1, 0 and 720
- uint32 addon; // 116 (0-original maps,1-tbc addon)
- // 117 some kind of time?
+ int32 entrance_map; // 58 map_id of entrance map
+ float entrance_x; // 59 entrance x coordinate (if exist single entry)
+ float entrance_y; // 60 entrance y coordinate (if exist single entry)
+ // 61 -1, 0 and 720
+ uint32 addon; // 62 (0-original maps,1-tbc addon)
+ // 63 some kind of time?
+ //uint32 maxPlayers; // 64 max players
// Helpers
uint32 Expansion() const { return addon; }
@@ -1148,8 +1142,6 @@ struct MapEntry
bool IsBattleGround() const { return map_type == MAP_BATTLEGROUND; }
bool IsBattleArena() const { return map_type == MAP_ARENA; }
bool IsBattleGroundOrArena() const { return map_type == MAP_BATTLEGROUND || map_type == MAP_ARENA; }
- bool SupportsHeroicMode() const { return resetTimeHeroic != 0; }
- bool HasResetTime() const { return resetTimeHeroic || resetTimeRaid; }
bool IsMountAllowed() const
{
@@ -1157,7 +1149,7 @@ struct MapEntry
MapID==209 || MapID==269 || MapID==309 || // TanarisInstance, CavernsOfTime, Zul'gurub
MapID==509 || MapID==534 || MapID==560 || // AhnQiraj, HyjalPast, HillsbradPast
MapID==568 || MapID==580 || MapID==615 || // ZulAman, Sunwell Plateau, Obsidian Sanctrum
- MapID==616; // Eye Of Eternity
+ MapID==616 || MapID==595; // Eye Of Eternity, The Culling of Stratholme
}
bool IsContinent() const
@@ -1166,6 +1158,19 @@ struct MapEntry
}
};
+struct MapDifficultyEntry
+{
+ //uint32 Id; // 0
+ uint32 MapId; // 1
+ uint32 Difficulty; // 2 (for arenas: arena slot)
+ //char* areaTriggerText[16]; // 3-18 text showed when transfer to map failed (missing requirements)
+ //uint32 textFlags; // 19
+ uint32 resetTime; // 20
+ uint32 maxPlayers; // 21
+ //char* difficultyString; // 22
+};
+
+
struct MovieEntry
{
uint32 Id; // 0 index
@@ -1191,42 +1196,51 @@ struct RandomPropertiesPointsEntry
struct ScalingStatDistributionEntry
{
- uint32 Id;
- int32 StatMod[10];
- uint32 Modifier[10];
- uint32 MaxLevel;
+ uint32 Id; // 0
+ int32 StatMod[10]; // 1-10
+ uint32 Modifier[10]; // 11-20
+ uint32 MaxLevel; // 21
};
struct ScalingStatValuesEntry
{
- uint32 Id;
- uint32 Level;
- uint32 ssdMultiplier[5]; // Multiplier for ScalingStatDistribution
- uint32 armorMod[4]; // Armor for level
- uint32 dpsMod[6]; // DPS mod for level
- uint32 spellBonus; // not sure.. TODO: need more info about
- uint32 feralBonus; // Feral AP bonus
-
+ uint32 Id; // 0
+ uint32 Level; // 1
+ uint32 ssdMultiplier[4]; // 2-5 Multiplier for ScalingStatDistribution
+ uint32 armorMod[4]; // 6-9 Armor for level
+ uint32 dpsMod[6]; // 10-15 DPS mod for level
+ uint32 spellBonus; // 16 spell power for level
+ uint32 ssdMultiplier2; // 17 there's data from 3.1 dbc ssdMultiplier[3]
+ //uint32 unk1; // 18 all fields equal to 0
+ //uint32 unk2; // 19 unk, probably also Armor for level
+ uint32 armorMod2[4]; // 20-23 Armor for level
+
uint32 getssdMultiplier(uint32 mask) const
{
- if (mask&0x001F)
+ if (mask & 0x001F)
{
if(mask & 0x00000001) return ssdMultiplier[0];
if(mask & 0x00000002) return ssdMultiplier[1];
if(mask & 0x00000004) return ssdMultiplier[2];
- if(mask & 0x00000008) return ssdMultiplier[3];
- if(mask & 0x00000010) return ssdMultiplier[4];
+ if(mask & 0x00000008) return ssdMultiplier2;
+ if(mask & 0x00000010) return ssdMultiplier[3];
}
return 0;
}
+
uint32 getArmorMod(uint32 mask) const
{
- if (mask&0x01E0)
+ if (mask & 0x00F001E0)
{
if(mask & 0x00000020) return armorMod[0];
if(mask & 0x00000040) return armorMod[1];
if(mask & 0x00000080) return armorMod[2];
if(mask & 0x00000100) return armorMod[3];
+
+ if(mask & 0x00100000) return armorMod2[0]; // cloth
+ if(mask & 0x00200000) return armorMod2[1]; // leather
+ if(mask & 0x00400000) return armorMod2[2]; // mail
+ if(mask & 0x00800000) return armorMod2[3]; // plate
}
return 0;
}
@@ -1239,7 +1253,7 @@ struct ScalingStatValuesEntry
if(mask & 0x00000800) return dpsMod[2];
if(mask & 0x00001000) return dpsMod[3];
if(mask & 0x00002000) return dpsMod[4];
- if(mask & 0x00004000) return dpsMod[5];
+ if(mask & 0x00004000) return dpsMod[5]; // not used?
}
return 0;
}
@@ -1248,9 +1262,9 @@ struct ScalingStatValuesEntry
if (mask & 0x00008000) return spellBonus;
return 0;
}
- uint32 getFeralBonus(uint32 mask) const
+ uint32 getFeralBonus(uint32 mask) const // removed in 3.2.x?
{
- if (mask & 0x00010000) return feralBonus;
+ if (mask & 0x00010000) return 0; // not used?
return 0;
}
};
@@ -1342,68 +1356,71 @@ struct SpellEntry
uint32 AttributesEx4; // 8 m_attributesExD
uint32 AttributesEx5; // 9 m_attributesExE
uint32 AttributesEx6; // 10 m_attributesExF
- uint32 Stances; // 11 m_shapeshiftMask
- uint32 StancesNot; // 12 m_shapeshiftExclude
- uint32 Targets; // 13 m_targets
- uint32 TargetCreatureType; // 14 m_targetCreatureType
- uint32 RequiresSpellFocus; // 15 m_requiresSpellFocus
- uint32 FacingCasterFlags; // 16 m_facingCasterFlags
- uint32 CasterAuraState; // 17 m_casterAuraState
- uint32 TargetAuraState; // 18 m_targetAuraState
- uint32 CasterAuraStateNot; // 19 m_excludeCasterAuraState
- uint32 TargetAuraStateNot; // 20 m_excludeTargetAuraState
- uint32 casterAuraSpell; // 21 m_casterAuraSpell
- uint32 targetAuraSpell; // 22 m_targetAuraSpell
- uint32 excludeCasterAuraSpell; // 23 m_excludeCasterAuraSpell
- uint32 excludeTargetAuraSpell; // 24 m_excludeTargetAuraSpell
- uint32 CastingTimeIndex; // 25 m_castingTimeIndex
- uint32 RecoveryTime; // 26 m_recoveryTime
- uint32 CategoryRecoveryTime; // 27 m_categoryRecoveryTime
- uint32 InterruptFlags; // 28 m_interruptFlags
- uint32 AuraInterruptFlags; // 29 m_auraInterruptFlags
- uint32 ChannelInterruptFlags; // 30 m_channelInterruptFlags
- uint32 procFlags; // 31 m_procTypeMask
- uint32 procChance; // 32 m_procChance
- uint32 procCharges; // 33 m_procCharges
- uint32 maxLevel; // 34 m_maxLevel
- uint32 baseLevel; // 35 m_baseLevel
- uint32 spellLevel; // 36 m_spellLevel
- uint32 DurationIndex; // 37 m_durationIndex
- uint32 powerType; // 38 m_powerType
- uint32 manaCost; // 39 m_manaCost
- uint32 manaCostPerlevel; // 40 m_manaCostPerLevel
- uint32 manaPerSecond; // 41 m_manaPerSecond
- uint32 manaPerSecondPerLevel; // 42 m_manaPerSecondPerLeve
- uint32 rangeIndex; // 43 m_rangeIndex
- float speed; // 44 m_speed
- //uint32 modalNextSpell; // 45 m_modalNextSpell not used
- uint32 StackAmount; // 46 m_cumulativeAura
- uint32 Totem[2]; // 47-48 m_totem
- int32 Reagent[8]; // 49-56 m_reagent
- uint32 ReagentCount[8]; // 57-64 m_reagentCount
- int32 EquippedItemClass; // 65 m_equippedItemClass (value)
- int32 EquippedItemSubClassMask; // 66 m_equippedItemSubclass (mask)
- int32 EquippedItemInventoryTypeMask; // 67 m_equippedItemInvTypes (mask)
- uint32 Effect[MAX_SPELL_EFFECTS]; // 68-70 m_effect
- int32 EffectDieSides[MAX_SPELL_EFFECTS]; // 71-73 m_effectDieSides
- int32 EffectBaseDice[MAX_SPELL_EFFECTS]; // 74-76 m_effectBaseDice
- float EffectDicePerLevel[MAX_SPELL_EFFECTS]; // 77-79 m_effectDicePerLevel
- float EffectRealPointsPerLevel[MAX_SPELL_EFFECTS]; // 80-82 m_effectRealPointsPerLevel
- int32 EffectBasePoints[MAX_SPELL_EFFECTS]; // 83-85 m_effectBasePoints (don't must be used in spell/auras explicitly, must be used cached Spell::m_currentBasePoints)
- uint32 EffectMechanic[MAX_SPELL_EFFECTS]; // 86-88 m_effectMechanic
- uint32 EffectImplicitTargetA[MAX_SPELL_EFFECTS]; // 89-91 m_implicitTargetA
- uint32 EffectImplicitTargetB[MAX_SPELL_EFFECTS]; // 92-94 m_implicitTargetB
- uint32 EffectRadiusIndex[MAX_SPELL_EFFECTS]; // 95-97 m_effectRadiusIndex - spellradius.dbc
- uint32 EffectApplyAuraName[MAX_SPELL_EFFECTS]; // 98-100 m_effectAura
- uint32 EffectAmplitude[MAX_SPELL_EFFECTS]; // 101-103 m_effectAuraPeriod
- float EffectMultipleValue[MAX_SPELL_EFFECTS]; // 104-106 m_effectAmplitude
- uint32 EffectChainTarget[MAX_SPELL_EFFECTS]; // 107-109 m_effectChainTargets
- uint32 EffectItemType[MAX_SPELL_EFFECTS]; // 110-112 m_effectItemType
- int32 EffectMiscValue[MAX_SPELL_EFFECTS]; // 113-115 m_effectMiscValue
- int32 EffectMiscValueB[MAX_SPELL_EFFECTS]; // 116-118 m_effectMiscValueB
- uint32 EffectTriggerSpell[MAX_SPELL_EFFECTS]; // 119-121 m_effectTriggerSpell
- float EffectPointsPerComboPoint[MAX_SPELL_EFFECTS]; // 122-124 m_effectPointsPerCombo
- flag96 EffectSpellClassMask[MAX_SPELL_EFFECTS]; //
+ // uint32 unk_320_1; // 11 3.2.0 (0x20 - totems, 0x4 - paladin auras, etc...)
+ uint32 Stances; // 12 m_shapeshiftMask
+ // uint32 unk_320_2; // 13 3.2.0
+ uint32 StancesNot; // 14 m_shapeshiftExclude
+ // uint32 unk_320_3; // 15 3.2.0
+ uint32 Targets; // 16 m_targets
+ uint32 TargetCreatureType; // 17 m_targetCreatureType
+ uint32 RequiresSpellFocus; // 18 m_requiresSpellFocus
+ uint32 FacingCasterFlags; // 19 m_facingCasterFlags
+ uint32 CasterAuraState; // 20 m_casterAuraState
+ uint32 TargetAuraState; // 21 m_targetAuraState
+ uint32 CasterAuraStateNot; // 22 m_excludeCasterAuraState
+ uint32 TargetAuraStateNot; // 23 m_excludeTargetAuraState
+ uint32 casterAuraSpell; // 24 m_casterAuraSpell
+ uint32 targetAuraSpell; // 25 m_targetAuraSpell
+ uint32 excludeCasterAuraSpell; // 26 m_excludeCasterAuraSpell
+ uint32 excludeTargetAuraSpell; // 27 m_excludeTargetAuraSpell
+ uint32 CastingTimeIndex; // 28 m_castingTimeIndex
+ uint32 RecoveryTime; // 29 m_recoveryTime
+ uint32 CategoryRecoveryTime; // 30 m_categoryRecoveryTime
+ uint32 InterruptFlags; // 31 m_interruptFlags
+ uint32 AuraInterruptFlags; // 32 m_auraInterruptFlags
+ uint32 ChannelInterruptFlags; // 33 m_channelInterruptFlags
+ uint32 procFlags; // 34 m_procTypeMask
+ uint32 procChance; // 35 m_procChance
+ uint32 procCharges; // 36 m_procCharges
+ uint32 maxLevel; // 37 m_maxLevel
+ uint32 baseLevel; // 38 m_baseLevel
+ uint32 spellLevel; // 39 m_spellLevel
+ uint32 DurationIndex; // 40 m_durationIndex
+ uint32 powerType; // 41 m_powerType
+ uint32 manaCost; // 42 m_manaCost
+ uint32 manaCostPerlevel; // 43 m_manaCostPerLevel
+ uint32 manaPerSecond; // 44 m_manaPerSecond
+ uint32 manaPerSecondPerLevel; // 45 m_manaPerSecondPerLeve
+ uint32 rangeIndex; // 46 m_rangeIndex
+ float speed; // 47 m_speed
+ //uint32 modalNextSpell; // 48 m_modalNextSpell not used
+ uint32 StackAmount; // 49 m_cumulativeAura
+ uint32 Totem[2]; // 50-51 m_totem
+ int32 Reagent[8]; // 50-59 m_reagent
+ uint32 ReagentCount[8]; // 60-67 m_reagentCount
+ int32 EquippedItemClass; // 68 m_equippedItemClass (value)
+ int32 EquippedItemSubClassMask; // 69 m_equippedItemSubclass (mask)
+ int32 EquippedItemInventoryTypeMask; // 70 m_equippedItemInvTypes (mask)
+ uint32 Effect[MAX_SPELL_EFFECTS]; // 71-73 m_effect
+ int32 EffectDieSides[MAX_SPELL_EFFECTS]; // 74-76 m_effectDieSides
+ int32 EffectBaseDice[MAX_SPELL_EFFECTS]; // 77-79 m_effectBaseDice
+ float EffectDicePerLevel[MAX_SPELL_EFFECTS]; // 80-82 m_effectDicePerLevel
+ float EffectRealPointsPerLevel[MAX_SPELL_EFFECTS]; // 83-85 m_effectRealPointsPerLevel
+ int32 EffectBasePoints[MAX_SPELL_EFFECTS]; // 86-88 m_effectBasePoints (don't must be used in spell/auras explicitly, must be used cached Spell::m_currentBasePoints)
+ uint32 EffectMechanic[MAX_SPELL_EFFECTS]; // 89-91 m_effectMechanic
+ uint32 EffectImplicitTargetA[MAX_SPELL_EFFECTS]; // 92-94 m_implicitTargetA
+ uint32 EffectImplicitTargetB[MAX_SPELL_EFFECTS]; // 95-97 m_implicitTargetB
+ uint32 EffectRadiusIndex[MAX_SPELL_EFFECTS]; // 98-100 m_effectRadiusIndex - spellradius.dbc
+ uint32 EffectApplyAuraName[MAX_SPELL_EFFECTS]; // 101-103 m_effectAura
+ uint32 EffectAmplitude[MAX_SPELL_EFFECTS]; // 104-106 m_effectAuraPeriod
+ float EffectMultipleValue[MAX_SPELL_EFFECTS]; // 107-109 m_effectAmplitude
+ uint32 EffectChainTarget[MAX_SPELL_EFFECTS]; // 110-112 m_effectChainTargets
+ uint32 EffectItemType[MAX_SPELL_EFFECTS]; // 113-115 m_effectItemType
+ int32 EffectMiscValue[MAX_SPELL_EFFECTS]; // 116-118 m_effectMiscValue
+ int32 EffectMiscValueB[MAX_SPELL_EFFECTS]; // 119-121 m_effectMiscValueB
+ uint32 EffectTriggerSpell[MAX_SPELL_EFFECTS]; // 122-124 m_effectTriggerSpell
+ float EffectPointsPerComboPoint[MAX_SPELL_EFFECTS]; // 125-127 m_effectPointsPerCombo
+ flag96 EffectSpellClassMask[MAX_SPELL_EFFECTS]; // 127-133
uint32 SpellVisual[2]; // 134-135 m_spellVisualID
uint32 SpellIconID; // 136 m_spellIconID
uint32 activeIconID; // 137 m_activeIconID
@@ -1436,6 +1453,8 @@ struct SpellEntry
uint32 runeCostID; // 229 m_runeCostID
//uint32 spellMissileID; // 230 m_spellMissileID not used
//uint32 PowerDisplayId; // 231 PowerDisplay.dbc, new in 3.1
+ //float unk_320_4[3]; // 232-234 3.2.0
+ //uint32 spellDescriptionVariableID; // 235 3.2.0
// helpers
int32 CalculateSimpleValue(uint8 eff) const { return EffectBasePoints[eff]+int32(EffectBaseDice[eff]); }
@@ -1538,7 +1557,7 @@ struct SpellItemEnchantmentEntry
uint32 EnchantmentCondition; // 34 m_condition_id
uint32 requiredSkill; // 35 m_requiredSkillID
uint32 requiredSkillValue; // 36 m_requiredSkillRank
- uint32 RequiredLevel; // 37 m_requiredLevel - new in 3.1
+ uint32 requiredLevel; // 37 m_requiredLevel
};
struct SpellItemEnchantmentConditionEntry
@@ -1558,6 +1577,7 @@ struct StableSlotPricesEntry
uint32 Price;
};
+
struct SummonPropertiesEntry
{
uint32 Id; // 0
@@ -1568,6 +1588,7 @@ struct SummonPropertiesEntry
uint32 Flags; // 5
};
+
#define MAX_TALENT_RANK 5
#define MAX_PET_TALENT_RANK 3 // use in calculations, expected <= MAX_TALENT_RANK
@@ -1747,6 +1768,7 @@ struct WorldMapAreaEntry
float x2; // 7
int32 virtual_map_id; // 8 -1 (map_id have correct map) other: virtual map where zone show (map_id - where zone in fact internally)
// int32 dungeonMap_id; // 9 pointer to DungeonMap.dbc (owerride x1,x2,y1,y2 coordinates)
+ // uint32 someMapID; // 10
};
#define MAX_WORLD_MAP_OVERLAY_AREA_IDX 4
@@ -1780,6 +1802,15 @@ struct WorldSafeLocsEntry
#endif
// Structures not used for casting to loaded DBC data and not required then packing
+struct MapDifficulty
+{
+ MapDifficulty() : resetTime(0), maxPlayers(0) {}
+ MapDifficulty(uint32 _resetTime, uint32 _maxPlayers) : resetTime(_resetTime), maxPlayers(_maxPlayers) {}
+
+ uint32 resetTime;
+ uint32 maxPlayers;
+};
+
struct TalentSpellPos
{
TalentSpellPos() : talent_id(0), rank(0) {}
diff --git a/src/game/DBCfmt.h b/src/game/DBCfmt.h
index 2dcb7619a3e..635de26a07d 100644
--- a/src/game/DBCfmt.h
+++ b/src/game/DBCfmt.h
@@ -36,7 +36,7 @@ const char CharTitlesEntryfmt[]="nxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxi";
const char ChatChannelsEntryfmt[]="iixssssssssssssssssxxxxxxxxxxxxxxxxxx";
// ChatChannelsEntryfmt, index not used (more compact store)
const char ChrClassesEntryfmt[]="nxixxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxixii";
-const char ChrRacesEntryfmt[]="nxixiixxixxxxissssssssssssssssxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxi";
+const char ChrRacesEntryfmt[]="nxixiixixxxxixssssssssssssssssxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxi";
const char CinematicSequencesEntryfmt[]="nxxxxxxxxx";
const char CreatureDisplayInfofmt[]="nxxxfxxxxxxxxxxx";
const char CreatureFamilyfmt[]="nfifiiiiixssssssssssssssssxx";
@@ -68,26 +68,27 @@ const char Itemfmt[]="niiiiiii";
const char ItemBagFamilyfmt[]="nxxxxxxxxxxxxxxxxx";
//const char ItemDisplayTemplateEntryfmt[]="nxxxxxxxxxxixxxxxxxxxxx";
//const char ItemCondExtCostsEntryfmt[]="xiii";
-const char ItemExtendedCostEntryfmt[]="niiiiiiiiiiiiix";
+const char ItemExtendedCostEntryfmt[]="niixiiiiiiiiiiix";
const char ItemLimitCategoryEntryfmt[]="nxxxxxxxxxxxxxxxxxix";
-const char ItemRandomPropertiesfmt[]="nxiiiiixxxxxxxxxxxxxxxxx";
-const char ItemRandomSuffixfmt[]="nxxxxxxxxxxxxxxxxxxiiiiiiiiii";
+const char ItemRandomPropertiesfmt[]="nxiiiiissssssssssssssssx";
+const char ItemRandomSuffixfmt[]="nssssssssssssssssxxiiiiiiiiii";
const char ItemSetEntryfmt[]="dssssssssssssssssxxxxxxxxxxxxxxxxxxiiiiiiiiiiiiiiiiii";
const char LockEntryfmt[]="niiiiiiiiiiiiiiiiiiiiiiiixxxxxxxx";
const char MailTemplateEntryfmt[]="nxxxxxxxxxxxxxxxxxssssssssssssssssx";
-const char MapEntryfmt[]="nxixssssssssssssssssxixxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxixxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxiffiixxix";
+const char MapEntryfmt[]="nxixssssssssssssssssxixxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxixiffxixx";
+const char MapDifficultyEntryfmt[]="diixxxxxxxxxxxxxxxxxiix";
const char MovieEntryfmt[]="nxx";
const char QuestSortEntryfmt[]="nxxxxxxxxxxxxxxxxx";
const char RandomPropertiesPointsfmt[]="niiiiiiiiiiiiiii";
const char ScalingStatDistributionfmt[]="niiiiiiiiiiiiiiiiiiiii";
-const char ScalingStatValuesfmt[]="iniiiiiiiiiiiiiiiii";
+const char ScalingStatValuesfmt[]="iniiiiiiiiiiiiiiiixxiiii";
const char SkillLinefmt[]="nixssssssssssssssssxxxxxxxxxxxxxxxxxxixxxxxxxxxxxxxxxxxi";
const char SkillLineAbilityfmt[]="niiiixxiiiiixx";
const char SoundEntriesfmt[]="nxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
const char SpellCastTimefmt[]="nixx";
const char SpellDurationfmt[]="niii";
-const char SpellEntryfmt[]="niiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiifxiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiffffffiiiiiiiiiiiiiiiiiiiiifffiiiiiiiiiiiiiiifffiiiiiiiiiiiiixssssssssssssssssxssssssssssssssssxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxiiiiiiiiiiixfffxxxiiiiixx";
-const std::string CustomSpellEntryfmt="pappppppppaaapaaaaaaaaaaapaaapapppppppaaaaapaapaaaaaaaaaaaaaaaaaappppppppppppppppppppppppppppppppppppppppppaaaaaapppppppppaaapppppppppaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaappppppppapppaaaaappaaa";
+const char SpellEntryfmt[]="niiiiiiiiiixixixiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiifxiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiffffffiiiiiiiiiiiiiiiiiiiiifffiiiiiiiiiiiiiiifffiiiiiiiiiiiiixssssssssssssssssxssssssssssssssssxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxiiiiiiiiiiixfffxxxiiiiixxxxxx";
+const std::string CustomSpellEntryfmt="pappppppppaaaaaapaaaaaaaaaaapaaapapppppppaaaaapaapaaaaaaaaaaaaaaaaaappppppppppppppppppppppppppppppppppppppppppaaaaaapppppppppaaapppppppppaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaappppppppapppaaaaappaaaaaaa";
const std::string CustomSpellEntryIndex = "Id";
const char SpellFocusObjectfmt[]="nxxxxxxxxxxxxxxxxx";
const char SpellItemEnchantmentfmt[]="nxiiiiiixxxiiissssssssssssssssxiiiiiii";
@@ -106,7 +107,7 @@ const char TaxiPathNodeEntryfmt[]="diiifffiixx";
const char TotemCategoryEntryfmt[]="nxxxxxxxxxxxxxxxxxii";
const char VehicleEntryfmt[]="niffffiiiiiiiifffffffffffffffssssfifiixx";
const char VehicleSeatEntryfmt[]="niiffffffffffiiiiiifffffffiiifffiiiiiiiffiiiiixxxxxxxxxxxx";
-const char WorldMapAreaEntryfmt[]="xinxffffix";
+const char WorldMapAreaEntryfmt[]="xinxffffixx";
const char WorldMapOverlayEntryfmt[]="nxiiiixxxxxxxxxxx";
const char WorldSafeLocsEntryfmt[]="nifffxxxxxxxxxxxxxxxxx";
diff --git a/src/game/Debugcmds.cpp b/src/game/Debugcmds.cpp
index e016d8c98b0..375ad770ded 100644
--- a/src/game/Debugcmds.cpp
+++ b/src/game/Debugcmds.cpp
@@ -823,7 +823,7 @@ bool ChatHandler::HandleDebugSendSetPhaseShiftCommand(const char* args)
return true;
}
-bool ChatHandler::HandleDebugSetItemFlagCommand(const char* args)
+bool ChatHandler::HandleDebugGetItemValueCommand(const char* args)
{
if (!*args)
return false;
@@ -835,14 +835,48 @@ bool ChatHandler::HandleDebugSetItemFlagCommand(const char* args)
return false;
uint32 guid = (uint32)atoi(e);
- uint32 flag = (uint32)atoi(f);
+ uint32 index = (uint32)atoi(f);
Item *i = m_session->GetPlayer()->GetItemByGuid(MAKE_NEW_GUID(guid, 0, HIGHGUID_ITEM));
if (!i)
return false;
- i->SetUInt32Value(ITEM_FIELD_FLAGS, flag);
+ if (index >= i->GetValuesCount())
+ return false;
+
+ uint32 value = i->GetUInt32Value(index);
+
+ PSendSysMessage("Item %u: value at %u is %u", guid, index, value);
+
+ return true;
+}
+
+bool ChatHandler::HandleDebugSetItemValueCommand(const char* args)
+{
+ if (!*args)
+ return false;
+
+ char* e = strtok((char*)args, " ");
+ char* f = strtok(NULL, " ");
+ char* g = strtok(NULL, " ");
+
+ if (!e || !f || !g)
+ return false;
+
+ uint32 guid = (uint32)atoi(e);
+ uint32 index = (uint32)atoi(f);
+ uint32 value = (uint32)atoi(g);
+
+ Item *i = m_session->GetPlayer()->GetItemByGuid(MAKE_NEW_GUID(guid, 0, HIGHGUID_ITEM));
+
+ if (!i)
+ return false;
+
+ if (index >= i->GetValuesCount())
+ return false;
+
+ i->SetUInt32Value(index, value);
return true;
}
diff --git a/src/game/DuelHandler.cpp b/src/game/DuelHandler.cpp
index c35b9dbdc07..d9854d900c8 100644
--- a/src/game/DuelHandler.cpp
+++ b/src/game/DuelHandler.cpp
@@ -51,10 +51,8 @@ void WorldSession::HandleDuelAcceptedOpcode(WorldPacket& recvPacket)
pl->duel->startTimer = now;
plTarget->duel->startTimer = now;
- WorldPacket data(SMSG_DUEL_COUNTDOWN, 4);
- data << (uint32)3000; // 3 seconds
- pl->GetSession()->SendPacket(&data);
- plTarget->GetSession()->SendPacket(&data);
+ pl->SendDuelCountdown(3000);
+ plTarget->SendDuelCountdown(3000);
}
void WorldSession::HandleDuelCancelledOpcode(WorldPacket& recvPacket)
@@ -84,4 +82,3 @@ void WorldSession::HandleDuelCancelledOpcode(WorldPacket& recvPacket)
GetPlayer()->DuelComplete(DUEL_INTERUPTED);
}
-
diff --git a/src/game/DynamicObject.cpp b/src/game/DynamicObject.cpp
index db0a4a7f2ef..be56b9f5069 100644
--- a/src/game/DynamicObject.cpp
+++ b/src/game/DynamicObject.cpp
@@ -33,7 +33,7 @@ DynamicObject::DynamicObject() : WorldObject()
m_objectType |= TYPEMASK_DYNAMICOBJECT;
m_objectTypeId = TYPEID_DYNAMICOBJECT;
- m_updateFlag = (UPDATEFLAG_HIGHGUID | UPDATEFLAG_HAS_POSITION);
+ m_updateFlag = (UPDATEFLAG_HIGHGUID | UPDATEFLAG_HAS_POSITION | UPDATEFLAG_POSITION);
m_valuesCount = DYNAMICOBJECT_END;
}
@@ -88,9 +88,6 @@ bool DynamicObject::Create(uint32 guidlow, Unit *caster, uint32 spellId, uint32
SetUInt32Value( DYNAMICOBJECT_BYTES, 0x00000001 );
SetUInt32Value( DYNAMICOBJECT_SPELLID, spellId );
SetFloatValue( DYNAMICOBJECT_RADIUS, radius);
- SetFloatValue( DYNAMICOBJECT_POS_X, pos.m_positionX );
- SetFloatValue( DYNAMICOBJECT_POS_Y, pos.m_positionY );
- SetFloatValue( DYNAMICOBJECT_POS_Z, pos.m_positionZ );
SetUInt32Value( DYNAMICOBJECT_CASTTIME, getMSTime() ); // new 2.4.0
m_aliveDuration = duration;
@@ -184,4 +181,3 @@ bool DynamicObject::isVisibleForInState(Player const* u, bool inVisibleList) con
return IsInWorld() && u->IsInWorld()
&& (IsWithinDistInMap(u->m_seer,World::GetMaxVisibleDistanceForObject()+(inVisibleList ? World::GetVisibleObjectGreyDistance() : 0.0f), false));
}
-
diff --git a/src/game/DynamicObject.h b/src/game/DynamicObject.h
index 13747891964..89b227e64ff 100644
--- a/src/game/DynamicObject.h
+++ b/src/game/DynamicObject.h
@@ -64,11 +64,9 @@ class DynamicObject : public WorldObject
uint32 m_effMask;
int32 m_aliveDuration;
uint32 m_updateTimer;
- time_t m_nextThinkTime;
float m_radius;
AffectedSet m_affected;
private:
GridReference<DynamicObject> m_gridRef;
};
#endif
-
diff --git a/src/game/GameEventMgr.cpp b/src/game/GameEventMgr.cpp
index 7c879d86e7f..6e66e87cbe1 100644
--- a/src/game/GameEventMgr.cpp
+++ b/src/game/GameEventMgr.cpp
@@ -1279,7 +1279,9 @@ void GameEventMgr::GameEventSpawn(int16 event_id)
for (IdList::iterator itr = mGameEventPoolIds[internal_event_id].begin(); itr != mGameEventPoolIds[internal_event_id].end(); ++itr)
{
- poolhandler.SpawnPool(*itr);
+ poolhandler.SpawnPool(*itr, 0, 0);
+ poolhandler.SpawnPool(*itr, 0, TYPEID_GAMEOBJECT);
+ poolhandler.SpawnPool(*itr, 0, TYPEID_UNIT);
}
}
diff --git a/src/game/GameObject.h b/src/game/GameObject.h
index a915b81fc78..7d55afb7e60 100644
--- a/src/game/GameObject.h
+++ b/src/game/GameObject.h
@@ -754,4 +754,3 @@ class TRINITY_DLL_SPEC GameObject : public WorldObject
GridReference<GameObject> m_gridRef;
};
#endif
-
diff --git a/src/game/GossipDef.cpp b/src/game/GossipDef.cpp
index 418f27dc4ea..5b0d0bd1dc8 100644
--- a/src/game/GossipDef.cpp
+++ b/src/game/GossipDef.cpp
@@ -547,13 +547,13 @@ void PlayerMenu::SendQuestQueryResponse( Quest const *pQuest )
WorldPacket data( SMSG_QUEST_QUERY_RESPONSE, 100 ); // guess size
- data << uint32(pQuest->GetQuestId());
+ data << uint32(pQuest->GetQuestId()); // quest id
data << uint32(pQuest->GetQuestMethod()); // Accepted values: 0, 1 or 2. 0==IsAutoComplete() (skip objectives/details)
data << uint32(pQuest->GetQuestLevel()); // may be -1, static data, in other cases must be used dynamic level: Player::GetQuestLevel (0 is not known, but assuming this is no longer valid for quest intended for client)
data << uint32(pQuest->GetZoneOrSort()); // zone or sort to display in quest log
- data << uint32(pQuest->GetType());
- data << uint32(pQuest->GetSuggestedPlayers());
+ data << uint32(pQuest->GetType()); // quest type
+ data << uint32(pQuest->GetSuggestedPlayers()); // suggested players count
data << uint32(pQuest->GetRepObjectiveFaction()); // shown in quest log as part of quest objective
data << uint32(pQuest->GetRepObjectiveValue()); // shown in quest log as part of quest objective
@@ -566,7 +566,7 @@ void PlayerMenu::SendQuestQueryResponse( Quest const *pQuest )
if (pQuest->HasFlag(QUEST_FLAGS_HIDDEN_REWARDS))
data << uint32(0); // Hide money rewarded
else
- data << uint32(pQuest->GetRewOrReqMoney());
+ data << uint32(pQuest->GetRewOrReqMoney()); // reward money (below max lvl)
data << uint32(pQuest->GetRewMoneyMaxLevel()); // used in XP calculation at client
data << uint32(pQuest->GetRewSpell()); // reward spell, this spell will display (icon) (casted if RewSpellCast==0)
@@ -574,8 +574,8 @@ void PlayerMenu::SendQuestQueryResponse( Quest const *pQuest )
// rewarded honor points
data << uint32(Trinity::Honor::hk_honor_at_level(pSession->GetPlayer()->getLevel(), pQuest->GetRewHonorableKills()));
- data << uint32(pQuest->GetSrcItemId());
- data << uint32(pQuest->GetFlags() & 0xFFFF);
+ data << uint32(pQuest->GetSrcItemId()); // source item id
+ data << uint32(pQuest->GetFlags() & 0xFFFF); // quest flags
data << uint32(pQuest->GetCharTitleId()); // CharTitleId, new 2.4.0, player gets this title (id from CharTitles)
data << uint32(pQuest->GetPlayersSlain()); // players slain
data << uint32(pQuest->GetBonusTalents()); // bonus talents
@@ -628,15 +628,12 @@ void PlayerMenu::SendQuestQueryResponse( Quest const *pQuest )
data << uint32(pQuest->ReqSourceId[iI]);
}
- for (iI = 0; iI < QUEST_OBJECTIVES_COUNT; ++iI)
+ for (iI = 0; iI < QUEST_ITEM_OBJECTIVES_COUNT; ++iI)
{
data << uint32(pQuest->ReqItemId[iI]);
data << uint32(pQuest->ReqItemCount[iI]);
}
- data << uint32(0); // TODO: 5 item objective
- data << uint32(0);
-
for (iI = 0; iI < QUEST_OBJECTIVES_COUNT; ++iI)
data << ObjectiveText[iI];
@@ -782,7 +779,7 @@ void PlayerMenu::SendQuestGiverRequestItems( Quest const *pQuest, uint64 npcGUID
data << uint32( pQuest->GetReqItemsCount() );
ItemPrototype const *pItem;
- for (int i = 0; i < QUEST_OBJECTIVES_COUNT; ++i)
+ for (int i = 0; i < QUEST_ITEM_OBJECTIVES_COUNT; ++i)
{
if ( !pQuest->ReqItemId[i] ) continue;
pItem = objmgr.GetItemPrototype(pQuest->ReqItemId[i]);
@@ -807,4 +804,3 @@ void PlayerMenu::SendQuestGiverRequestItems( Quest const *pQuest, uint64 npcGUID
pSession->SendPacket( &data );
sLog.outDebug( "WORLD: Sent SMSG_QUESTGIVER_REQUEST_ITEMS NPCGuid=%u, questid=%u", GUID_LOPART(npcGUID), pQuest->GetQuestId() );
}
-
diff --git a/src/game/GossipDef.h b/src/game/GossipDef.h
index 88c15f334a1..5e4c2e8b65a 100644
--- a/src/game/GossipDef.h
+++ b/src/game/GossipDef.h
@@ -207,4 +207,3 @@ class TRINITY_DLL_SPEC PlayerMenu
void SendQuestGiverRequestItems( Quest const *pQuest, uint64 npcGUID, bool Completable, bool CloseOnCancel );
};
#endif
-
diff --git a/src/game/GridDefines.h b/src/game/GridDefines.h
index c51b507fcbd..968118431a7 100644
--- a/src/game/GridDefines.h
+++ b/src/game/GridDefines.h
@@ -191,4 +191,3 @@ namespace Trinity
}
}
#endif
-
diff --git a/src/game/GridNotifiers.h b/src/game/GridNotifiers.h
index ed6232b101f..9deb5cb2e24 100644
--- a/src/game/GridNotifiers.h
+++ b/src/game/GridNotifiers.h
@@ -1244,4 +1244,3 @@ namespace Trinity
#endif
}
#endif
-
diff --git a/src/game/Group.cpp b/src/game/Group.cpp
index 9face6d0e7d..a3fe884a645 100644
--- a/src/game/Group.cpp
+++ b/src/game/Group.cpp
@@ -71,7 +71,7 @@ Group::~Group()
// it is undefined whether objectmgr (which stores the groups) or instancesavemgr
// will be unloaded first so we must be prepared for both cases
// this may unload some instance saves
- for (uint8 i = 0; i < TOTAL_DIFFICULTIES; ++i)
+ for (uint8 i = 0; i < MAX_DIFFICULTY; ++i)
for (BoundInstancesMap::iterator itr2 = m_boundInstances[i].begin(); itr2 != m_boundInstances[i].end(); ++itr2)
itr2->second.save->RemoveGroup(this);
@@ -94,22 +94,27 @@ bool Group::Create(const uint64 &guid, const char * name)
m_lootThreshold = ITEM_QUALITY_UNCOMMON;
m_looterGuid = guid;
- m_difficulty = DIFFICULTY_NORMAL;
+ m_dungeonDifficulty = DUNGEON_DIFFICULTY_NORMAL;
+ m_raidDifficulty = RAID_DIFFICULTY_10MAN_NORMAL;
if(!isBGGroup())
{
Player *leader = objmgr.GetPlayer(guid);
- if(leader) m_difficulty = leader->GetDifficulty();
-
+ if(leader)
+ {
+ m_dungeonDifficulty = leader->GetDungeonDifficulty();
+ m_raidDifficulty = leader->GetRaidDifficulty();
+ }
+
Player::ConvertInstancesToGroup(leader, this, guid);
// store group in database
CharacterDatabase.BeginTransaction();
CharacterDatabase.PExecute("DELETE FROM groups WHERE leaderGuid ='%u'", GUID_LOPART(m_leaderGuid));
CharacterDatabase.PExecute("DELETE FROM group_member WHERE leaderGuid ='%u'", GUID_LOPART(m_leaderGuid));
- CharacterDatabase.PExecute("INSERT INTO groups(leaderGuid,mainTank,mainAssistant,lootMethod,looterGuid,lootThreshold,icon1,icon2,icon3,icon4,icon5,icon6,icon7,icon8,isRaid,difficulty) "
- "VALUES('%u','%u','%u','%u','%u','%u','" UI64FMTD "','" UI64FMTD "','" UI64FMTD "','" UI64FMTD "','" UI64FMTD "','" UI64FMTD "','" UI64FMTD "','" UI64FMTD "','%u','%u')",
+ CharacterDatabase.PExecute("INSERT INTO groups (leaderGuid,mainTank,mainAssistant,lootMethod,looterGuid,lootThreshold,icon1,icon2,icon3,icon4,icon5,icon6,icon7,icon8,isRaid,difficulty,raiddifficulty) "
+ "VALUES ('%u','%u','%u','%u','%u','%u','" UI64FMTD "','" UI64FMTD "','" UI64FMTD "','" UI64FMTD "','" UI64FMTD "','" UI64FMTD "','" UI64FMTD "','" UI64FMTD "','%u','%u','%u')",
GUID_LOPART(m_leaderGuid), GUID_LOPART(m_mainTank), GUID_LOPART(m_mainAssistant), uint32(m_lootMethod),
- GUID_LOPART(m_looterGuid), uint32(m_lootThreshold), m_targetIcons[0], m_targetIcons[1], m_targetIcons[2], m_targetIcons[3], m_targetIcons[4], m_targetIcons[5], m_targetIcons[6], m_targetIcons[7], isRaidGroup(), m_difficulty);
+ GUID_LOPART(m_looterGuid), uint32(m_lootThreshold), m_targetIcons[0], m_targetIcons[1], m_targetIcons[2], m_targetIcons[3], m_targetIcons[4], m_targetIcons[5], m_targetIcons[6], m_targetIcons[7], isRaidGroup(), uint32(m_dungeonDifficulty), m_raidDifficulty);
}
if(!AddMember(guid, name))
@@ -129,8 +134,8 @@ bool Group::LoadGroupFromDB(const uint64 &leaderGuid, QueryResult *result, bool
if(!result)
{
external = false;
- // 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14
- result = CharacterDatabase.PQuery("SELECT mainTank, mainAssistant, lootMethod, looterGuid, lootThreshold, icon1, icon2, icon3, icon4, icon5, icon6, icon7, icon8, isRaid, difficulty FROM groups WHERE leaderGuid ='%u'", GUID_LOPART(leaderGuid));
+ // 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
+ result = CharacterDatabase.PQuery("SELECT mainTank, mainAssistant, lootMethod, looterGuid, lootThreshold, icon1, icon2, icon3, icon4, icon5, icon6, icon7, icon8, isRaid, difficulty, raiddifficulty FROM groups WHERE leaderGuid ='%u'", GUID_LOPART(leaderGuid));
if(!result)
return false;
}
@@ -149,7 +154,16 @@ bool Group::LoadGroupFromDB(const uint64 &leaderGuid, QueryResult *result, bool
if (m_groupType == GROUPTYPE_RAID)
_initRaidSubGroupsCounter();
- m_difficulty = (*result)[14].GetUInt8();
+ uint32 diff = (*result)[14].GetUInt8();
+ if (diff >= MAX_DUNGEON_DIFFICULTY)
+ diff = DUNGEON_DIFFICULTY_NORMAL;
+ m_dungeonDifficulty = Difficulty(diff);
+
+ uint32 r_diff = (*result)[15].GetUInt8();
+ if (r_diff >= MAX_RAID_DIFFICULTY)
+ r_diff = RAID_DIFFICULTY_10MAN_NORMAL;
+ m_raidDifficulty = Difficulty(r_diff);
+
m_mainTank = (*result)[0].GetUInt64();
m_mainAssistant = (*result)[1].GetUInt64();
m_lootMethod = (LootMethod)(*result)[2].GetUInt8();
@@ -291,12 +305,21 @@ bool Group::AddMember(const uint64 &guid, const char* name)
{
// reset the new member's instances, unless he is currently in one of them
// including raid/heroic instances that they are not permanently bound to!
- player->ResetInstances(INSTANCE_RESET_GROUP_JOIN);
+ player->ResetInstances(INSTANCE_RESET_GROUP_JOIN,false);
+ player->ResetInstances(INSTANCE_RESET_GROUP_JOIN,true);
- if(player->getLevel() >= LEVELREQUIREMENT_HEROIC && player->GetDifficulty() != GetDifficulty() )
+ if (player->getLevel() >= LEVELREQUIREMENT_HEROIC)
{
- player->SetDifficulty(m_difficulty);
- player->SendDungeonDifficulty(true);
+ if (player->GetDungeonDifficulty() != GetDungeonDifficulty())
+ {
+ player->SetDungeonDifficulty(GetDungeonDifficulty());
+ player->SendDungeonDifficulty(true);
+ }
+ if (player->GetRaidDifficulty() != GetRaidDifficulty())
+ {
+ player->SetRaidDifficulty(GetRaidDifficulty());
+ player->SendRaidDifficulty(true);
+ }
}
}
player->SetGroupUpdateFlag(GROUP_UPDATE_FULL);
@@ -441,7 +464,8 @@ void Group::Disband(bool hideDestroy)
CharacterDatabase.PExecute("DELETE FROM groups WHERE leaderGuid='%u'", GUID_LOPART(m_leaderGuid));
CharacterDatabase.PExecute("DELETE FROM group_member WHERE leaderGuid='%u'", GUID_LOPART(m_leaderGuid));
CharacterDatabase.CommitTransaction();
- ResetInstances(INSTANCE_RESET_GROUP_DISBAND, NULL);
+ ResetInstances(INSTANCE_RESET_GROUP_DISBAND, false, NULL);
+ ResetInstances(INSTANCE_RESET_GROUP_DISBAND, true, NULL);
}
m_leaderGuid = 0;
@@ -454,12 +478,13 @@ void Group::Disband(bool hideDestroy)
void Group::SendLootStartRoll(uint32 CountDown, const Roll &r)
{
- WorldPacket data(SMSG_LOOT_START_ROLL, (8+4+4+4+4+4));
+ WorldPacket data(SMSG_LOOT_START_ROLL, (8+4+4+4+4+4+4));
data << uint64(r.itemGUID); // guid of rolled item
data << uint32(r.totalPlayersRolling); // maybe the number of players rolling for it???
data << uint32(r.itemid); // the itemEntryId for the item that shall be rolled for
data << uint32(r.itemRandomSuffix); // randomSuffix
data << uint32(r.itemRandomPropId); // item random property ID
+ data << uint32(r.itemCount); // items in stack
data << uint32(CountDown); // the countdown time to choose "need" or "greed"
for (Roll::PlayerVote::const_iterator itr=r.playerVote.begin(); itr!=r.playerVote.end(); ++itr)
@@ -475,7 +500,7 @@ void Group::SendLootStartRoll(uint32 CountDown, const Roll &r)
void Group::SendLootRoll(const uint64& SourceGuid, const uint64& TargetGuid, uint8 RollNumber, uint8 RollType, const Roll &r)
{
- WorldPacket data(SMSG_LOOT_ROLL, (8+4+8+4+4+4+1+1));
+ WorldPacket data(SMSG_LOOT_ROLL, (8+4+8+4+4+4+1+1+1));
data << uint64(SourceGuid); // guid of the item rolled
data << uint32(0); // unknown, maybe amount of players
data << uint64(TargetGuid);
@@ -704,23 +729,23 @@ void Group::CountRollVote(const uint64& playerGUID, const uint64& Guid, uint32 N
switch (Choise)
{
- case 0: //Player choose pass
+ case ROLL_PASS: // Player choose pass
{
- SendLootRoll(0, playerGUID, 128, 128, *roll);
+ SendLootRoll(0, playerGUID, 0, ROLL_PASS, *roll);
++roll->totalPass;
itr->second = PASS;
}
break;
- case 1: //player choose Need
+ case ROLL_NEED: // player choose Need
{
- SendLootRoll(0, playerGUID, 0, 0, *roll);
+ SendLootRoll(0, playerGUID, 0, ROLL_NEED, *roll);
++roll->totalNeed;
itr->second = NEED;
}
break;
- case 2: //player choose Greed
+ case ROLL_GREED: // player choose Greed
{
- SendLootRoll(0, playerGUID, 128, 2, *roll);
+ SendLootRoll(0, playerGUID, 128, ROLL_GREED, *roll);
++roll->totalGreed;
itr->second = GREED;
}
@@ -768,14 +793,14 @@ void Group::CountTheRoll(Rolls::iterator rollI, uint32 NumberOfPlayers)
continue;
uint8 randomN = urand(1, 99);
- SendLootRoll(0, itr->first, randomN, 1, *roll);
+ SendLootRoll(0, itr->first, randomN, ROLL_NEED, *roll);
if (maxresul < randomN)
{
maxguid = itr->first;
maxresul = randomN;
}
}
- SendLootRollWon(0, maxguid, maxresul, 1, *roll);
+ SendLootRollWon(0, maxguid, maxresul, ROLL_NEED, *roll);
player = objmgr.GetPlayer(maxguid);
if(player && player->GetSession())
@@ -815,14 +840,14 @@ void Group::CountTheRoll(Rolls::iterator rollI, uint32 NumberOfPlayers)
continue;
uint8 randomN = urand(1, 99);
- SendLootRoll(0, itr->first, randomN, 2, *roll);
+ SendLootRoll(0, itr->first, randomN, ROLL_GREED, *roll);
if (maxresul < randomN)
{
maxguid = itr->first;
maxresul = randomN;
}
}
- SendLootRollWon(0, maxguid, maxresul, 2, *roll);
+ SendLootRollWon(0, maxguid, maxresul, ROLL_GREED, *roll);
player = objmgr.GetPlayer(maxguid);
if(player && player->GetSession())
@@ -959,7 +984,8 @@ void Group::SendUpdate()
data << (uint8)m_lootMethod; // loot method
data << (uint64)m_looterGuid; // looter guid
data << (uint8)m_lootThreshold; // loot threshold
- data << (uint8)m_difficulty; // Heroic Mod Group
+ data << (uint8)m_dungeonDifficulty; // Dungeon Difficulty
+ data << (uint8)m_raidDifficulty; // Raid Difficulty
}
player->GetSession()->SendPacket( &data );
}
@@ -1076,7 +1102,7 @@ bool Group::_addMember(const uint64 &guid, const char* name, bool isAssistant, u
else
player->SetGroup(this, group);
// if the same group invites the player back, cancel the homebind timer
- InstanceGroupBind *bind = GetBoundInstance(player->GetMapId(), player->GetDifficulty());
+ InstanceGroupBind *bind = GetBoundInstance(player);
if(bind && bind->save->GetInstanceId() == player->GetInstanceId())
player->m_InstanceValid = true;
}
@@ -1162,7 +1188,7 @@ void Group::_setLeader(const uint64 &guid)
Player *player = objmgr.GetPlayer(slot->guid);
if(player)
{
- for (uint8 i = 0; i < TOTAL_DIFFICULTIES; ++i)
+ for (uint8 i = 0; i < MAX_DIFFICULTY; ++i)
{
for (BoundInstancesMap::iterator itr = m_boundInstances[i].begin(); itr != m_boundInstances[i].end();)
{
@@ -1211,7 +1237,7 @@ void Group::_removeRolls(const uint64 &guid)
roll->playerVote.erase(itr2);
- CountRollVote(guid, roll->itemGUID, GetMembersCount()-1, 3);
+ CountRollVote(guid, roll->itemGUID, GetMembersCount()-1, MAX_ROLL_TYPE);
}
}
@@ -1449,19 +1475,38 @@ void Roll::targetObjectBuildLink()
getTarget()->addLootValidatorRef(this);
}
-void Group::SetDifficulty(uint8 difficulty)
+void Group::SetDungeonDifficulty(Difficulty difficulty)
{
- m_difficulty = difficulty;
- if (!isBGGroup())
- CharacterDatabase.PExecute("UPDATE groups SET difficulty = %u WHERE leaderGuid ='%u'", m_difficulty, GUID_LOPART(m_leaderGuid));
-
+ m_dungeonDifficulty = difficulty;
+ if(!isBGGroup())
+ CharacterDatabase.PExecute("UPDATE groups SET difficulty = %u WHERE leaderGuid ='%u'", m_dungeonDifficulty, GUID_LOPART(m_leaderGuid));
+
for (GroupReference *itr = GetFirstMember(); itr != NULL; itr = itr->next())
{
Player *player = itr->getSource();
if(!player->GetSession() || player->getLevel() < LEVELREQUIREMENT_HEROIC)
continue;
- player->SetDifficulty(difficulty);
+ player->SetDungeonDifficulty(difficulty);
player->SendDungeonDifficulty(true);
+ //send player to recall positio nis a dungeon (to avoid an exploit)
+ if (sMapStore.LookupEntry(player->GetMap()->IsDungeon()))
+ player->TeleportTo(player->m_recallMap, player->m_recallX, player->m_recallY, player->m_recallZ, player->m_recallO);
+ }
+}
+
+void Group::SetRaidDifficulty(Difficulty difficulty)
+{
+ m_raidDifficulty = difficulty;
+ if(!isBGGroup())
+ CharacterDatabase.PExecute("UPDATE groups SET raiddifficulty = %u WHERE leaderGuid ='%u'", m_raidDifficulty, GUID_LOPART(m_leaderGuid));
+
+ for(GroupReference *itr = GetFirstMember(); itr != NULL; itr = itr->next())
+ {
+ Player *player = itr->getSource();
+ if(!player->GetSession() || player->getLevel() < LEVELREQUIREMENT_HEROIC)
+ continue;
+ player->SetRaidDifficulty(difficulty);
+ player->SendRaidDifficulty(true);
}
}
@@ -1470,7 +1515,7 @@ bool Group::InCombatToInstance(uint32 instanceId)
for (GroupReference *itr = GetFirstMember(); itr != NULL; itr = itr->next())
{
Player *pPlayer = itr->getSource();
- if(pPlayer && pPlayer->getAttackers().size() && pPlayer->GetInstanceId() == instanceId && (pPlayer->GetMap()->IsRaid() || pPlayer->GetMap()->IsHeroic()))
+ if(pPlayer && pPlayer->getAttackers().size() && pPlayer->GetInstanceId() == instanceId && (pPlayer->GetMap()->IsRaidOrHeroicDungeon()))
for (std::set<Unit*>::const_iterator i = pPlayer->getAttackers().begin(); i!=pPlayer->getAttackers().end(); ++i)
if((*i) && (*i)->GetTypeId() == TYPEID_UNIT && ((Creature*)(*i))->GetCreatureInfo()->flags_extra & CREATURE_FLAG_EXTRA_INSTANCE_BIND)
return true;
@@ -1478,7 +1523,7 @@ bool Group::InCombatToInstance(uint32 instanceId)
return false;
}
-void Group::ResetInstances(uint8 method, Player* SendMsgTo)
+void Group::ResetInstances(uint8 method, bool isRaid, Player* SendMsgTo)
{
if(isBGGroup())
return;
@@ -1486,13 +1531,13 @@ void Group::ResetInstances(uint8 method, Player* SendMsgTo)
// method can be INSTANCE_RESET_ALL, INSTANCE_RESET_CHANGE_DIFFICULTY, INSTANCE_RESET_GROUP_DISBAND
// we assume that when the difficulty changes, all instances that can be reset will be
- uint8 dif = GetDifficulty();
+ Difficulty diff = GetDifficulty(isRaid);
- for (BoundInstancesMap::iterator itr = m_boundInstances[dif].begin(); itr != m_boundInstances[dif].end();)
+ for (BoundInstancesMap::iterator itr = m_boundInstances[diff].begin(); itr != m_boundInstances[diff].end(); )
{
InstanceSave *p = itr->second.save;
const MapEntry *entry = sMapStore.LookupEntry(itr->first);
- if(!entry || (!p->CanReset() && method != INSTANCE_RESET_GROUP_DISBAND))
+ if(!entry || entry->IsRaid() != isRaid || !p->CanReset() && method != INSTANCE_RESET_GROUP_DISBAND)
{
++itr;
continue;
@@ -1501,7 +1546,7 @@ void Group::ResetInstances(uint8 method, Player* SendMsgTo)
if(method == INSTANCE_RESET_ALL)
{
// the "reset all instances" method can only reset normal maps
- if(dif == DIFFICULTY_HEROIC || entry->map_type == MAP_RAID)
+ if (entry->map_type == MAP_RAID || diff == DUNGEON_DIFFICULTY_HEROIC)
{
++itr;
continue;
@@ -1531,8 +1576,8 @@ void Group::ResetInstances(uint8 method, Player* SendMsgTo)
if(p->CanReset()) p->DeleteFromDB();
else CharacterDatabase.PExecute("DELETE FROM group_instance WHERE instance = '%u'", p->GetInstanceId());
// i don't know for sure if hash_map iterators
- m_boundInstances[dif].erase(itr);
- itr = m_boundInstances[dif].begin();
+ m_boundInstances[diff].erase(itr);
+ itr = m_boundInstances[diff].begin();
// this unloads the instance save unless online players are bound to it
// (eg. permanent binds or GM solo binds)
p->RemoveGroup(this);
@@ -1542,11 +1587,19 @@ void Group::ResetInstances(uint8 method, Player* SendMsgTo)
}
}
-InstanceGroupBind* Group::GetBoundInstance(uint32 mapid, uint8 difficulty)
+InstanceGroupBind* Group::GetBoundInstance(Player* player)
{
+ uint32 mapid = player->GetMapId();
+ MapEntry const* mapEntry = sMapStore.LookupEntry(mapid);
+ if(!mapEntry)
+ return NULL;
+
+ Difficulty difficulty = player->GetDifficulty(mapEntry->IsRaid());
+
// some instances only have one difficulty
- const MapEntry* entry = sMapStore.LookupEntry(mapid);
- if(!entry || !entry->SupportsHeroicMode()) difficulty = DIFFICULTY_NORMAL;
+ MapDifficulty const* mapDiff = GetMapDifficultyData(mapid,difficulty);
+ if(!mapDiff)
+ difficulty = DUNGEON_DIFFICULTY_NORMAL;
BoundInstancesMap::iterator itr = m_boundInstances[difficulty].find(mapid);
if(itr != m_boundInstances[difficulty].end())
@@ -1555,6 +1608,24 @@ InstanceGroupBind* Group::GetBoundInstance(uint32 mapid, uint8 difficulty)
return NULL;
}
+InstanceGroupBind* Group::GetBoundInstance(Map* aMap)
+{
+ // Currently spawn numbering not different from map difficulty
+ Difficulty difficulty = GetDifficulty(aMap->IsRaid());
+
+ // some instances only have one difficulty
+ MapDifficulty const* mapDiff = GetMapDifficultyData(aMap->GetId(),difficulty);
+ if(!mapDiff)
+ return NULL;
+
+ BoundInstancesMap::iterator itr = m_boundInstances[difficulty].find(aMap->GetId());
+ if(itr != m_boundInstances[difficulty].end())
+ return &itr->second;
+ else
+ return NULL;
+}
+
+
InstanceGroupBind* Group::BindToInstance(InstanceSave *save, bool permanent, bool load)
{
if(save && !isBGGroup())
@@ -1624,4 +1695,3 @@ void Group::BroadcastGroupUpdate(void)
}
}
}
-
diff --git a/src/game/Group.h b/src/game/Group.h
index e38d39ecd7b..26c2ea878e6 100644
--- a/src/game/Group.h
+++ b/src/game/Group.h
@@ -25,6 +25,7 @@
#include "GroupRefManager.h"
#include "BattleGround.h"
#include "LootMgr.h"
+#include "DBCEnums.h"
#include <map>
#include <vector>
@@ -100,7 +101,7 @@ class Roll : public LootValidatorRef
{
public:
Roll(uint64 _guid, LootItem const& li)
- : itemGUID(_guid), itemid(li.itemid), itemRandomPropId(li.randomPropertyId), itemRandomSuffix(li.randomSuffix),
+ : itemGUID(_guid), itemid(li.itemid), itemRandomPropId(li.randomPropertyId), itemRandomSuffix(li.randomSuffix), itemCount(li.count),
totalPlayersRolling(0), totalNeed(0), totalGreed(0), totalPass(0), itemSlot(0) {}
~Roll() { }
void setLoot(Loot *pLoot) { link(pLoot, this); }
@@ -111,6 +112,7 @@ class Roll : public LootValidatorRef
uint32 itemid;
int32 itemRandomPropId;
uint32 itemRandomSuffix;
+ uint8 itemCount;
typedef std::map<uint64, RollVote> PlayerVote;
PlayerVote playerVote; //vote position correspond with player position (in group)
uint8 totalPlayersRolling;
@@ -281,11 +283,15 @@ class TRINITY_DLL_SPEC Group
}
void SetTargetIcon(uint8 id, uint64 guid);
- void SetDifficulty(uint8 difficulty);
- uint8 GetDifficulty() { return m_difficulty; }
+
+ Difficulty GetDifficulty(bool isRaid) const { return isRaid ? m_raidDifficulty : m_dungeonDifficulty; }
+ Difficulty GetDungeonDifficulty() const { return m_dungeonDifficulty; }
+ Difficulty GetRaidDifficulty() const { return m_raidDifficulty; }
+ void SetDungeonDifficulty(Difficulty difficulty);
+ void SetRaidDifficulty(Difficulty difficulty);
uint16 InInstance();
bool InCombatToInstance(uint32 instanceId);
- void ResetInstances(uint8 method, Player* SendMsgTo);
+ void ResetInstances(uint8 method, bool isRaid, Player* SendMsgTo);
// -no description-
//void SendInit(WorldSession *session);
@@ -329,8 +335,9 @@ class TRINITY_DLL_SPEC Group
InstanceGroupBind* BindToInstance(InstanceSave *save, bool permanent, bool load = false);
void UnbindInstance(uint32 mapid, uint8 difficulty, bool unload = false);
- InstanceGroupBind* GetBoundInstance(uint32 mapid, uint8 difficulty);
- BoundInstancesMap& GetBoundInstances(uint8 difficulty) { return m_boundInstances[difficulty]; }
+ InstanceGroupBind* GetBoundInstance(Player* player);
+ InstanceGroupBind* GetBoundInstance(Map* aMap);
+ BoundInstancesMap& GetBoundInstances(Difficulty difficulty) { return m_boundInstances[difficulty]; }
// FG: evil hacks
void BroadcastGroupUpdate(void);
@@ -402,15 +409,15 @@ class TRINITY_DLL_SPEC Group
uint64 m_mainTank;
uint64 m_mainAssistant;
GroupType m_groupType;
- uint8 m_difficulty;
+ Difficulty m_dungeonDifficulty;
+ Difficulty m_raidDifficulty;
BattleGround* m_bgGroup;
uint64 m_targetIcons[TARGETICONCOUNT];
LootMethod m_lootMethod;
ItemQualities m_lootThreshold;
uint64 m_looterGuid;
Rolls RollId;
- BoundInstancesMap m_boundInstances[TOTAL_DIFFICULTIES];
+ BoundInstancesMap m_boundInstances[MAX_DIFFICULTY];
uint8* m_subGroupsCounts;
};
#endif
-
diff --git a/src/game/GroupHandler.cpp b/src/game/GroupHandler.cpp
index fab192bbedc..f8bdc008e51 100644
--- a/src/game/GroupHandler.cpp
+++ b/src/game/GroupHandler.cpp
@@ -96,7 +96,7 @@ void WorldSession::HandleGroupInviteOpcode( WorldPacket & recv_data )
return;
}
// just ignore us
- if(player->GetInstanceId() != 0 && player->GetDifficulty() != GetPlayer()->GetDifficulty())
+ if(player->GetInstanceId() != 0 && player->GetDungeonDifficulty() != GetPlayer()->GetDungeonDifficulty())
{
SendPartyResult(PARTY_OP_INVITE, membername, PARTY_RESULT_TARGET_IGNORE_YOU);
return;
@@ -386,10 +386,10 @@ void WorldSession::HandleLootRoll( WorldPacket &recv_data )
uint64 Guid;
uint32 NumberOfPlayers;
- uint8 Choise;
+ uint8 rollType;
recv_data >> Guid; //guid of the item rolled
recv_data >> NumberOfPlayers;
- recv_data >> Choise; //0: pass, 1: need, 2: greed
+ recv_data >> rollType; //0: pass, 1: need, 2: greed
//sLog.outDebug("WORLD RECIEVE CMSG_LOOT_ROLL, From:%u, Numberofplayers:%u, Choise:%u", (uint32)Guid, NumberOfPlayers, Choise);
@@ -398,14 +398,14 @@ void WorldSession::HandleLootRoll( WorldPacket &recv_data )
return;
// everything's fine, do it
- group->CountRollVote(GetPlayer()->GetGUID(), Guid, NumberOfPlayers, Choise);
+ group->CountRollVote(GetPlayer()->GetGUID(), Guid, NumberOfPlayers, rollType);
- switch (Choise)
+ switch (rollType)
{
- case 1:
+ case ROLL_NEED:
GetPlayer()->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_ROLL_NEED, 1);
break;
- case 2:
+ case ROLL_GREED:
GetPlayer()->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_ROLL_GREED, 1);
break;
}
@@ -919,4 +919,3 @@ void WorldSession::HandleOptOutOfLootOpcode( WorldPacket & recv_data )
if(unkn!=0)
sLog.outError("CMSG_GROUP_PASS_ON_LOOT: activation not implemented!");
}
-
diff --git a/src/game/Guild.cpp b/src/game/Guild.cpp
index 5e1e1409039..76c93a07956 100644
--- a/src/game/Guild.cpp
+++ b/src/game/Guild.cpp
@@ -953,15 +953,13 @@ void Guild::LogGuildEvent(uint8 EventType, uint32 PlayerGuid1, uint32 PlayerGuid
// Bank content related
void Guild::DisplayGuildBankContent(WorldSession *session, uint8 TabId)
{
- WorldPacket data(SMSG_GUILD_BANK_LIST, 1300);
-
- GuildBankTab const* tab = GetBankTab(TabId);
- if (!tab)
- return;
+ GuildBankTab const* tab = m_TabListMap[TabId];
if (!IsMemberHaveRights(session->GetPlayer()->GetGUIDLow(),TabId,GUILD_BANK_RIGHT_VIEW_TAB))
return;
+ WorldPacket data(SMSG_GUILD_BANK_LIST,1200);
+
data << uint64(GetGuildBankMoney());
data << uint8(TabId);
data << uint32(GetMemberSlotWithdrawRem(session->GetPlayer()->GetGUIDLow(), TabId)); // remaining slots for today
@@ -979,9 +977,7 @@ void Guild::DisplayGuildBankContent(WorldSession *session, uint8 TabId)
void Guild::DisplayGuildBankContentUpdate(uint8 TabId, int32 slot1, int32 slot2)
{
- GuildBankTab const* tab = GetBankTab(TabId);
- if (!tab)
- return;
+ GuildBankTab const* tab = m_TabListMap[TabId];
WorldPacket data(SMSG_GUILD_BANK_LIST,1200);
@@ -1029,9 +1025,7 @@ void Guild::DisplayGuildBankContentUpdate(uint8 TabId, int32 slot1, int32 slot2)
void Guild::DisplayGuildBankContentUpdate(uint8 TabId, GuildItemPosCountVec const& slots)
{
- GuildBankTab const* tab = GetBankTab(TabId);
- if (!tab)
- return;
+ GuildBankTab const* tab = m_TabListMap[TabId];
WorldPacket data(SMSG_GUILD_BANK_LIST,1200);
@@ -1101,6 +1095,20 @@ void Guild::DisplayGuildBankTabsInfo(WorldSession *session)
sLog.outDebug("WORLD: Sent (SMSG_GUILD_BANK_LIST)");
}
+void Guild::DisplayGuildBankMoneyUpdate()
+{
+ WorldPacket data(SMSG_GUILD_BANK_LIST, 8+1+4+1+1);
+
+ data << uint64(GetGuildBankMoney());
+ data << uint8(0); // TabId, default 0
+ data << uint32(0); // slot withdrow, default 0
+ data << uint8(0); // Tell client this is a tab content packet
+ data << uint8(0); // not send items
+ BroadcastPacket(&data);
+
+ sLog.outDebug("WORLD: Sent (SMSG_GUILD_BANK_LIST)");
+}
+
void Guild::CreateNewBankTab()
{
if (m_PurchasedTabs >= GUILD_BANK_MAX_TABS)
@@ -1121,14 +1129,6 @@ void Guild::CreateNewBankTab()
void Guild::SetGuildBankTabInfo(uint8 TabId, std::string Name, std::string Icon)
{
- if (TabId >= GUILD_BANK_MAX_TABS)
- return;
- if (TabId >= m_TabListMap.size())
- return;
-
- if (!m_TabListMap[TabId])
- return;
-
if (m_TabListMap[TabId]->Name == Name && m_TabListMap[TabId]->Icon == Icon)
return;
@@ -1572,7 +1572,7 @@ void Guild::UnloadGuildBankEventLog()
void Guild::DisplayGuildBankLogs(WorldSession *session, uint8 TabId)
{
- if (TabId > GUILD_BANK_MAX_TABS)
+ if (TabId >= GUILD_BANK_MAX_TABS) // tabs starts in 0
return;
if (TabId == GUILD_BANK_MAX_TABS)
@@ -1739,7 +1739,7 @@ Item* Guild::StoreItem(uint8 tabId, GuildItemPosCountVec const& dest, Item* pIte
return lastItem;
}
-// Return stored item (if stored to stack, it can diff. from pItem). And pItem can be deleted in this case.
+// Return stored item (if stored to stack, it can diff. from pItem). And pItem ca be deleted in this case.
Item* Guild::_StoreItem( uint8 tab, uint8 slot, Item *pItem, uint32 count, bool clone )
{
if (!pItem)
@@ -1765,15 +1765,15 @@ Item* Guild::_StoreItem( uint8 tab, uint8 slot, Item *pItem, uint32 count, bool
pItem->SetUInt64Value(ITEM_FIELD_OWNER, 0);
AddGBankItemToDB(GetId(), tab, slot, pItem->GetGUIDLow(), pItem->GetEntry());
pItem->FSetState(ITEM_NEW);
- pItem->SaveToDB(); // not in inventory and can be save standalone
+ pItem->SaveToDB(); // not in onventory and can be save standalone
return pItem;
}
else
{
- pItem2->SetCount(pItem2->GetCount() + count);
+ pItem2->SetCount( pItem2->GetCount() + count );
pItem2->FSetState(ITEM_CHANGED);
- pItem2->SaveToDB(); // not in inventory and can be save standalone
+ pItem2->SaveToDB(); // not in onventory and can be save standalone
if (!clone)
{
@@ -1968,12 +1968,7 @@ void Guild::SetGuildBankTabText(uint8 TabId, std::string text)
void Guild::SendGuildBankTabText(WorldSession *session, uint8 TabId)
{
- if (TabId >= GUILD_BANK_MAX_TABS) // tabs starts in 0
- return;
-
- GuildBankTab const *tab = GetBankTab(TabId);
- if (!tab)
- return;
+ GuildBankTab const* tab = m_TabListMap[TabId];
WorldPacket data(MSG_QUERY_GUILD_BANK_TEXT, 1+tab->Text.size()+1);
data << uint8(TabId);
@@ -1999,7 +1994,7 @@ void Guild::SwapItems(Player * pl, uint8 BankTab, uint8 BankTabSlot, uint8 BankT
{
sLog.outCrash("Guild::SwapItems: Player %s(GUIDLow: %u) tried to move item %u from tab %u slot %u to tab %u slot %u, but item %u has a stack of zero!",
pl->GetName(), pl->GetGUIDLow(), pItemSrc->GetEntry(), BankTab, BankTabSlot, BankTabDst, BankTabSlotDst, pItemSrc->GetEntry());
- //return; // Commented out for now, uncomment when it's verified that this causes a crash!
+ //return; // Commented out for now, uncomment when it's verified that this causes a crash!!
}
if (SplitedAmount >= pItemSrc->GetCount())
diff --git a/src/game/Guild.h b/src/game/Guild.h
index f3626942bfc..9e7c2ed9941 100644
--- a/src/game/Guild.h
+++ b/src/game/Guild.h
@@ -389,6 +389,7 @@ class Guild
// ** Guild bank **
// Content & item deposit/withdraw
void DisplayGuildBankContent(WorldSession *session, uint8 TabId);
+ void DisplayGuildBankMoneyUpdate();
void SwapItems( Player * pl, uint8 BankTab, uint8 BankTabSlot, uint8 BankTabDst, uint8 BankTabSlotDst, uint32 SplitedAmount);
void MoveFromBankToChar( Player * pl, uint8 BankTab, uint8 BankTabSlot, uint8 PlayerBag, uint8 PlayerSlot, uint32 SplitedAmount);
@@ -400,7 +401,6 @@ class Guild
void SetGuildBankTabText(uint8 TabId, std::string text);
void SendGuildBankTabText(WorldSession *session, uint8 TabId);
void SetGuildBankTabInfo(uint8 TabId, std::string name, std::string icon);
- const GuildBankTab *GetBankTab(uint8 index) { if(index >= m_TabListMap.size()) return NULL; return m_TabListMap[index]; }
const uint8 GetPurchasedTabs() const { return m_PurchasedTabs; }
uint32 GetBankRights(uint32 rankId, uint8 TabId) const;
bool IsMemberHaveRights(uint32 LowGuid, uint8 TabId,uint32 rights) const;
@@ -408,6 +408,7 @@ class Guild
// Load/unload
void LoadGuildBankFromDB();
void UnloadGuildBank();
+ bool IsGuildBankLoaded() const { return m_GuildBankLoaded; }
void IncOnlineMemberCount() { ++m_OnlineMembers; }
// Money deposit/withdraw
void SendMoneyInfo(WorldSession *session, uint32 LowGuid);
@@ -489,4 +490,3 @@ class Guild
Item* _StoreItem( uint8 tab, uint8 slot, Item *pItem, uint32 count, bool clone );
};
#endif
-
diff --git a/src/game/GuildHandler.cpp b/src/game/GuildHandler.cpp
index 80f5d124e94..e69a55d4024 100644
--- a/src/game/GuildHandler.cpp
+++ b/src/game/GuildHandler.cpp
@@ -31,36 +31,32 @@
void WorldSession::HandleGuildQueryOpcode(WorldPacket& recvPacket)
{
- uint32 guildId;
- Guild *guild;
-
- //sLog.outDebug("WORLD: Received CMSG_GUILD_QUERY");
+ sLog.outDebug("WORLD: Received CMSG_GUILD_QUERY");
+ uint32 guildId;
recvPacket >> guildId;
- guild = objmgr.GetGuildById(guildId);
- if(!guild)
+ if(Guild *guild = objmgr.GetGuildById(guildId))
{
- SendGuildCommandResult(GUILD_CREATE_S, "", GUILD_PLAYER_NOT_IN_GUILD);
+ guild->Query(this);
return;
}
- guild->Query(this);
+ SendGuildCommandResult(GUILD_CREATE_S, "", GUILD_PLAYER_NOT_IN_GUILD);
}
void WorldSession::HandleGuildCreateOpcode(WorldPacket& recvPacket)
{
- std::string gname;
-
- //sLog.outDebug("WORLD: Received CMSG_GUILD_CREATE");
+ sLog.outDebug("WORLD: Received CMSG_GUILD_CREATE");
+ std::string gname;
recvPacket >> gname;
- if(GetPlayer()->GetGuildId())
+ if(GetPlayer()->GetGuildId()) // already in guild
return;
Guild *guild = new Guild;
- if(!guild->Create(GetPlayer(),gname))
+ if(!guild->Create(GetPlayer(), gname))
{
delete guild;
return;
@@ -71,12 +67,11 @@ void WorldSession::HandleGuildCreateOpcode(WorldPacket& recvPacket)
void WorldSession::HandleGuildInviteOpcode(WorldPacket& recvPacket)
{
- std::string Invitedname, plname;
+ sLog.outDebug("WORLD: Received CMSG_GUILD_INVITE");
- //sLog.outDebug("WORLD: Received CMSG_GUILD_INVITE");
+ std::string Invitedname, plname;
Player * player = NULL;
-
recvPacket >> Invitedname;
if(normalizePlayerName(Invitedname))
@@ -137,15 +132,14 @@ void WorldSession::HandleGuildInviteOpcode(WorldPacket& recvPacket)
data << guild->GetName();
player->GetSession()->SendPacket(&data);
- //sLog.outDebug("WORLD: Sent (SMSG_GUILD_INVITE)");
+ sLog.outDebug("WORLD: Sent (SMSG_GUILD_INVITE)");
}
void WorldSession::HandleGuildRemoveOpcode(WorldPacket& recvPacket)
{
- std::string plName;
-
- //sLog.outDebug("WORLD: Received CMSG_GUILD_REMOVE");
+ sLog.outDebug("WORLD: Received CMSG_GUILD_REMOVE");
+ std::string plName;
recvPacket >> plName;
if(!normalizePlayerName(plName))
@@ -202,7 +196,7 @@ void WorldSession::HandleGuildAcceptOpcode(WorldPacket& /*recvPacket*/)
Guild *guild;
Player *player = GetPlayer();
- //sLog.outDebug("WORLD: Received CMSG_GUILD_ACCEPT");
+ sLog.outDebug("WORLD: Received CMSG_GUILD_ACCEPT");
guild = objmgr.GetGuildById(player->GetGuildIdInvited());
if(!guild || player->GetGuildId())
@@ -223,12 +217,12 @@ void WorldSession::HandleGuildAcceptOpcode(WorldPacket& /*recvPacket*/)
data << player->GetName();
guild->BroadcastPacket(&data);
- //sLog.outDebug("WORLD: Sent (SMSG_GUILD_EVENT)");
+ sLog.outDebug("WORLD: Sent (SMSG_GUILD_EVENT)");
}
void WorldSession::HandleGuildDeclineOpcode(WorldPacket& /*recvPacket*/)
{
- //sLog.outDebug("WORLD: Received CMSG_GUILD_DECLINE");
+ sLog.outDebug("WORLD: Received CMSG_GUILD_DECLINE");
GetPlayer()->SetGuildIdInvited(0);
GetPlayer()->SetInGuild(0);
@@ -237,7 +231,7 @@ void WorldSession::HandleGuildDeclineOpcode(WorldPacket& /*recvPacket*/)
void WorldSession::HandleGuildInfoOpcode(WorldPacket& /*recvPacket*/)
{
Guild *guild;
- //sLog.outDebug("WORLD: Received CMSG_GUILD_INFO");
+ sLog.outDebug("WORLD: Received CMSG_GUILD_INFO");
guild = objmgr.GetGuildById(GetPlayer()->GetGuildId());
if(!guild)
@@ -259,21 +253,17 @@ void WorldSession::HandleGuildInfoOpcode(WorldPacket& /*recvPacket*/)
void WorldSession::HandleGuildRosterOpcode(WorldPacket& /*recvPacket*/)
{
- //sLog.outDebug("WORLD: Received CMSG_GUILD_ROSTER");
-
- Guild* guild = objmgr.GetGuildById(GetPlayer()->GetGuildId());
- if(!guild)
- return;
+ sLog.outDebug("WORLD: Received CMSG_GUILD_ROSTER");
- guild->Roster(this);
+ if(Guild* guild = objmgr.GetGuildById(_player->GetGuildId()))
+ guild->Roster(this);
}
void WorldSession::HandleGuildPromoteOpcode(WorldPacket& recvPacket)
{
- std::string plName;
-
- //sLog.outDebug("WORLD: Received CMSG_GUILD_PROMOTE");
+ sLog.outDebug("WORLD: Received CMSG_GUILD_PROMOTE");
+ std::string plName;
recvPacket >> plName;
if(!normalizePlayerName(plName))
@@ -285,6 +275,7 @@ void WorldSession::HandleGuildPromoteOpcode(WorldPacket& recvPacket)
SendGuildCommandResult(GUILD_CREATE_S, "", GUILD_PLAYER_NOT_IN_GUILD);
return;
}
+
if(!guild->HasRankRight(GetPlayer()->GetRank(), GR_RIGHT_PROMOTE))
{
SendGuildCommandResult(GUILD_INVITE_S, "", GUILD_PERMISSIONS);
@@ -332,10 +323,9 @@ void WorldSession::HandleGuildPromoteOpcode(WorldPacket& recvPacket)
void WorldSession::HandleGuildDemoteOpcode(WorldPacket& recvPacket)
{
- std::string plName;
-
- //sLog.outDebug("WORLD: Received CMSG_GUILD_DEMOTE");
+ sLog.outDebug("WORLD: Received CMSG_GUILD_DEMOTE");
+ std::string plName;
recvPacket >> plName;
if(!normalizePlayerName(plName))
@@ -401,17 +391,15 @@ void WorldSession::HandleGuildDemoteOpcode(WorldPacket& recvPacket)
void WorldSession::HandleGuildLeaveOpcode(WorldPacket& /*recvPacket*/)
{
- std::string plName;
- Guild *guild;
+ sLog.outDebug("WORLD: Received CMSG_GUILD_LEAVE");
- //sLog.outDebug("WORLD: Received CMSG_GUILD_LEAVE");
-
- guild = objmgr.GetGuildById(_player->GetGuildId());
+ Guild *guild = objmgr.GetGuildById(_player->GetGuildId());
if(!guild)
{
SendGuildCommandResult(GUILD_CREATE_S, "", GUILD_PLAYER_NOT_IN_GUILD);
return;
}
+
if(_player->GetGUID() == guild->GetLeader() && guild->GetMemberSize() > 1)
{
SendGuildCommandResult(GUILD_QUIT_S, "", GUILD_LEADER_LEAVE);
@@ -424,8 +412,6 @@ void WorldSession::HandleGuildLeaveOpcode(WorldPacket& /*recvPacket*/)
return;
}
- plName = _player->GetName();
-
guild->DelMember(_player->GetGUID());
// Put record into guildlog
guild->LogGuildEvent(GUILD_EVENT_LOG_LEAVE_GUILD, _player->GetGUIDLow(), 0, 0);
@@ -433,27 +419,25 @@ void WorldSession::HandleGuildLeaveOpcode(WorldPacket& /*recvPacket*/)
WorldPacket data(SMSG_GUILD_EVENT, (2+10)); // guess size
data << (uint8)GE_LEFT;
data << (uint8)1; // strings count
- data << plName;
+ data << _player->GetName();
guild->BroadcastPacket(&data);
- //sLog.outDebug("WORLD: Sent (SMSG_GUILD_EVENT)");
+ sLog.outDebug("WORLD: Sent (SMSG_GUILD_EVENT)");
SendGuildCommandResult(GUILD_QUIT_S, guild->GetName(), GUILD_PLAYER_NO_MORE_IN_GUILD);
}
void WorldSession::HandleGuildDisbandOpcode(WorldPacket& /*recvPacket*/)
{
- std::string name;
- Guild *guild;
-
- //sLog.outDebug("WORLD: Received CMSG_GUILD_DISBAND");
+ sLog.outDebug("WORLD: Received CMSG_GUILD_DISBAND");
- guild = objmgr.GetGuildById(GetPlayer()->GetGuildId());
+ Guild *guild = objmgr.GetGuildById(GetPlayer()->GetGuildId());
if(!guild)
{
SendGuildCommandResult(GUILD_CREATE_S, "", GUILD_PLAYER_NOT_IN_GUILD);
return;
}
+
if(GetPlayer()->GetGUID() != guild->GetLeader())
{
SendGuildCommandResult(GUILD_INVITE_S, "", GUILD_PERMISSIONS);
@@ -462,23 +446,22 @@ void WorldSession::HandleGuildDisbandOpcode(WorldPacket& /*recvPacket*/)
guild->Disband();
- //sLog.outDebug("WORLD: Guild Sucefully Disbanded");
+ sLog.outDebug("WORLD: Guild Successfully Disbanded");
}
void WorldSession::HandleGuildLeaderOpcode(WorldPacket& recvPacket)
{
- std::string name;
- Player *oldLeader = GetPlayer();
- Guild *guild;
-
- //sLog.outDebug("WORLD: Received CMSG_GUILD_LEADER");
+ sLog.outDebug("WORLD: Received CMSG_GUILD_LEADER");
+ std::string name;
recvPacket >> name;
+ Player *oldLeader = GetPlayer();
+
if(!normalizePlayerName(name))
return;
- guild = objmgr.GetGuildById(oldLeader->GetGuildId());
+ Guild *guild = objmgr.GetGuildById(oldLeader->GetGuildId());
if (!guild)
{
@@ -516,28 +499,28 @@ void WorldSession::HandleGuildLeaderOpcode(WorldPacket& recvPacket)
void WorldSession::HandleGuildMOTDOpcode(WorldPacket& recvPacket)
{
- Guild *guild;
+ sLog.outDebug("WORLD: Received CMSG_GUILD_MOTD");
+
std::string MOTD;
- //sLog.outDebug("WORLD: Received CMSG_GUILD_MOTD");
+ if(!recvPacket.empty())
+ recvPacket >> MOTD;
+ else
+ MOTD = "";
- guild = objmgr.GetGuildById(GetPlayer()->GetGuildId());
+ Guild *guild = objmgr.GetGuildById(GetPlayer()->GetGuildId());
if(!guild)
{
SendGuildCommandResult(GUILD_CREATE_S, "", GUILD_PLAYER_NOT_IN_GUILD);
return;
}
+
if(!guild->HasRankRight(GetPlayer()->GetRank(), GR_RIGHT_SETMOTD))
{
SendGuildCommandResult(GUILD_INVITE_S, "", GUILD_PERMISSIONS);
return;
}
- if(!recvPacket.empty())
- recvPacket >> MOTD;
- else
- MOTD = "";
-
guild->SetMOTD(MOTD);
WorldPacket data(SMSG_GUILD_EVENT, (2+MOTD.size()+1));
@@ -546,15 +529,14 @@ void WorldSession::HandleGuildMOTDOpcode(WorldPacket& recvPacket)
data << MOTD;
guild->BroadcastPacket(&data);
- //sLog.outDebug("WORLD: Sent (SMSG_GUILD_EVENT)");
+ sLog.outDebug("WORLD: Sent (SMSG_GUILD_EVENT)");
}
void WorldSession::HandleGuildSetPublicNoteOpcode(WorldPacket& recvPacket)
{
- std::string name,PNOTE;
-
- //sLog.outDebug("WORLD: Received CMSG_GUILD_SET_PUBLIC_NOTE");
+ sLog.outDebug("WORLD: Received CMSG_GUILD_SET_PUBLIC_NOTE");
+ std::string name,PNOTE;
recvPacket >> name;
if(!normalizePlayerName(name))
@@ -590,10 +572,9 @@ void WorldSession::HandleGuildSetPublicNoteOpcode(WorldPacket& recvPacket)
void WorldSession::HandleGuildSetOfficerNoteOpcode(WorldPacket& recvPacket)
{
- std::string plName, OFFNOTE;
-
- //sLog.outDebug("WORLD: Received CMSG_GUILD_SET_OFFICER_NOTE");
+ sLog.outDebug("WORLD: Received CMSG_GUILD_SET_OFFICER_NOTE");
+ std::string plName, OFFNOTE;
recvPacket >> plName;
if(!normalizePlayerName(plName))
@@ -605,6 +586,7 @@ void WorldSession::HandleGuildSetOfficerNoteOpcode(WorldPacket& recvPacket)
SendGuildCommandResult(GUILD_CREATE_S, "", GUILD_PLAYER_NOT_IN_GUILD);
return;
}
+
if (!guild->HasRankRight(GetPlayer()->GetRank(), GR_RIGHT_EOFFNOTE))
{
SendGuildCommandResult(GUILD_INVITE_S, "", GUILD_PERMISSIONS);
@@ -628,23 +610,19 @@ void WorldSession::HandleGuildSetOfficerNoteOpcode(WorldPacket& recvPacket)
void WorldSession::HandleGuildRankOpcode(WorldPacket& recvPacket)
{
- //recvPacket.hexlike();
-
- Guild *guild;
std::string rankname;
uint32 rankId;
uint32 rights, MoneyPerDay;
- //sLog.outDebug("WORLD: Received CMSG_GUILD_RANK");
+ sLog.outDebug("WORLD: Received CMSG_GUILD_RANK");
- guild = objmgr.GetGuildById(GetPlayer()->GetGuildId());
+ Guild *guild = objmgr.GetGuildById(GetPlayer()->GetGuildId());
if(!guild)
{
recvPacket.rpos(recvPacket.wpos()); // set to end to avoid warnings spam
SendGuildCommandResult(GUILD_CREATE_S, "", GUILD_PLAYER_NOT_IN_GUILD);
return;
}
-
else if(GetPlayer()->GetGUID() != guild->GetLeader())
{
recvPacket.rpos(recvPacket.wpos()); // set to end to avoid warnings spam
@@ -683,12 +661,12 @@ void WorldSession::HandleGuildRankOpcode(WorldPacket& recvPacket)
void WorldSession::HandleGuildAddRankOpcode(WorldPacket& recvPacket)
{
- Guild *guild;
- std::string rankname;
+ sLog.outDebug("WORLD: Received CMSG_GUILD_ADD_RANK");
- //sLog.outDebug("WORLD: Received CMSG_GUILD_ADD_RANK");
+ std::string rankname;
+ recvPacket >> rankname;
- guild = objmgr.GetGuildById(GetPlayer()->GetGuildId());
+ Guild *guild = objmgr.GetGuildById(GetPlayer()->GetGuildId());
if(!guild)
{
SendGuildCommandResult(GUILD_CREATE_S, "", GUILD_PLAYER_NOT_IN_GUILD);
@@ -704,8 +682,6 @@ void WorldSession::HandleGuildAddRankOpcode(WorldPacket& recvPacket)
if(guild->GetRanksSize() >= GUILD_RANKS_MAX_COUNT) // client not let create more 10 than ranks
return;
- recvPacket >> rankname;
-
guild->CreateRank(rankname, GR_RIGHT_GCHATLISTEN | GR_RIGHT_GCHATSPEAK);
guild->Query(this);
@@ -714,18 +690,14 @@ void WorldSession::HandleGuildAddRankOpcode(WorldPacket& recvPacket)
void WorldSession::HandleGuildDelRankOpcode(WorldPacket& /*recvPacket*/)
{
- Guild *guild;
- std::string rankname;
+ sLog.outDebug("WORLD: Received CMSG_GUILD_DEL_RANK");
- //sLog.outDebug("WORLD: Received CMSG_GUILD_DEL_RANK");
-
- guild = objmgr.GetGuildById(GetPlayer()->GetGuildId());
+ Guild *guild = objmgr.GetGuildById(GetPlayer()->GetGuildId());
if(!guild)
{
SendGuildCommandResult(GUILD_CREATE_S, "", GUILD_PLAYER_NOT_IN_GUILD);
return;
}
-
else if(GetPlayer()->GetGUID() != guild->GetLeader())
{
SendGuildCommandResult(GUILD_INVITE_S, "", GUILD_PERMISSIONS);
@@ -746,12 +718,12 @@ void WorldSession::SendGuildCommandResult(uint32 typecmd, const std::string& str
data << cmdresult;
SendPacket(&data);
- //sLog.outDebug("WORLD: Sent (SMSG_GUILD_COMMAND_RESULT)");
+ sLog.outDebug("WORLD: Sent (SMSG_GUILD_COMMAND_RESULT)");
}
void WorldSession::HandleGuildChangeInfoTextOpcode(WorldPacket& recvPacket)
{
- //sLog.outDebug("WORLD: Received CMSG_GUILD_INFO_TEXT");
+ sLog.outDebug("WORLD: Received CMSG_GUILD_INFO_TEXT");
std::string GINFO;
@@ -775,17 +747,14 @@ void WorldSession::HandleGuildChangeInfoTextOpcode(WorldPacket& recvPacket)
void WorldSession::HandleSaveGuildEmblemOpcode(WorldPacket& recvPacket)
{
- //sLog.outDebug("WORLD: Received MSG_SAVE_GUILD_EMBLEM");
+ sLog.outDebug("WORLD: Received MSG_SAVE_GUILD_EMBLEM");
uint64 vendorGuid;
- uint32 EmblemStyle;
- uint32 EmblemColor;
- uint32 BorderStyle;
- uint32 BorderColor;
- uint32 BackgroundColor;
+ uint32 EmblemStyle, EmblemColor, BorderStyle, BorderColor, BackgroundColor;
recvPacket >> vendorGuid;
+ recvPacket >> EmblemStyle >> EmblemColor >> BorderStyle >> BorderColor >> BackgroundColor;
Creature *pCreature = GetPlayer()->GetNPCIfCanInteractWith(vendorGuid,UNIT_NPC_FLAG_TABARDDESIGNER);
if (!pCreature)
@@ -800,12 +769,6 @@ void WorldSession::HandleSaveGuildEmblemOpcode(WorldPacket& recvPacket)
if(GetPlayer()->hasUnitState(UNIT_STAT_DIED))
GetPlayer()->RemoveAurasByType(SPELL_AURA_FEIGN_DEATH);
- recvPacket >> EmblemStyle;
- recvPacket >> EmblemColor;
- recvPacket >> BorderStyle;
- recvPacket >> BorderColor;
- recvPacket >> BackgroundColor;
-
Guild *guild = objmgr.GetGuildById(GetPlayer()->GetGuildId());
if(!guild)
{
@@ -841,17 +804,9 @@ void WorldSession::HandleGuildEventLogQueryOpcode(WorldPacket& /* recvPacket */)
{
// empty
sLog.outDebug("WORLD: Received (MSG_GUILD_EVENT_LOG_QUERY)");
- //recvPacket.hexlike();
-
- uint32 GuildId = GetPlayer()->GetGuildId();
- if (GuildId == 0)
- return;
-
- Guild *pGuild = objmgr.GetGuildById(GuildId);
- if(!pGuild)
- return;
-
- pGuild->DisplayGuildEventLog(this);
+ if(uint32 GuildId = GetPlayer()->GetGuildId())
+ if(Guild *pGuild = objmgr.GetGuildById(GuildId))
+ pGuild->DisplayGuildEventLog(this);
}
/****** GUILD BANK *******/
@@ -859,53 +814,44 @@ void WorldSession::HandleGuildEventLogQueryOpcode(WorldPacket& /* recvPacket */)
void WorldSession::HandleGuildBankMoneyWithdrawn( WorldPacket & /* recv_data */ )
{
sLog.outDebug("WORLD: Received (MSG_GUILD_BANK_MONEY_WITHDRAWN)");
- //recv_data.hexlike();
-
- uint32 GuildId = GetPlayer()->GetGuildId();
- if (GuildId == 0)
- return;
-
- Guild *pGuild = objmgr.GetGuildById(GuildId);
- if(!pGuild)
- return;
-
- pGuild->SendMoneyInfo(this, GetPlayer()->GetGUIDLow());
+ if(uint32 GuildId = GetPlayer()->GetGuildId())
+ if(Guild *pGuild = objmgr.GetGuildById(GuildId))
+ pGuild->SendMoneyInfo(this, GetPlayer()->GetGUIDLow());
}
void WorldSession::HandleGuildPermissions( WorldPacket& /* recv_data */ )
{
sLog.outDebug("WORLD: Received (MSG_GUILD_PERMISSIONS)");
- uint32 GuildId = GetPlayer()->GetGuildId();
- if (GuildId == 0)
- return;
-
- Guild *pGuild = objmgr.GetGuildById(GuildId);
- if(!pGuild)
- return;
-
- uint32 rankId = GetPlayer()->GetRank();
-
- WorldPacket data(MSG_GUILD_PERMISSIONS, 4*15+1);
- data << uint32(rankId); // guild rank id
- data << uint32(pGuild->GetRankRights(rankId)); // rank rights
- // money per day left
- data << uint32(pGuild->GetMemberMoneyWithdrawRem(GetPlayer()->GetGUIDLow()));
- data << uint8(pGuild->GetPurchasedTabs()); // tabs count
- // why sending all info when not all tabs are purchased???
- for (int i = 0; i < GUILD_BANK_MAX_TABS; ++i)
+ if(uint32 GuildId = GetPlayer()->GetGuildId())
{
- data << uint32(pGuild->GetBankRights(rankId, uint8(i)));
- data << uint32(pGuild->GetMemberSlotWithdrawRem(GetPlayer()->GetGUIDLow(), uint8(i)));
+ if(Guild *pGuild = objmgr.GetGuildById(GuildId))
+ {
+ uint32 rankId = GetPlayer()->GetRank();
+
+ WorldPacket data(MSG_GUILD_PERMISSIONS, 4*15+1);
+ data << uint32(rankId); // guild rank id
+ data << uint32(pGuild->GetRankRights(rankId)); // rank rights
+ // money per day left
+ data << uint32(pGuild->GetMemberMoneyWithdrawRem(GetPlayer()->GetGUIDLow()));
+ data << uint8(pGuild->GetPurchasedTabs()); // tabs count
+ // why sending all info when not all tabs are purchased???
+ for (int i = 0; i < GUILD_BANK_MAX_TABS; ++i)
+ {
+ data << uint32(pGuild->GetBankRights(rankId, uint8(i)));
+ data << uint32(pGuild->GetMemberSlotWithdrawRem(GetPlayer()->GetGUIDLow(), uint8(i)));
+ }
+ SendPacket(&data);
+ sLog.outDebug("WORLD: Sent (MSG_GUILD_PERMISSIONS)");
+ }
}
- SendPacket(&data);
- sLog.outDebug("WORLD: Sent (MSG_GUILD_PERMISSIONS)");
}
/* Called when clicking on Guild bank gameobject */
void WorldSession::HandleGuildBankerActivate( WorldPacket & recv_data )
{
sLog.outDebug("WORLD: Received (CMSG_GUILD_BANKER_ACTIVATE)");
+
uint64 GoGuid;
uint8 unk;
recv_data >> GoGuid >> unk;
@@ -917,7 +863,7 @@ void WorldSession::HandleGuildBankerActivate( WorldPacket & recv_data )
{
if(Guild *pGuild = objmgr.GetGuildById(GuildId))
{
- pGuild->DisplayGuildBankTabsInfo(this);
+ pGuild->DisplayGuildBankTabsInfo(this); // this also will load guild bank if not yet
return;
}
}
@@ -929,31 +875,35 @@ void WorldSession::HandleGuildBankerActivate( WorldPacket & recv_data )
void WorldSession::HandleGuildBankQueryTab( WorldPacket & recv_data )
{
sLog.outDebug("WORLD: Received (CMSG_GUILD_BANK_QUERY_TAB)");
+
uint64 GoGuid;
- uint8 TabId,unk1;
+ uint8 TabId, unk1;
recv_data >> GoGuid >> TabId >> unk1;
if (!GetPlayer()->GetGameObjectIfCanInteractWith(GoGuid, GAMEOBJECT_TYPE_GUILD_BANK))
return;
uint32 GuildId = GetPlayer()->GetGuildId();
- if (GuildId == 0)
+ if (!GuildId)
return;
Guild *pGuild = objmgr.GetGuildById(GuildId);
- if(!pGuild)
+ if (!pGuild)
+ return;
+
+ if (!pGuild->IsGuildBankLoaded() || TabId >= pGuild->GetPurchasedTabs())
return;
// Let's update the amount of gold the player can withdraw before displaying the content
- // This is usefull if money withdraw right has changed
+ // This is useful if money withdraw right has changed
pGuild->SendMoneyInfo(this, GetPlayer()->GetGUIDLow());
-
pGuild->DisplayGuildBankContent(this, TabId);
}
void WorldSession::HandleGuildBankDepositMoney( WorldPacket & recv_data )
{
sLog.outDebug("WORLD: Received (CMSG_GUILD_BANK_DEPOSIT_MONEY)");
+
uint64 GoGuid;
uint32 money;
recv_data >> GoGuid >> money;
@@ -964,15 +914,18 @@ void WorldSession::HandleGuildBankDepositMoney( WorldPacket & recv_data )
if (!GetPlayer()->GetGameObjectIfCanInteractWith(GoGuid, GAMEOBJECT_TYPE_GUILD_BANK))
return;
+ if (GetPlayer()->GetMoney() < money)
+ return;
+
uint32 GuildId = GetPlayer()->GetGuildId();
- if (GuildId == 0)
+ if (!GuildId)
return;
Guild *pGuild = objmgr.GetGuildById(GuildId);
- if(!pGuild)
+ if (!pGuild)
return;
- if (GetPlayer()->GetMoney() < money)
+ if (!pGuild->IsGuildBankLoaded() || !pGuild->GetPurchasedTabs())
return;
CharacterDatabase.BeginTransaction();
@@ -995,11 +948,13 @@ void WorldSession::HandleGuildBankDepositMoney( WorldPacket & recv_data )
pGuild->DisplayGuildBankTabsInfo(this);
pGuild->DisplayGuildBankContent(this, 0);
+ pGuild->DisplayGuildBankMoneyUpdate();
}
void WorldSession::HandleGuildBankWithdrawMoney( WorldPacket & recv_data )
{
sLog.outDebug("WORLD: Received (CMSG_GUILD_BANK_WITHDRAW_MONEY)");
+
uint64 GoGuid;
uint32 money;
recv_data >> GoGuid >> money;
@@ -1018,6 +973,9 @@ void WorldSession::HandleGuildBankWithdrawMoney( WorldPacket & recv_data )
if(!pGuild)
return;
+ if (!pGuild->IsGuildBankLoaded() || !pGuild->GetPurchasedTabs())
+ return;
+
if (pGuild->GetGuildBankMoney()<money) // not enough money in bank
return;
@@ -1043,12 +1001,12 @@ void WorldSession::HandleGuildBankWithdrawMoney( WorldPacket & recv_data )
pGuild->SendMoneyInfo(this, GetPlayer()->GetGUIDLow());
pGuild->DisplayGuildBankTabsInfo(this);
pGuild->DisplayGuildBankContent(this,0);
+ pGuild->DisplayGuildBankMoneyUpdate();
}
void WorldSession::HandleGuildBankSwapItems( WorldPacket & recv_data )
{
sLog.outDebug("WORLD: Received (CMSG_GUILD_BANK_SWAP_ITEMS)");
- //recv_data.hexlike();
uint64 GoGuid;
uint8 BankToBank;
@@ -1063,6 +1021,21 @@ void WorldSession::HandleGuildBankSwapItems( WorldPacket & recv_data )
uint32 SplitedAmount = 0;
recv_data >> GoGuid >> BankToBank;
+
+ uint32 GuildId = GetPlayer()->GetGuildId();
+ if (!GuildId)
+ {
+ recv_data.rpos(recv_data.wpos()); // prevent additional spam at rejected packet
+ return;
+ }
+
+ Guild *pGuild = objmgr.GetGuildById(GuildId);
+ if (!pGuild || !pGuild->IsGuildBankLoaded())
+ {
+ recv_data.rpos(recv_data.wpos()); // prevent additional spam at rejected packet
+ return;
+ }
+
if (BankToBank)
{
recv_data >> BankTabDst;
@@ -1074,7 +1047,10 @@ void WorldSession::HandleGuildBankSwapItems( WorldPacket & recv_data )
recv_data >> unk2; // always 0
recv_data >> SplitedAmount;
- if (BankTabSlotDst >= GUILD_BANK_MAX_SLOTS || (BankTabDst == BankTab && BankTabSlotDst == BankTabSlot) || BankTab >= GUILD_BANK_MAX_TABS)
+ if (BankTabSlotDst >= GUILD_BANK_MAX_SLOTS ||
+ (BankTabDst == BankTab && BankTabSlotDst == BankTabSlot) ||
+ BankTab >= pGuild->GetPurchasedTabs() ||
+ BankTabDst >= pGuild->GetPurchasedTabs())
{
recv_data.rpos(recv_data.wpos()); // prevent additional spam at rejected packet
return;
@@ -1100,7 +1076,8 @@ void WorldSession::HandleGuildBankSwapItems( WorldPacket & recv_data )
recv_data >> SplitedAmount;
}
- if ((BankTabSlot >= GUILD_BANK_MAX_SLOTS && BankTabSlot != 0xFF) || BankTab >= GUILD_BANK_MAX_TABS)
+ if (BankTabSlot >= GUILD_BANK_MAX_SLOTS && BankTabSlot != 0xFF ||
+ BankTab >= pGuild->GetPurchasedTabs())
{
recv_data.rpos(recv_data.wpos()); // prevent additional spam at rejected packet
return;
@@ -1110,30 +1087,20 @@ void WorldSession::HandleGuildBankSwapItems( WorldPacket & recv_data )
if (!GetPlayer()->GetGameObjectIfCanInteractWith(GoGuid, GAMEOBJECT_TYPE_GUILD_BANK))
return;
- uint32 GuildId = GetPlayer()->GetGuildId();
- if (GuildId == 0)
- return;
-
- Guild *pGuild = objmgr.GetGuildById(GuildId);
- if(!pGuild)
- return;
-
if (BankTab >= pGuild->GetPurchasedTabs())
return;
- Player *pl = GetPlayer();
-
// Bank <-> Bank
if (BankToBank)
{
- pGuild->SwapItems(pl, BankTab, BankTabSlot, BankTabDst, BankTabSlotDst, SplitedAmount);
+ pGuild->SwapItems(_player, BankTab, BankTabSlot, BankTabDst, BankTabSlotDst, SplitedAmount);
return;
}
// Player <-> Bank
// allow work with inventory only
- if(!Player::IsInventoryPos(PlayerBag,PlayerSlot) && !(PlayerBag == NULL_BAG && PlayerSlot == NULL_SLOT))
+ if(!Player::IsInventoryPos(PlayerBag, PlayerSlot) && !(PlayerBag == NULL_BAG && PlayerSlot == NULL_SLOT) )
{
_player->SendEquipError( EQUIP_ERR_NONE, NULL, NULL );
return;
@@ -1141,15 +1108,15 @@ void WorldSession::HandleGuildBankSwapItems( WorldPacket & recv_data )
// BankToChar swap or char to bank remaining
if (ToChar) // Bank -> Char cases
- pGuild->MoveFromBankToChar(pl, BankTab, BankTabSlot, PlayerBag, PlayerSlot, SplitedAmount);
+ pGuild->MoveFromBankToChar(_player, BankTab, BankTabSlot, PlayerBag, PlayerSlot, SplitedAmount);
else // Char -> Bank cases
- pGuild->MoveFromCharToBank(pl, PlayerBag, PlayerSlot, BankTab, BankTabSlot, SplitedAmount);
+ pGuild->MoveFromCharToBank(_player, PlayerBag, PlayerSlot, BankTab, BankTabSlot, SplitedAmount);
}
void WorldSession::HandleGuildBankBuyTab( WorldPacket & recv_data )
{
sLog.outDebug("WORLD: Received (CMSG_GUILD_BANK_BUY_TAB)");
- //recv_data.hexlike();
+
uint64 GoGuid;
uint8 TabId;
@@ -1160,25 +1127,20 @@ void WorldSession::HandleGuildBankBuyTab( WorldPacket & recv_data )
return;
uint32 GuildId = GetPlayer()->GetGuildId();
- if (GuildId==0)
+ if (!GuildId)
return;
Guild *pGuild = objmgr.GetGuildById(GuildId);
if(!pGuild)
return;
- uint32 TabCost = GetGuildBankTabPrice(TabId) * GOLD;
- if (!TabCost)
- return;
-
- if (pGuild->GetPurchasedTabs() >= GUILD_BANK_MAX_TABS)
+ // m_PurchasedTabs = 0 when buying Tab 0, that is why this check can be made
+ if (!pGuild->IsGuildBankLoaded() || TabId != pGuild->GetPurchasedTabs())
return;
- if (TabId != pGuild->GetPurchasedTabs()) // m_PurchasedTabs = 0 when buying Tab 0, that is why this check can be made
- {
- sLog.outError("Error: trying to buy a tab non contigous to owned ones");
+ uint32 TabCost = GetGuildBankTabPrice(TabId) * GOLD;
+ if (!TabCost)
return;
- }
if (GetPlayer()->GetMoney() < TabCost) // Should not happen, this is checked by client
return;
@@ -1195,7 +1157,7 @@ void WorldSession::HandleGuildBankBuyTab( WorldPacket & recv_data )
void WorldSession::HandleGuildBankUpdateTab( WorldPacket & recv_data )
{
sLog.outDebug("WORLD: Received (CMSG_GUILD_BANK_UPDATE_TAB)");
- //recv_data.hexlike();
+
uint64 GoGuid;
uint8 TabId;
std::string Name;
@@ -1216,11 +1178,14 @@ void WorldSession::HandleGuildBankUpdateTab( WorldPacket & recv_data )
return;
uint32 GuildId = GetPlayer()->GetGuildId();
- if (GuildId==0)
+ if (!GuildId)
return;
Guild *pGuild = objmgr.GetGuildById(GuildId);
- if(!pGuild)
+ if (!pGuild)
+ return;
+
+ if (!pGuild->IsGuildBankLoaded() || TabId >= pGuild->GetPurchasedTabs())
return;
pGuild->SetGuildBankTabInfo(TabId, Name, IconIndex);
@@ -1232,16 +1197,23 @@ void WorldSession::HandleGuildBankLogQuery( WorldPacket & recv_data )
{
sLog.outDebug("WORLD: Received (MSG_GUILD_BANK_LOG_QUERY)");
+ uint8 TabId;
+ recv_data >> TabId;
+
uint32 GuildId = GetPlayer()->GetGuildId();
- if (GuildId == 0)
+ if (!GuildId)
return;
Guild *pGuild = objmgr.GetGuildById(GuildId);
- if(!pGuild)
+ if (!pGuild)
return;
- uint8 TabId;
- recv_data >> TabId;
+ if (!pGuild->IsGuildBankLoaded())
+ return;
+
+ // GUILD_BANK_MAX_TABS send by client for money log
+ if (TabId >= pGuild->GetPurchasedTabs() && TabId != GUILD_BANK_MAX_TABS)
+ return;
pGuild->DisplayGuildBankLogs(this, TabId);
}
@@ -1250,16 +1222,19 @@ void WorldSession::HandleQueryGuildBankTabText(WorldPacket &recv_data)
{
sLog.outDebug("WORLD: Received MSG_QUERY_GUILD_BANK_TEXT");
+ uint8 TabId;
+ recv_data >> TabId;
+
uint32 GuildId = GetPlayer()->GetGuildId();
- if (GuildId == 0)
+ if (!GuildId)
return;
Guild *pGuild = objmgr.GetGuildById(GuildId);
- if(!pGuild)
+ if (!pGuild)
return;
- uint8 TabId;
- recv_data >> TabId;
+ if (!pGuild->IsGuildBankLoaded() || TabId >= pGuild->GetPurchasedTabs())
+ return;
pGuild->SendGuildBankTabText(this, TabId);
}
@@ -1267,18 +1242,22 @@ void WorldSession::HandleQueryGuildBankTabText(WorldPacket &recv_data)
void WorldSession::HandleSetGuildBankTabText(WorldPacket &recv_data)
{
sLog.outDebug("WORLD: Received CMSG_SET_GUILD_BANK_TEXT");
+
+ uint8 TabId;
+ std::string Text;
+ recv_data >> TabId;
+ recv_data >> Text;
+
uint32 GuildId = GetPlayer()->GetGuildId();
- if (GuildId == 0)
+ if (!GuildId)
return;
Guild *pGuild = objmgr.GetGuildById(GuildId);
- if(!pGuild)
+ if (!pGuild)
return;
- uint8 TabId;
- std::string Text;
- recv_data >> TabId;
- recv_data >> Text;
+ if (!pGuild->IsGuildBankLoaded() || TabId >= pGuild->GetPurchasedTabs())
+ return;
pGuild->SetGuildBankTabText(TabId, Text);
}
@@ -1289,4 +1268,3 @@ void WorldSession::SendSaveGuildEmblem( uint32 msg )
data << uint32(msg); // not part of guild
SendPacket( &data );
}
-
diff --git a/src/game/InstanceSaveMgr.cpp b/src/game/InstanceSaveMgr.cpp
index 8c1aab1b60b..128674d978a 100644
--- a/src/game/InstanceSaveMgr.cpp
+++ b/src/game/InstanceSaveMgr.cpp
@@ -77,15 +77,27 @@ InstanceSaveManager::~InstanceSaveManager()
- adding instance into manager
- called from InstanceMap::Add, _LoadBoundInstances, LoadGroups
*/
-InstanceSave* InstanceSaveManager::AddInstanceSave(uint32 mapId, uint32 instanceId, uint8 difficulty, time_t resetTime, bool canReset, bool load)
+InstanceSave* InstanceSaveManager::AddInstanceSave(uint32 mapId, uint32 instanceId, Difficulty difficulty, time_t resetTime, bool canReset, bool load)
{
- InstanceSave *save = GetInstanceSave(instanceId);
- if(save) return save;
+ if(InstanceSave *old_save = GetInstanceSave(instanceId))
+ return old_save;
const MapEntry* entry = sMapStore.LookupEntry(mapId);
- if(!entry || instanceId == 0)
+ if (!entry)
{
- sLog.outError("InstanceSaveManager::AddInstanceSave: mapid = %d, instanceid = %d!", mapId, instanceId);
+ sLog.outError("InstanceSaveManager::AddInstanceSave: wrong mapid = %d!", mapId, instanceId);
+ return NULL;
+ }
+
+ if (instanceId == 0)
+ {
+ sLog.outError("InstanceSaveManager::AddInstanceSave: mapid = %d, wrong instanceid = %d!", mapId, instanceId);
+ return NULL;
+ }
+
+ if (difficulty >= (entry->IsRaid() ? MAX_RAID_DIFFICULTY : MAX_DUNGEON_DIFFICULTY))
+ {
+ sLog.outError("InstanceSaveManager::AddInstanceSave: mapid = %d, instanceid = %d, wrong dificalty %u!", mapId, instanceId, difficulty);
return NULL;
}
@@ -93,19 +105,19 @@ InstanceSave* InstanceSaveManager::AddInstanceSave(uint32 mapId, uint32 instance
{
// initialize reset time
// for normal instances if no creatures are killed the instance will reset in two hours
- if(entry->map_type == MAP_RAID || difficulty == DIFFICULTY_HEROIC)
- resetTime = GetResetTimeFor(mapId);
+ if(entry->map_type == MAP_RAID || difficulty > DUNGEON_DIFFICULTY_NORMAL)
+ resetTime = GetResetTimeFor(mapId,difficulty);
else
{
resetTime = time(NULL) + 2 * HOUR;
// normally this will be removed soon after in InstanceMap::Add, prevent error
- ScheduleReset(true, resetTime, InstResetEvent(0, mapId, instanceId));
+ ScheduleReset(true, resetTime, InstResetEvent(0, mapId, difficulty, instanceId));
}
}
sLog.outDebug("InstanceSaveManager::AddInstanceSave: mapid = %d, instanceid = %d", mapId, instanceId);
- save = new InstanceSave(mapId, instanceId, difficulty, resetTime, canReset);
+ InstanceSave *save = new InstanceSave(mapId, instanceId, difficulty, resetTime, canReset);
if(!load) save->SaveToDB();
m_instanceSaveById[instanceId] = save;
@@ -141,7 +153,7 @@ void InstanceSaveManager::RemoveInstanceSave(uint32 InstanceId)
}
}
-InstanceSave::InstanceSave(uint16 MapId, uint32 InstanceId, uint8 difficulty, time_t resetTime, bool canReset)
+InstanceSave::InstanceSave(uint16 MapId, uint32 InstanceId, Difficulty difficulty, time_t resetTime, bool canReset)
: m_resetTime(resetTime), m_instanceid(InstanceId), m_mapid(MapId),
m_difficulty(difficulty), m_canReset(canReset)
{
@@ -180,7 +192,7 @@ time_t InstanceSave::GetResetTimeForDB()
{
// only save the reset time for normal instances
const MapEntry *entry = sMapStore.LookupEntry(GetMapId());
- if(!entry || entry->map_type == MAP_RAID || GetDifficulty() == DIFFICULTY_HEROIC)
+ if(!entry || entry->map_type == MAP_RAID || GetDifficulty() == DUNGEON_DIFFICULTY_HEROIC)
return 0;
else
return GetResetTime();
@@ -402,18 +414,26 @@ void InstanceSaveManager::LoadResetTimes()
// get the current reset times for normal instances (these may need to be updated)
// these are only kept in memory for InstanceSaves that are loaded later
// resettime = 0 in the DB for raid/heroic instances so those are skipped
- typedef std::map<uint32, std::pair<uint32, time_t> > ResetTimeMapType;
- ResetTimeMapType InstResetTime;
- QueryResult *result = CharacterDatabase.Query("SELECT id, map, resettime FROM instance WHERE resettime > 0");
+ typedef std::pair<uint32 /*PAIR32(map,difficulty)*/, time_t> ResetTimeMapDiffType;
+ typedef std::map<uint32, ResetTimeMapDiffType> InstResetTimeMapDiffType;
+ InstResetTimeMapDiffType instResetTime;
+
+ // index instance ids by map/difficulty pairs for fast reset warning send
+ typedef std::multimap<uint32 /*PAIR32(map,difficulty)*/, uint32 /*instanceid*/ > ResetTimeMapDiffInstances;
+ ResetTimeMapDiffInstances mapDiffResetInstances;
+
+ QueryResult *result = CharacterDatabase.Query("SELECT id, map, difficulty, resettime FROM instance WHERE resettime > 0");
if( result )
{
do
{
- if(time_t resettime = time_t((*result)[2].GetUInt64()))
+ if(time_t resettime = time_t((*result)[3].GetUInt64()))
{
uint32 id = (*result)[0].GetUInt32();
uint32 mapid = (*result)[1].GetUInt32();
- InstResetTime[id] = std::pair<uint32, uint64>(mapid, resettime);
+ uint32 difficulty = (*result)[2].GetUInt32();
+ instResetTime[id] = ResetTimeMapDiffType(MAKE_PAIR32(mapid,difficulty), resettime);
+ mapDiffResetInstances.insert(ResetTimeMapDiffInstances::value_type(MAKE_PAIR32(mapid,difficulty),id));
}
}
while (result->NextRow());
@@ -428,8 +448,8 @@ void InstanceSaveManager::LoadResetTimes()
Field *fields = result->Fetch();
uint32 instance = fields[1].GetUInt32();
time_t resettime = time_t(fields[0].GetUInt64() + 2 * HOUR);
- ResetTimeMapType::iterator itr = InstResetTime.find(instance);
- if(itr != InstResetTime.end() && itr->second.second != resettime)
+ InstResetTimeMapDiffType::iterator itr = instResetTime.find(instance);
+ if(itr != instResetTime.end() && itr->second.second != resettime)
{
CharacterDatabase.DirectPExecute("UPDATE instance SET resettime = '"UI64FMTD"' WHERE id = '%u'", uint64(resettime), instance);
itr->second.second = resettime;
@@ -440,62 +460,65 @@ void InstanceSaveManager::LoadResetTimes()
}
// schedule the reset times
- for (ResetTimeMapType::iterator itr = InstResetTime.begin(); itr != InstResetTime.end(); ++itr)
+ for(InstResetTimeMapDiffType::iterator itr = instResetTime.begin(); itr != instResetTime.end(); ++itr)
if(itr->second.second > now)
- ScheduleReset(true, itr->second.second, InstResetEvent(0, itr->second.first, itr->first));
+ ScheduleReset(true, itr->second.second, InstResetEvent(0, PAIR32_LOPART(itr->second.first),Difficulty(PAIR32_HIPART(itr->second.first)),itr->first));
}
// load the global respawn times for raid/heroic instances
uint32 diff = sWorld.getConfig(CONFIG_INSTANCE_RESET_TIME_HOUR) * HOUR;
- m_resetTimeByMapId.resize(sMapStore.GetNumRows()+1);
- result = CharacterDatabase.Query("SELECT mapid, resettime FROM instance_reset");
+ result = CharacterDatabase.Query("SELECT mapid, difficulty, resettime FROM instance_reset");
if(result)
{
do
{
Field *fields = result->Fetch();
uint32 mapid = fields[0].GetUInt32();
- if(!objmgr.GetInstanceTemplate(mapid))
+ Difficulty difficulty = Difficulty(fields[1].GetUInt32());
+ uint64 oldresettime = fields[2].GetUInt64();
+
+ MapDifficulty const* mapDiff = GetMapDifficultyData(mapid,difficulty);
+ if(!mapDiff)
{
- sLog.outError("InstanceSaveManager::LoadResetTimes: invalid mapid %u in instance_reset!", mapid);
- CharacterDatabase.DirectPExecute("DELETE FROM instance_reset WHERE mapid = '%u'", mapid);
+ sLog.outError("InstanceSaveManager::LoadResetTimes: invalid mapid(%u)/difficulty(%u) pair in instance_reset!", mapid, difficulty);
+ CharacterDatabase.DirectPExecute("DELETE FROM instance_reset WHERE mapid = '%u' AND difficulty = '%u'", mapid,difficulty);
continue;
}
// update the reset time if the hour in the configs changes
- uint64 oldresettime = fields[1].GetUInt64();
uint64 newresettime = (oldresettime / DAY) * DAY + diff;
if(oldresettime != newresettime)
- CharacterDatabase.DirectPExecute("UPDATE instance_reset SET resettime = '"UI64FMTD"' WHERE mapid = '%u'", newresettime, mapid);
+ CharacterDatabase.DirectPExecute("UPDATE instance_reset SET resettime = '"UI64FMTD"' WHERE mapid = '%u' AND difficulty = '%u'", newresettime, mapid, difficulty);
- m_resetTimeByMapId[mapid] = newresettime;
+ SetResetTimeFor(mapid,difficulty,newresettime);
} while(result->NextRow());
delete result;
}
// clean expired instances, references to them will be deleted in CleanupInstances
// must be done before calculating new reset times
- _DelHelper(CharacterDatabase, "id, map, difficulty", "instance", "LEFT JOIN instance_reset ON mapid = map WHERE (instance.resettime < '"UI64FMTD"' AND instance.resettime > '0') OR (NOT instance_reset.resettime IS NULL AND instance_reset.resettime < '"UI64FMTD"')", (uint64)now, (uint64)now);
+ _DelHelper(CharacterDatabase, "id, map, instance.difficulty", "instance", "LEFT JOIN instance_reset ON mapid = map AND instance.difficulty = instance_reset.difficulty WHERE (instance.resettime < '"UI64FMTD"' AND instance.resettime > '0') OR (NOT instance_reset.resettime IS NULL AND instance_reset.resettime < '"UI64FMTD"')", (uint64)now, (uint64)now);
// calculate new global reset times for expired instances and those that have never been reset yet
// add the global reset times to the priority queue
- for (uint32 i = 0; i < sInstanceTemplate.MaxEntry; i++)
+ for(MapDifficultyMap::const_iterator itr = sMapDifficultyMap.begin(); itr != sMapDifficultyMap.end(); ++itr)
{
- InstanceTemplate const* temp = objmgr.GetInstanceTemplate(i);
- if(!temp) continue;
- // only raid/heroic maps have a global reset time
- const MapEntry* entry = sMapStore.LookupEntry(temp->map);
- if(!entry || !entry->HasResetTime())
+ uint32 map_diff_pair = itr->first;
+ uint32 mapid = PAIR32_LOPART(map_diff_pair);
+ Difficulty difficulty = Difficulty(PAIR32_HIPART(map_diff_pair));
+ MapDifficulty const* mapDiff = &itr->second;
+ if (!mapDiff->resetTime)
continue;
- uint32 period = temp->reset_delay * DAY;
- assert(period != 0);
- time_t t = m_resetTimeByMapId[temp->map];
+ // the reset_delay must be at least one day
+ uint32 period = (mapDiff->resetTime / DAY * sWorld.getRate(RATE_INSTANCE_RESET_TIME)) * DAY;
+
+ time_t t = GetResetTimeFor(mapid,difficulty);
if(!t)
{
// initialize the reset time
t = today + period + diff;
- CharacterDatabase.DirectPExecute("INSERT INTO instance_reset VALUES ('%u','"UI64FMTD"')", i, (uint64)t);
+ CharacterDatabase.DirectPExecute("INSERT INTO instance_reset VALUES ('%u','%u','"UI64FMTD"')", mapid, difficulty, (uint64)t);
}
if(t < now)
@@ -504,17 +527,23 @@ void InstanceSaveManager::LoadResetTimes()
// calculate the next reset time
t = (t / DAY) * DAY;
t += ((today - t) / period + 1) * period + diff;
- CharacterDatabase.DirectPExecute("UPDATE instance_reset SET resettime = '"UI64FMTD"' WHERE mapid = '%u'", (uint64)t, i);
+ CharacterDatabase.DirectPExecute("UPDATE instance_reset SET resettime = '"UI64FMTD"' WHERE mapid = '%u' AND difficulty= '%u'", (uint64)t, mapid, difficulty);
}
- m_resetTimeByMapId[temp->map] = t;
+ SetResetTimeFor(mapid,difficulty,t);
// schedule the global reset/warning
uint8 type = 1;
static int tim[4] = {3600, 900, 300, 60};
for (; type < 4; type++)
- if(t - tim[type-1] > now) break;
- ScheduleReset(true, t - tim[type-1], InstResetEvent(type, i));
+ if(t - tim[type-1] > now)
+ break;
+
+ for(ResetTimeMapDiffInstances::const_iterator in_itr = mapDiffResetInstances.lower_bound(map_diff_pair);
+ in_itr != mapDiffResetInstances.upper_bound(map_diff_pair); ++in_itr)
+ {
+ ScheduleReset(true, t - tim[type-1], InstResetEvent(type, mapid, difficulty, in_itr->second));
+ }
}
}
@@ -555,8 +584,8 @@ void InstanceSaveManager::Update()
else
{
// global reset/warning for a certain map
- time_t resetTime = GetResetTimeFor(event.mapid);
- _ResetOrWarnAll(event.mapid, event.type != 4, resetTime - now);
+ time_t resetTime = GetResetTimeFor(event.mapid,event.difficulty);
+ _ResetOrWarnAll(event.mapid, event.difficulty, event.type != 4, resetTime - now);
if(event.type != 4)
{
// schedule the next warning/reset
@@ -607,29 +636,28 @@ void InstanceSaveManager::_ResetInstance(uint32 mapid, uint32 instanceId)
else objmgr.DeleteRespawnTimeForInstance(instanceId); // even if map is not loaded
}
-void InstanceSaveManager::_ResetOrWarnAll(uint32 mapid, bool warn, uint32 timeLeft)
+void InstanceSaveManager::_ResetOrWarnAll(uint32 mapid, Difficulty difficulty, bool warn, uint32 timeLeft)
{
// global reset for all instances of the given map
- // note: this isn't fast but it's meant to be executed very rarely
- Map const *map = MapManager::Instance().CreateBaseMap(mapid);
- if(!map->Instanceable())
+ MapEntry const *mapEntry = sMapStore.LookupEntry(mapid);
+ if (!mapEntry->Instanceable())
return;
+
uint64 now = (uint64)time(NULL);
if(!warn)
{
- // this is called one minute before the reset time
- InstanceTemplate const* temp = objmgr.GetInstanceTemplate(mapid);
- if(!temp || !temp->reset_delay)
+ MapDifficulty const* mapDiff = GetMapDifficultyData(mapid,difficulty);
+ if (!mapDiff || !mapDiff->resetTime)
{
- sLog.outError("InstanceSaveManager::ResetOrWarnAll: no instance template or reset delay for map %d", mapid);
+ sLog.outError("InstanceSaveManager::ResetOrWarnAll: not valid difficulty or no reset delay for map %d", mapid);
return;
}
// remove all binds to instances of the given map
for (InstanceSaveHashMap::iterator itr = m_instanceSaveById.begin(); itr != m_instanceSaveById.end();)
{
- if(itr->second->GetMapId() == mapid)
+ if (itr->second->GetMapId() == mapid && itr->second->GetDifficulty() == difficulty)
_ResetSave(itr);
else
++itr;
@@ -644,16 +672,14 @@ void InstanceSaveManager::_ResetOrWarnAll(uint32 mapid, bool warn, uint32 timeLe
// calculate the next reset time
uint32 diff = sWorld.getConfig(CONFIG_INSTANCE_RESET_TIME_HOUR) * HOUR;
- uint32 period = temp->reset_delay * DAY;
+ uint32 period = mapDiff->resetTime * DAY;
uint64 next_reset = ((now + timeLeft + MINUTE) / DAY * DAY) + period + diff;
// update it in the DB
- CharacterDatabase.PExecute("UPDATE instance_reset SET resettime = '"UI64FMTD"' WHERE mapid = '%d'", next_reset, mapid);
-
- // schedule next reset.
- m_resetTimeByMapId[mapid] = (time_t) next_reset;
- ScheduleReset(true, (time_t) (next_reset-3600), InstResetEvent(1, mapid));
+ CharacterDatabase.PExecute("UPDATE instance_reset SET resettime = '"UI64FMTD"' WHERE mapid = '%d' AND difficulty = '%d'", next_reset, mapid, difficulty);
}
+ // note: this isn't fast but it's meant to be executed very rarely
+ Map const *map = MapManager::Instance().CreateBaseMap(mapid); // _not_ include difficulty
MapInstanced::InstancedMaps &instMaps = ((MapInstanced*)map)->GetInstancedMaps();
MapInstanced::InstancedMaps::iterator mitr;
for (mitr = instMaps.begin(); mitr != instMaps.end(); ++mitr)
@@ -682,4 +708,3 @@ uint32 InstanceSaveManager::GetNumBoundGroupsTotal()
ret += itr->second->GetGroupCount();
return ret;
}
-
diff --git a/src/game/InstanceSaveMgr.h b/src/game/InstanceSaveMgr.h
index 29972210f3d..6d031af752d 100644
--- a/src/game/InstanceSaveMgr.h
+++ b/src/game/InstanceSaveMgr.h
@@ -29,6 +29,8 @@
#include <map>
#include "Utilities/UnorderedMap.h"
#include "Database/DatabaseEnv.h"
+#include "DBCEnums.h"
+#include "ObjectDefines.h"
struct InstanceTemplate;
struct MapEntry;
@@ -50,7 +52,7 @@ class InstanceSave
- any new instance is being generated
- the first time a player bound to InstanceId logs in
- when a group bound to the instance is loaded */
- InstanceSave(uint16 MapId, uint32 InstanceId, uint8 difficulty, time_t resetTime, bool canReset);
+ InstanceSave(uint16 MapId, uint32 InstanceId, Difficulty difficulty, time_t resetTime, bool canReset);
/* Unloaded when m_playerList and m_groupList become empty
or when the instance is reset */
@@ -95,7 +97,7 @@ class InstanceSave
/* currently it is possible to omit this information from this structure
but that would depend on a lot of things that can easily change in future */
- uint8 GetDifficulty() { return m_difficulty; }
+ Difficulty GetDifficulty() { return m_difficulty; }
typedef std::list<Player*> PlayerListType;
typedef std::list<Group*> GroupListType;
@@ -108,8 +110,8 @@ class InstanceSave
GroupListType m_groupList;
time_t m_resetTime;
uint32 m_instanceid;
- uint16 m_mapid;
- uint8 m_difficulty;
+ uint32 m_mapid;
+ Difficulty m_difficulty;
bool m_canReset;
};
@@ -120,33 +122,44 @@ class MANGOS_DLL_DECL InstanceSaveManager : public MaNGOS::Singleton<InstanceSav
InstanceSaveManager();
~InstanceSaveManager();
- typedef std::map<uint32 /*InstanceId*/, InstanceSave*> InstanceSaveMap;
typedef UNORDERED_MAP<uint32 /*InstanceId*/, InstanceSave*> InstanceSaveHashMap;
- typedef std::map<uint32 /*mapId*/, InstanceSaveMap> InstanceSaveMapMap;
+ typedef UNORDERED_MAP<uint32 /*mapId*/, InstanceSaveHashMap> InstanceSaveMapMap;
/* resetTime is a global propery of each (raid/heroic) map
all instances of that map reset at the same time */
struct InstResetEvent
{
uint8 type;
+ Difficulty difficulty:8;
uint16 mapid;
uint16 instanceId;
- InstResetEvent(uint8 t = 0, uint16 m = 0, uint16 i = 0) : type(t), mapid(m), instanceId(i) {}
+
+ InstResetEvent() : type(0), difficulty(DUNGEON_DIFFICULTY_NORMAL), mapid(0), instanceId(0) {}
+ InstResetEvent(uint8 t, uint32 _mapid, Difficulty d, uint16 _instanceid)
+ : type(t), difficulty(d), mapid(_mapid), instanceId(_instanceid) {}
bool operator == (const InstResetEvent& e) { return e.instanceId == instanceId; }
};
typedef std::multimap<time_t /*resetTime*/, InstResetEvent> ResetTimeQueue;
- typedef std::vector<time_t /*resetTime*/> ResetTimeVector;
+ typedef UNORDERED_MAP<uint32 /*PAIR32(map,difficulty)*/,time_t /*resetTime*/> ResetTimeByMapDifficultyMap;
void CleanupInstances();
void PackInstances();
void LoadResetTimes();
- time_t GetResetTimeFor(uint32 mapid) { return m_resetTimeByMapId[mapid]; }
+ time_t GetResetTimeFor(uint32 mapid, Difficulty d) const
+ {
+ ResetTimeByMapDifficultyMap::const_iterator itr = m_resetTimeByMapDifficulty.find(MAKE_PAIR32(mapid,d));
+ return itr != m_resetTimeByMapDifficulty.end() ? itr->second : 0;
+ }
+ void SetResetTimeFor(uint32 mapid, Difficulty d, time_t t)
+ {
+ m_resetTimeByMapDifficulty[MAKE_PAIR32(mapid,d)] = t;
+ }
void ScheduleReset(bool add, time_t time, InstResetEvent event);
void Update();
- InstanceSave* AddInstanceSave(uint32 mapId, uint32 instanceId, uint8 difficulty, time_t resetTime, bool canReset, bool load = false);
+ InstanceSave* AddInstanceSave(uint32 mapId, uint32 instanceId, Difficulty difficulty, time_t resetTime, bool canReset, bool load = false);
void RemoveInstanceSave(uint32 InstanceId);
static void DeleteInstanceFromDB(uint32 instanceid);
@@ -158,7 +171,7 @@ class MANGOS_DLL_DECL InstanceSaveManager : public MaNGOS::Singleton<InstanceSav
uint32 GetNumBoundGroupsTotal();
private:
- void _ResetOrWarnAll(uint32 mapid, bool warn, uint32 timeleft);
+ void _ResetOrWarnAll(uint32 mapid, Difficulty difficulty, bool warn, uint32 timeleft);
void _ResetInstance(uint32 mapid, uint32 instanceId);
void _ResetSave(InstanceSaveHashMap::iterator &itr);
void _DelHelper(DatabaseType &db, const char *fields, const char *table, const char *queryTail,...);
@@ -166,11 +179,10 @@ class MANGOS_DLL_DECL InstanceSaveManager : public MaNGOS::Singleton<InstanceSav
bool lock_instLists;
// fast lookup by instance id
InstanceSaveHashMap m_instanceSaveById;
- // fast lookup for reset times
- ResetTimeVector m_resetTimeByMapId;
+ // fast lookup for reset times (always use existed functions for access/set)
+ ResetTimeByMapDifficultyMap m_resetTimeByMapDifficulty;
ResetTimeQueue m_resetTimeQueue;
};
#define sInstanceSaveManager Trinity::Singleton<InstanceSaveManager>::Instance()
#endif
-
diff --git a/src/game/Item.cpp b/src/game/Item.cpp
index f26106cb452..05c1adec795 100644
--- a/src/game/Item.cpp
+++ b/src/game/Item.cpp
@@ -751,15 +751,15 @@ uint32 Item::GetEnchantRequiredLevel() const
for (uint32 enchant_slot = PERM_ENCHANTMENT_SLOT; enchant_slot < MAX_ENCHANTMENT_SLOT; ++enchant_slot)
if (uint32 enchant_id = GetEnchantmentId(EnchantmentSlot(enchant_slot)))
if (SpellItemEnchantmentEntry const* enchantEntry = sSpellItemEnchantmentStore.LookupEntry(enchant_id))
- if (enchantEntry->RequiredLevel > level)
- level = enchantEntry->RequiredLevel;
+ if (enchantEntry->requiredLevel > level)
+ level = enchantEntry->requiredLevel;
return level;
}
bool Item::IsBoundByEnchant() const
{
// Check all enchants for soulbound
- for (uint32 enchant_slot = PERM_ENCHANTMENT_SLOT; enchant_slot < MAX_ENCHANTMENT_SLOT; ++enchant_slot)
+ for (uint32 enchant_slot = PERM_ENCHANTMENT_SLOT; enchant_slot < MAX_ENCHANTMENT_SLOT; ++enchant_slot)
if (uint32 enchant_id = GetEnchantmentId(EnchantmentSlot(enchant_slot)))
if (SpellItemEnchantmentEntry const* enchantEntry = sSpellItemEnchantmentStore.LookupEntry(enchant_id))
if (enchantEntry->slot & ENCHANTMENT_CAN_SOULBOUND)
diff --git a/src/game/Item.h b/src/game/Item.h
index a26b9148f21..710e0a56d57 100644
--- a/src/game/Item.h
+++ b/src/game/Item.h
@@ -319,6 +319,21 @@ class TRINITY_DLL_SPEC Item : public Object
bool IsWeaponVellum() const { return GetProto()->IsWeaponVellum(); }
bool IsArmorVellum() const { return GetProto()->IsArmorVellum(); }
bool IsConjuredConsumable() const { return GetProto()->IsConjuredConsumable(); }
+
+ // Item Refund system
+ uint32 GetPaidHonorPoints() { return m_paidHonorPoints; }
+ uint32 GetPaidArenaPoints() { return m_paidArenaPoints; }
+ uint32 GetPaidExtendedCostId(uint32 pos) { return m_paidExtendedCostId[pos]; }
+ uint32 GetPaidExtendedCostCount(uint32 pos) { return m_paidExtendedCostCount[pos]; }
+ uint32 GetRefundExpiryTime() { return GetUInt32Value(ITEM_FIELD_CREATE_PLAYED_TIME); }
+ void SetRefundExpiryTime(uint32 timeval) { SetUInt32Value(ITEM_FIELD_CREATE_PLAYED_TIME, timeval); }
+ void SetPaidHonorPoints(uint32 value) { m_paidHonorPoints = value; }
+ void SetPaidArenaPoints(uint32 value) { m_paidArenaPoints = value; }
+ void SetPaidExtendedCost(uint32 pos, uint32 entry, uint32 count)
+ {
+ m_paidExtendedCostId[pos] = entry;
+ m_paidExtendedCostCount[pos] = count;
+ }
private:
uint8 m_slot;
@@ -326,6 +341,11 @@ class TRINITY_DLL_SPEC Item : public Object
ItemUpdateState uState;
int16 uQueuePos;
bool mb_in_trade; // true if item is currently in trade-window
+
+ // refund system
+ uint32 m_paidHonorPoints;
+ uint32 m_paidArenaPoints;
+ uint32 m_paidExtendedCostId[5];
+ uint32 m_paidExtendedCostCount[5];
};
#endif
-
diff --git a/src/game/ItemHandler.cpp b/src/game/ItemHandler.cpp
index ad9b1a7de4b..b4b22fe90cc 100644
--- a/src/game/ItemHandler.cpp
+++ b/src/game/ItemHandler.cpp
@@ -67,7 +67,7 @@ void WorldSession::HandleSwapInvItemOpcode( WorldPacket & recv_data )
//sLog.outDebug("WORLD: CMSG_SWAP_INV_ITEM");
uint8 srcslot, dstslot;
- recv_data >> srcslot >> dstslot;
+ recv_data >> dstslot >> srcslot;
//sLog.outDebug("STORAGE: receive srcslot = %u, dstslot = %u", srcslot, dstslot);
// prevent attempt swap same item to current position generated by client at special checting sequence
@@ -319,6 +319,7 @@ void WorldSession::HandleItemQuerySingleOpcode( WorldPacket & recv_data )
data << pProto->DisplayInfoID;
data << pProto->Quality;
data << pProto->Flags;
+ data << pProto->Faction; // 3.2 faction?
data << pProto->BuyPrice;
data << pProto->SellPrice;
data << pProto->InventoryType;
@@ -947,10 +948,10 @@ void WorldSession::HandleSetAmmoOpcode(WorldPacket & recv_data)
void WorldSession::SendEnchantmentLog(uint64 Target, uint64 Caster,uint32 ItemID,uint32 SpellID)
{
WorldPacket data(SMSG_ENCHANTMENTLOG, (8+8+4+4+1)); // last check 2.0.10
- data << Target;
- data << Caster;
- data << ItemID;
- data << SpellID;
+ data << uint64(Target);
+ data << uint64(Caster);
+ data << uint32(ItemID);
+ data << uint32(SpellID);
data << uint8(0);
SendPacket(&data);
}
@@ -1336,3 +1337,112 @@ void WorldSession::HandleCancelTempEnchantmentOpcode(WorldPacket& recv_data)
item->ClearEnchantment(TEMP_ENCHANTMENT_SLOT);
}
+void WorldSession::HandleItemRefundInfoRequest(WorldPacket& recv_data)
+{
+ sLog.outDebug("WORLD: CMSG_ITEM_REFUND_INFO_REQUEST");
+
+ uint64 guid;
+
+ recv_data >> guid; // item guid
+
+ Item *item = _player->GetItemByGuid(guid);
+
+ if(!item)
+ {
+ sLog.outDebug("Item refund: item not found!");
+ return;
+ }
+
+ if(!item->HasFlag(ITEM_FIELD_FLAGS, ITEM_FLAGS_REFUNDABLE))
+ {
+ sLog.outDebug("Item refund: item not refundable!");
+ return;
+ }
+
+ // item refund system not implemented yet
+ WorldPacket data(SMSG_ITEM_REFUND_TIMER, 8+4+4+4+4*4+4*4+4+4); // guess size
+ data << uint64(guid); // item guid
+ data << uint32(1); // unknown
+ data << uint32(item->GetPaidHonorPoints()); // honor point cost
+ data << uint32(item->GetPaidArenaPoints()); // arena point cost
+ for(uint32 i = 0; i < 5; ++i) // extended cost data
+ {
+ data << uint32(item->GetPaidExtendedCostId(i));
+ data << uint32(item->GetPaidExtendedCostCount(i));
+ }
+ data << uint32(0);
+ data << uint32(0);
+ SendPacket(&data);
+}
+
+void WorldSession::HandleItemRefund(WorldPacket &recv_data)
+{
+ sLog.outDebug("WORLD: CMSG_ITEM_REFUND");
+ uint64 guid;
+ recv_data >> guid; // item guid
+
+ Item *item = _player->GetItemByGuid(guid);
+ if(!item)
+ {
+ sLog.outDebug("Item refund: item not found!");
+ return;
+ }
+
+ if(!item->HasFlag(ITEM_FIELD_FLAGS, ITEM_FLAGS_REFUNDABLE))
+ {
+ sLog.outDebug("Item refund: item not refundable!");
+ return;
+ }
+
+ if(item->GetRefundExpiryTime() <= time(NULL)) // item refund has expired
+ {
+ WorldPacket data(SMSG_ITEM_REFUND);
+ data << uint64(guid); // guid
+ data << uint32(1); // error, abort refund
+ return;
+ }
+
+ WorldPacket data(SMSG_ITEM_REFUND);
+ data << uint64(guid); // guid?
+ data << uint32(0); // must be 0 or client side error in refund
+ data << uint32(0); // unk - message sent to client?
+ data << uint32(item->GetPaidHonorPoints()); // honor points refund
+ data << uint32(item->GetPaidArenaPoints()); // arena points refund
+ for(uint32 i = 0; i < 5; ++i) // extended cost?
+ {
+ data << uint32(item->GetPaidExtendedCostId(i));
+ data << uint32(item->GetPaidExtendedCostCount(i));
+ }
+ SendPacket(&data);
+
+ // Grant back extendedcost items
+ uint32 count = 0;
+ uint32 itemid = 0;
+ for(uint32 i = 0; i < 5; ++i)
+ {
+ count = item->GetPaidExtendedCostCount(i);
+ itemid = item->GetPaidExtendedCostId(i);
+ if (count && itemid)
+ {
+ ItemPosCountVec dest;
+ uint8 msg = _player->CanStoreNewItem(NULL_BAG, NULL_SLOT, dest, itemid, count);
+ if (msg == EQUIP_ERR_OK)
+ {
+ Item* it = _player->StoreNewItem(dest, itemid, true);
+ _player->SendNewItem(it, count, true, false, true);
+ }
+
+ // What to do if there's no space?
+ }
+ }
+ // Grant back Honor points
+ if (uint32 honorRefund = item->GetPaidHonorPoints() > 0)
+ _player->ModifyHonorPoints(honorRefund);
+
+ // Grant back Arena points
+ if (uint32 arenaRefund = item->GetPaidArenaPoints() > 0)
+ _player->ModifyArenaPoints(arenaRefund);
+
+ // Destroy item
+ _player->DestroyItemCount(item->GetEntry(), 1, true, true);
+}
diff --git a/src/game/ItemPrototype.h b/src/game/ItemPrototype.h
index a6daf47cb48..4a2ab112538 100644
--- a/src/game/ItemPrototype.h
+++ b/src/game/ItemPrototype.h
@@ -65,10 +65,13 @@ enum ItemModType
ITEM_MOD_SPELL_DAMAGE_DONE = 42, // deprecated
ITEM_MOD_MANA_REGENERATION = 43,
ITEM_MOD_ARMOR_PENETRATION_RATING = 44,
- ITEM_MOD_SPELL_POWER = 45
+ ITEM_MOD_SPELL_POWER = 45,
+ ITEM_MOD_HEALTH_REGEN = 46,
+ ITEM_MOD_SPELL_PENETRATION = 47,
+ ITEM_MOD_BLOCK_VALUE = 48
};
-#define MAX_ITEM_MOD 46
+#define MAX_ITEM_MOD 49
enum ItemSpelltriggerType
{
@@ -108,9 +111,13 @@ enum ITEM_FLAGS
ITEM_FLAGS_OPENABLE = 0x00000004,
ITEM_FLAGS_WRAPPED = 0x00000008,
ITEM_FLAGS_BROKEN = 0x00000010, // appears red icon (like when item durability==0)
+ ITEM_FLAGS_TOTEM = 0x00000020, // ?
+ ITEM_FLAGS_USABLE = 0x00000040, // ?
ITEM_FLAGS_WRAPPER = 0x00000200, // used or not used wrapper
ITEM_FLAGS_PARTY_LOOT = 0x00000800, // determines if item is party loot or not
+ ITEM_FLAGS_REFUNDABLE = 0x00001000, // item cost can be refunded within 2 hours after purchase
ITEM_FLAGS_CHARTER = 0x00002000, // arena/guild charter
+ ITEM_FLAGS_REFUNDABLE_2 = 0x00008000,
ITEM_FLAGS_PROSPECTABLE = 0x00040000,
ITEM_FLAGS_UNIQUE_EQUIPPED = 0x00080000,
ITEM_FLAGS_USEABLE_IN_ARENA = 0x00200000,
@@ -118,7 +125,9 @@ enum ITEM_FLAGS
ITEM_FLAGS_SPECIALUSE = 0x00800000, // last used flag in 2.3.0
ITEM_FLAGS_BOA = 0x08000000, // bind on account (set in template for items that can binded in like way)
ITEM_FLAGS_TRIGGERED_CAST = 0x10000000, // used by enchanting scrolls made with vellum
- ITEM_FLAGS_MILLABLE = 0x20000000
+ ITEM_FLAGS_ENCHANT_SCROLL = 0x10000000, // for enchant scrolls
+ ITEM_FLAGS_MILLABLE = 0x20000000,
+ ITEM_FLAGS_BOP_TRADEABLE = 0x80000000
};
enum BAG_FAMILY_MASK
@@ -515,6 +524,7 @@ struct ItemPrototype
uint32 DisplayInfoID; // id from ItemDisplayInfo.dbc
uint32 Quality;
uint32 Flags;
+ uint32 Faction;
uint32 BuyCount;
uint32 BuyPrice;
uint32 SellPrice;
@@ -649,4 +659,3 @@ struct ItemLocale
#pragma pack(pop)
#endif
#endif
-
diff --git a/src/game/Level1.cpp b/src/game/Level1.cpp
index 4ae90ebdcc3..bb99299e060 100644
--- a/src/game/Level1.cpp
+++ b/src/game/Level1.cpp
@@ -827,7 +827,7 @@ bool ChatHandler::HandleNamegoCommand(const char* args)
Map* cMap = target->GetMap();
if (cMap->Instanceable() && cMap->GetInstanceId() != pMap->GetInstanceId())
{
- target->UnbindInstance(pMap->GetInstanceId(), target->GetDifficulty(), true);
+ target->UnbindInstance(pMap->GetInstanceId(), target->GetDungeonDifficulty(), true);
// cannot summon from instance to instance
//PSendSysMessage(LANG_CANNOT_SUMMON_TO_INST,nameLink.c_str());
//SetSentErrorMessage(true);
@@ -968,24 +968,26 @@ bool ChatHandler::HandleGonameCommand(const char* args)
// if the player or the player's group is bound to another instance
// the player will not be bound to another one
- InstancePlayerBind *pBind = _player->GetBoundInstance(target->GetMapId(), target->GetDifficulty());
+ InstancePlayerBind *pBind = _player->GetBoundInstance(target->GetMapId(), target->GetDifficulty(cMap->IsRaid()));
if (!pBind)
{
Group *group = _player->GetGroup();
// if no bind exists, create a solo bind
- InstanceGroupBind *gBind = group ? group->GetBoundInstance(target->GetMapId(), target->GetDifficulty()) : NULL;
- // if no bind exists, create a solo bind
+ InstanceGroupBind *gBind = group ? group->GetBoundInstance(target) : NULL; // if no bind exists, create a solo bind
if (!gBind)
if (InstanceSave *save = sInstanceSaveManager.GetInstanceSave(target->GetInstanceId()))
_player->BindToInstance(save, !save->CanReset());
}
- _player->SetDifficulty(target->GetDifficulty());
+ if(cMap->IsRaid())
+ _player->SetRaidDifficulty(target->GetRaidDifficulty());
+ else
+ _player->SetDungeonDifficulty(target->GetDungeonDifficulty());
}
PSendSysMessage(LANG_APPEARING_AT, chrNameLink.c_str());
- if (needReportToTarget(target))
- ChatHandler(target).PSendSysMessage(LANG_APPEARING_TO, GetNameLink().c_str());
+ //if (needReportToTarget(target))
+ // ChatHandler(target).PSendSysMessage(LANG_APPEARING_TO, GetNameLink().c_str());
// stop flight if need
if (_player->isInFlight())
diff --git a/src/game/Level2.cpp b/src/game/Level2.cpp
index 3c2a7bf8f1d..f22a3dedfbb 100644
--- a/src/game/Level2.cpp
+++ b/src/game/Level2.cpp
@@ -4361,6 +4361,7 @@ bool ChatHandler::HandleWintergraspTimerCommand(const char* args)
time *= MINUTE * IN_MILISECONDS;
pvpWG->setTimer((uint32)time);
+
PSendSysMessage(LANG_BG_WG_CHANGE_TIMER, secsToTimeString(pvpWG->GetTimer(), true).c_str());
return true;
}
diff --git a/src/game/Level3.cpp b/src/game/Level3.cpp
index a095be0a531..e4adb4c6550 100644
--- a/src/game/Level3.cpp
+++ b/src/game/Level3.cpp
@@ -54,6 +54,7 @@
#include "InstanceData.h"
#include "AuctionHouseBot.h"
#include "CreatureEventAIMgr.h"
+#include "DBCEnums.h"
bool ChatHandler::HandleAHBotOptionsCommand(const char *args)
{
@@ -3108,9 +3109,7 @@ bool ChatHandler::HandleGameObjectStateCommand(const char *args)
gobj->SendObjectDeSpawnAnim(gobj->GetGUID());
else if(type == -2)
{
- WorldPacket data(SMSG_GAMEOBJECT_SPAWN_ANIM_OBSOLETE, 8);
- data << gobj->GetGUID();
- gobj->SendMessageToSet(&data,true);
+ return false;
}
return true;
}
@@ -3933,7 +3932,7 @@ bool ChatHandler::HandleLookupMapCommand(const char *args)
if(!*args)
return false;
- std::string namepart = args;
+ /*std::string namepart = args;
std::wstring wnamepart;
// converting string that we try to find to lower case
@@ -4000,6 +3999,7 @@ bool ChatHandler::HandleLookupMapCommand(const char *args)
ss << GetTrinityString(LANG_HEROIC);
uint32 ResetTimeRaid = MapInfo->resetTimeRaid;
+
std::string ResetTimeRaidStr;
if(ResetTimeRaid)
ResetTimeRaidStr = secsToTimeString(ResetTimeRaid, true, false);
@@ -4029,7 +4029,7 @@ bool ChatHandler::HandleLookupMapCommand(const char *args)
if(!found)
SendSysMessage(LANG_COMMAND_NOMAPFOUND);
-
+ */
return true;
}
@@ -5410,6 +5410,14 @@ bool ChatHandler::HandleServerShutDownCommand(const char *args)
char* time_str = strtok ((char*) args, " ");
char* exitcode_str = strtok (NULL, "");
+ char* tailStr = *args!='"' ? strtok(NULL, "") : (char*)args;
+ if(!tailStr)
+ return false;
+
+ char* reason = extractQuotedArg(tailStr);
+ if(!reason)
+ return false;
+
int32 time = atoi (time_str);
///- Prevent interpret wrong arg value as 0 secs shutdown time
@@ -5675,7 +5683,7 @@ bool ChatHandler::HandleQuestComplete(const char *args)
}
// Add quest items for quests that require items
- for (uint8 x = 0; x < QUEST_OBJECTIVES_COUNT; ++x)
+ for (uint8 x = 0; x < QUEST_ITEM_OBJECTIVES_COUNT; ++x)
{
uint32 id = pQuest->ReqItemId[x];
uint32 count = pQuest->ReqItemCount[x];
@@ -6800,14 +6808,14 @@ bool ChatHandler::HandleInstanceListBindsCommand(const char* /*args*/)
Player* player = getSelectedPlayer();
if (!player) player = m_session->GetPlayer();
uint32 counter = 0;
- for (uint8 i = 0; i < TOTAL_DIFFICULTIES; ++i)
+ for (uint8 i = 0; i < MAX_DIFFICULTY; ++i)
{
- Player::BoundInstancesMap &binds = player->GetBoundInstances(i);
+ Player::BoundInstancesMap &binds = player->GetBoundInstances(Difficulty(i));
for (Player::BoundInstancesMap::const_iterator itr = binds.begin(); itr != binds.end(); ++itr)
{
InstanceSave *save = itr->second.save;
std::string timeleft = GetTimeString(save->GetResetTime() - time(NULL));
- PSendSysMessage("map: %d inst: %d perm: %s diff: %s canReset: %s TTR: %s", itr->first, save->GetInstanceId(), itr->second.perm ? "yes" : "no", save->GetDifficulty() == DIFFICULTY_NORMAL ? "normal" : "heroic", save->CanReset() ? "yes" : "no", timeleft.c_str());
+ PSendSysMessage("map: %d inst: %d perm: %s diff: %d canReset: %s TTR: %s", itr->first, save->GetInstanceId(), itr->second.perm ? "yes" : "no", save->GetDifficulty(), save->CanReset() ? "yes" : "no", timeleft.c_str());
counter++;
}
}
@@ -6816,15 +6824,14 @@ bool ChatHandler::HandleInstanceListBindsCommand(const char* /*args*/)
Group *group = player->GetGroup();
if(group)
{
- for (uint8 i = 0; i < TOTAL_DIFFICULTIES; ++i)
+ for (uint8 i = 0; i < MAX_DIFFICULTY; ++i)
{
- Group::BoundInstancesMap &binds = group->GetBoundInstances(i);
+ Group::BoundInstancesMap &binds = group->GetBoundInstances(Difficulty(i));
for (Group::BoundInstancesMap::const_iterator itr = binds.begin(); itr != binds.end(); ++itr)
{
InstanceSave *save = itr->second.save;
std::string timeleft = GetTimeString(save->GetResetTime() - time(NULL));
- PSendSysMessage("map: %d inst: %d perm: %s diff: %s canReset: %s TTR: %s", itr->first, save->GetInstanceId(), itr->second.perm ? "yes" : "no", save->GetDifficulty() == DIFFICULTY_NORMAL ? "normal" : "heroic", save->CanReset() ? "yes" : "no", timeleft.c_str());
- counter++;
+ PSendSysMessage("map: %d inst: %d perm: %s diff: %d canReset: %s TTR: %s", itr->first, save->GetInstanceId(), itr->second.perm ? "yes" : "no", save->GetDifficulty(), save->CanReset() ? "yes" : "no", timeleft.c_str()); counter++;
}
}
}
@@ -6844,17 +6851,17 @@ bool ChatHandler::HandleInstanceUnbindCommand(const char *args)
Player* player = getSelectedPlayer();
if (!player) player = m_session->GetPlayer();
uint32 counter = 0;
- for (uint8 i = 0; i < TOTAL_DIFFICULTIES; ++i)
+ for (uint8 i = 0; i < MAX_DIFFICULTY; ++i)
{
- Player::BoundInstancesMap &binds = player->GetBoundInstances(i);
+ Player::BoundInstancesMap &binds = player->GetBoundInstances(Difficulty(i));
for (Player::BoundInstancesMap::iterator itr = binds.begin(); itr != binds.end();)
{
if(itr->first != player->GetMapId())
{
InstanceSave *save = itr->second.save;
std::string timeleft = GetTimeString(save->GetResetTime() - time(NULL));
- PSendSysMessage("unbinding map: %d inst: %d perm: %s diff: %s canReset: %s TTR: %s", itr->first, save->GetInstanceId(), itr->second.perm ? "yes" : "no", save->GetDifficulty() == DIFFICULTY_NORMAL ? "normal" : "heroic", save->CanReset() ? "yes" : "no", timeleft.c_str());
- player->UnbindInstance(itr, i);
+ PSendSysMessage("unbinding map: %d inst: %d perm: %s diff: %d canReset: %s TTR: %s", itr->first, save->GetInstanceId(), itr->second.perm ? "yes" : "no", save->GetDifficulty(), save->CanReset() ? "yes" : "no", timeleft.c_str());
+ player->UnbindInstance(itr, Difficulty(i));
counter++;
}
else
@@ -7537,4 +7544,3 @@ bool ChatHandler::HandleUnbindSightCommand(const char *args)
m_session->GetPlayer()->StopCastingBindSight();
return true;
}
-
diff --git a/src/game/LootHandler.cpp b/src/game/LootHandler.cpp
index de464cf050e..74b9730691f 100644
--- a/src/game/LootHandler.cpp
+++ b/src/game/LootHandler.cpp
@@ -222,7 +222,7 @@ void WorldSession::HandleLootMoneyOpcode( WorldPacket & /*recv_data*/ )
Player* playerGroup = itr->getSource();
if(!playerGroup)
continue;
- if (player->IsWithinDist(playerGroup,sWorld.getConfig(CONFIG_GROUP_XP_DISTANCE),false))
+ if (player->IsWithinDistInMap(playerGroup,sWorld.getConfig(CONFIG_GROUP_XP_DISTANCE),false))
playersNear.push_back(playerGroup);
}
diff --git a/src/game/LootMgr.cpp b/src/game/LootMgr.cpp
index 2cfd92f11fc..809df7e9e51 100644
--- a/src/game/LootMgr.cpp
+++ b/src/game/LootMgr.cpp
@@ -1449,4 +1449,3 @@ void LoadLootTemplates_Reference()
// output error for any still listed ids (not referenced from any loot table)
LootTemplates_Reference.ReportUnusedIds(ids_set);
}
-
diff --git a/src/game/LootMgr.h b/src/game/LootMgr.h
index bcd9b564904..84532ece197 100644
--- a/src/game/LootMgr.h
+++ b/src/game/LootMgr.h
@@ -33,7 +33,8 @@ enum RollType
{
ROLL_PASS = 0,
ROLL_NEED = 1,
- ROLL_GREED = 2
+ ROLL_GREED = 2,
+ MAX_ROLL_TYPE = 3
};
#define MAX_NR_LOOT_ITEMS 16
@@ -365,4 +366,3 @@ inline void LoadLootTables()
}
#endif
-
diff --git a/src/game/Map.cpp b/src/game/Map.cpp
index a34ce673d9a..5a72c6ed8f0 100644
--- a/src/game/Map.cpp
+++ b/src/game/Map.cpp
@@ -38,6 +38,7 @@
#include "MapRefManager.h"
#include "Vehicle.h"
#include "WaypointManager.h"
+#include "DBCEnums.h"
#include "MapInstanced.h"
#include "InstanceSaveMgr.h"
@@ -217,12 +218,12 @@ Map::Map(uint32 id, time_t expiry, uint32 InstanceId, uint8 SpawnMode, Map* _par
{
m_notifyTimer.SetInterval(IN_MILISECONDS/2);
- for (uint8 idx = 0; idx < MAX_NUMBER_OF_GRIDS; ++idx)
+ for (unsigned int idx=0; idx < MAX_NUMBER_OF_GRIDS; ++idx)
{
- for (uint8 j = 0; j < MAX_NUMBER_OF_GRIDS; ++j)
+ for (unsigned int j=0; j < MAX_NUMBER_OF_GRIDS; ++j)
{
//z code
- GridMaps[idx][j] = NULL;
+ GridMaps[idx][j] =NULL;
setNGrid(NULL, idx, j);
}
}
@@ -2384,6 +2385,7 @@ void Map::RemoveAllObjectsInRemoveList()
i_objectsToRemove.erase(itr);
}
+
//sLog.outDebug("Object remover 2 check.");
}
@@ -2584,11 +2586,11 @@ bool InstanceMap::Add(Player *player)
if(!mapSave)
{
sLog.outDetail("InstanceMap::Add: creating instance save for map %d spawnmode %d with instance id %d", GetId(), GetSpawnMode(), GetInstanceId());
- mapSave = sInstanceSaveManager.AddInstanceSave(GetId(), GetInstanceId(), GetSpawnMode(), 0, true);
+ mapSave = sInstanceSaveManager.AddInstanceSave(GetId(), GetInstanceId(), Difficulty(GetSpawnMode()), 0, true);
}
// check for existing instance binds
- InstancePlayerBind *playerBind = player->GetBoundInstance(GetId(), GetSpawnMode());
+ InstancePlayerBind *playerBind = player->GetBoundInstance(GetId(), Difficulty(GetSpawnMode()));
if(playerBind && playerBind->perm)
{
// cannot enter other instances if bound permanently
@@ -2604,7 +2606,7 @@ bool InstanceMap::Add(Player *player)
if(pGroup)
{
// solo saves should be reset when entering a group
- InstanceGroupBind *groupBind = pGroup->GetBoundInstance(GetId(), GetSpawnMode());
+ InstanceGroupBind *groupBind = pGroup->GetBoundInstance(this);
if(playerBind)
{
sLog.outError("InstanceMap::Add: player %s(%d) is being put in instance %d,%d,%d,%d,%d,%d but he is in group %d and is bound to instance %d,%d,%d,%d,%d,%d!", player->GetName(), player->GetGUIDLow(), mapSave->GetMapId(), mapSave->GetInstanceId(), mapSave->GetDifficulty(), mapSave->GetPlayerCount(), mapSave->GetGroupCount(), mapSave->CanReset(), GUID_LOPART(pGroup->GetLeaderGUID()), playerBind->save->GetMapId(), playerBind->save->GetInstanceId(), playerBind->save->GetDifficulty(), playerBind->save->GetPlayerCount(), playerBind->save->GetGroupCount(), playerBind->save->CanReset());
@@ -2811,7 +2813,7 @@ void InstanceMap::UnloadAll()
void InstanceMap::SendResetWarnings(uint32 timeLeft) const
{
for (MapRefManager::const_iterator itr = m_mapRefManager.begin(); itr != m_mapRefManager.end(); ++itr)
- itr->getSource()->SendInstanceResetWarning(GetId(), itr->getSource()->GetDifficulty(), timeLeft);
+ itr->getSource()->SendInstanceResetWarning(GetId(), itr->getSource()->GetDifficulty(IsRaid()), timeLeft);
}
void InstanceMap::SetResetSchedule(bool on)
@@ -2819,26 +2821,45 @@ void InstanceMap::SetResetSchedule(bool on)
// only for normal instances
// the reset time is only scheduled when there are no payers inside
// it is assumed that the reset time will rarely (if ever) change while the reset is scheduled
- if (IsDungeon() && !HavePlayers() && !IsRaid() && !IsHeroic())
+ if(IsDungeon() && !HavePlayers() && !IsRaidOrHeroicDungeon())
{
InstanceSave *save = sInstanceSaveManager.GetInstanceSave(GetInstanceId());
if (!save) sLog.outError("InstanceMap::SetResetSchedule: cannot turn schedule %s, no save available for instance %d of %d", on ? "on" : "off", GetInstanceId(), GetId());
- else sInstanceSaveManager.ScheduleReset(on, save->GetResetTime(), InstanceSaveManager::InstResetEvent(0, GetId(), GetInstanceId()));
+ else sInstanceSaveManager.ScheduleReset(on, save->GetResetTime(), InstanceSaveManager::InstResetEvent(0, GetId(), Difficulty(GetSpawnMode()), GetInstanceId()));
}
}
+MapDifficulty const* InstanceMap::GetMapDifficulty() const
+{
+ return GetMapDifficultyData(GetId(),GetDifficulty());
+}
+
uint32 InstanceMap::GetMaxPlayers() const
{
- InstanceTemplate const* iTemplate = objmgr.GetInstanceTemplate(GetId());
- if (!iTemplate)
+ if(MapDifficulty const* mapDiff = GetMapDifficulty())
+ {
+ if(mapDiff->maxPlayers || IsRegularDifficulty()) // Normal case (expect that regular difficulty always have correct maxplayers)
+ return mapDiff->maxPlayers;
+ else // DBC have 0 maxplayers for heroic instances with expansion < 2
+ { // The heroic entry exists, so we don't have to check anything, simply return normal max players
+ MapDifficulty const* normalDiff = GetMapDifficultyData(GetId(), REGULAR_DIFFICULTY);
+ return normalDiff ? normalDiff->maxPlayers : 0;
+ }
+ }
+ else // I'd rather assert(false);
return 0;
- return IsHeroic() ? iTemplate->maxPlayersHeroic : iTemplate->maxPlayers;
+}
+
+uint32 InstanceMap::GetMaxResetDelay() const
+{
+ MapDifficulty const* mapDiff = GetMapDifficulty();
+ return mapDiff ? mapDiff->resetTime : 0;
}
/* ******* Battleground Instance Maps ******* */
-BattleGroundMap::BattleGroundMap(uint32 id, time_t expiry, uint32 InstanceId, Map* _parent)
- : Map(id, expiry, InstanceId, DIFFICULTY_NORMAL, _parent)
+BattleGroundMap::BattleGroundMap(uint32 id, time_t expiry, uint32 InstanceId, Map* _parent, uint8 spawnMode)
+ : Map(id, expiry, InstanceId, spawnMode, _parent)
{
//lets initialize visibility distance for BG/Arenas
BattleGroundMap::InitVisibilityDistance();
@@ -3789,4 +3810,3 @@ void Map::UpdateIteratorBack(Player *player)
if(m_mapRefIter == player->GetMapRef())
m_mapRefIter = m_mapRefIter->nocheck_prev();
}
-
diff --git a/src/game/Map.h b/src/game/Map.h
index fa4e7a03468..981a48bbbb6 100644
--- a/src/game/Map.h
+++ b/src/game/Map.h
@@ -51,6 +51,7 @@ class CreatureGroup;
struct ScriptInfo;
struct ScriptAction;
struct Position;
+class BattleGround;
typedef ACE_RW_Thread_Mutex GridRWLock;
@@ -229,9 +230,6 @@ struct InstanceTemplate
{
uint32 map;
uint32 parent;
- uint32 maxPlayers;
- uint32 maxPlayersHeroic;
- uint32 reset_delay; // FIX ME: now exist normal/heroic raids with possible different time of reset.
uint32 access_id;
float startLocX;
float startLocY;
@@ -383,7 +381,8 @@ class MANGOS_DLL_SPEC Map : public GridRefManager<NGridType>, public MaNGOS::Obj
// NOTE: this duplicate of Instanceable(), but Instanceable() can be changed when BG also will be instanceable
bool IsDungeon() const { return i_mapEntry && i_mapEntry->IsDungeon(); }
bool IsRaid() const { return i_mapEntry && i_mapEntry->IsRaid(); }
- bool IsHeroic() const { return i_spawnMode == DIFFICULTY_HEROIC; }
+ bool IsRaidOrHeroicDungeon() const { return IsRaid() || i_spawnMode > DUNGEON_DIFFICULTY_NORMAL; }
+ bool IsHeroic() const { return IsRaid() ? i_spawnMode >= RAID_DIFFICULTY_10MAN_HEROIC : i_spawnMode >= DUNGEON_DIFFICULTY_HEROIC; }
bool IsBattleGround() const { return i_mapEntry && i_mapEntry->IsBattleGround(); }
bool IsBattleArena() const { return i_mapEntry && i_mapEntry->IsBattleArena(); }
bool IsBattleGroundOrArena() const { return i_mapEntry && i_mapEntry->IsBattleGroundOrArena(); }
@@ -610,7 +609,13 @@ class TRINITY_DLL_SPEC InstanceMap : public Map
bool CanEnter(Player* player);
void SendResetWarnings(uint32 timeLeft) const;
void SetResetSchedule(bool on);
+
+ // have meaning only for instanced map (that have set real difficulty)
+ Difficulty GetDifficulty() const { return Difficulty(GetSpawnMode()); }
+ bool IsRegularDifficulty() const { return GetDifficulty() == REGULAR_DIFFICULTY; }
uint32 GetMaxPlayers() const;
+ uint32 GetMaxResetDelay() const;
+ MapDifficulty const* GetMapDifficulty() const;
virtual void InitVisibilityDistance();
private:
@@ -623,7 +628,7 @@ class TRINITY_DLL_SPEC InstanceMap : public Map
class TRINITY_DLL_SPEC BattleGroundMap : public Map
{
public:
- BattleGroundMap(uint32 id, time_t, uint32 InstanceId, Map* _parent);
+ BattleGroundMap(uint32 id, time_t, uint32 InstanceId, Map* _parent, uint8 spawnMode);
~BattleGroundMap();
bool Add(Player *);
@@ -634,6 +639,10 @@ class TRINITY_DLL_SPEC BattleGroundMap : public Map
void RemoveAllPlayers();
virtual void InitVisibilityDistance();
+ BattleGround* GetBG() { return m_bg; }
+ void SetBG(BattleGround* bg) { m_bg = bg; }
+ private:
+ BattleGround* m_bg;
};
/*inline
@@ -710,4 +719,3 @@ Map::VisitGrid(const float &x, const float &y, float radius, NOTIFIER &notifier)
cell_lock->Visit(cell_lock, grid_object_notifier, *this, radius, x_off, y_off);
}
#endif
-
diff --git a/src/game/MapInstanced.cpp b/src/game/MapInstanced.cpp
index c77e40cb8f9..2fd9564a263 100644
--- a/src/game/MapInstanced.cpp
+++ b/src/game/MapInstanced.cpp
@@ -26,7 +26,7 @@
#include "InstanceSaveMgr.h"
#include "World.h"
-MapInstanced::MapInstanced(uint32 id, time_t expiry) : Map(id, expiry, 0, 0)
+MapInstanced::MapInstanced(uint32 id, time_t expiry) : Map(id, expiry, 0, DUNGEON_DIFFICULTY_NORMAL)
{
// initialize instanced maps list
m_InstancedMaps.clear();
@@ -40,7 +40,9 @@ void MapInstanced::InitVisibilityDistance()
return;
//initialize visibility distances for all instance copies
for (InstancedMaps::iterator i = m_InstancedMaps.begin(); i != m_InstancedMaps.end(); ++i)
+ {
(*i).second->InitVisibilityDistance();
+ }
}
void MapInstanced::Update(const uint32& t)
@@ -118,46 +120,63 @@ void MapInstanced::UnloadAll()
- create the instance if it's not created already
- the player is not actually added to the instance (only in InstanceMap::Add)
*/
-Map* MapInstanced::CreateInstance(const uint32 mapId, Player * player, uint32 instanceId)
+Map* MapInstanced::CreateInstance(const uint32 mapId, Player * player)
{
- if(instanceId)
- if(Map *map = _FindMap(instanceId))
- return map;
+ if(GetId() != mapId || !player)
+ return NULL;
+
+ Map* map = NULL;
+ uint32 NewInstanceId = 0; // instanceId of the resulting map
if(IsBattleGroundOrArena())
{
- instanceId = player->GetBattleGroundId();
- if(instanceId)
- if(Map *map = _FindMap(instanceId))
- return map;
- return CreateBattleGround(instanceId);
+ // instantiate or find existing bg map for player
+ // the instance id is set in battlegroundid
+ NewInstanceId = player->GetBattleGroundId();
+ if(!NewInstanceId) return NULL;
+ map = _FindMap(NewInstanceId);
+ if(!map)
+ map = CreateBattleGround(NewInstanceId, player->GetBattleGround());
}
- else if(InstanceSave *pSave = player->GetInstanceSave(GetId()))
+ else
{
- if(!instanceId)
+ InstancePlayerBind *pBind = player->GetBoundInstance(GetId(), player->GetDifficulty(IsRaid()));
+ InstanceSave *pSave = pBind ? pBind->save : NULL;
+
+ // the player's permanent player bind is taken into consideration first
+ // then the player's group bind and finally the solo bind.
+ if(!pBind || !pBind->perm)
{
- instanceId = pSave->GetInstanceId(); // go from outside to instance
- if(Map *map = _FindMap(instanceId))
- return map;
+ InstanceGroupBind *groupBind = NULL;
+ Group *group = player->GetGroup();
+ // use the player's difficulty setting (it may not be the same as the group's)
+ if(group && (groupBind = group->GetBoundInstance(this)))
+ pSave = groupBind->save;
}
- else if(instanceId != pSave->GetInstanceId()) // cannot go from one instance to another
- return NULL;
- // else log in at a saved instance
-
- return CreateInstance(instanceId, pSave, pSave->GetDifficulty());
- }
- else if(!player->GetSession()->PlayerLoading())
- {
- if(!instanceId)
- instanceId = MapManager::Instance().GenerateInstanceId();
+ if(pSave)
+ {
+ // solo/perm/group
+ NewInstanceId = pSave->GetInstanceId();
+ map = _FindMap(NewInstanceId);
+ // it is possible that the save exists but the map doesn't
+ if(!map)
+ map = CreateInstance(NewInstanceId, pSave, pSave->GetDifficulty());
+ }
+ else
+ {
+ // if no instanceId via group members or instance saves is found
+ // the instance will be created for the first time
+ NewInstanceId = MapManager::Instance().GenerateInstanceId();
- return CreateInstance(instanceId, NULL, player->GetDifficulty());
+ Difficulty diff = player->GetGroup() ? player->GetGroup()->GetDifficulty(IsRaid()) : player->GetDifficulty(IsRaid());
+ map = CreateInstance(NewInstanceId, NULL, diff);
+ }
}
- return NULL;
+ return map;
}
-InstanceMap* MapInstanced::CreateInstance(uint32 InstanceId, InstanceSave *save, uint8 difficulty)
+InstanceMap* MapInstanced::CreateInstance(uint32 InstanceId, InstanceSave *save, Difficulty difficulty)
{
// load/create a map
Guard guard(*this);
@@ -177,7 +196,9 @@ InstanceMap* MapInstanced::CreateInstance(uint32 InstanceId, InstanceSave *save,
}
// some instances only have one difficulty
- if (entry && !entry->SupportsHeroicMode()) difficulty = DIFFICULTY_NORMAL;
+ MapDifficulty const* mapDiff = GetMapDifficultyData(GetId(),difficulty);
+ if (!mapDiff)
+ difficulty = DUNGEON_DIFFICULTY_NORMAL;
sLog.outDebug("MapInstanced::CreateInstance: %s map instance %d for %d created with difficulty %s", save?"":"new ", InstanceId, GetId(), difficulty?"heroic":"normal");
@@ -191,15 +212,21 @@ InstanceMap* MapInstanced::CreateInstance(uint32 InstanceId, InstanceSave *save,
return map;
}
-BattleGroundMap* MapInstanced::CreateBattleGround(uint32 InstanceId)
+BattleGroundMap* MapInstanced::CreateBattleGround(uint32 InstanceId, BattleGround* bg)
{
// load/create a map
Guard guard(*this);
sLog.outDebug("MapInstanced::CreateBattleGround: map bg %d for %d created.", InstanceId, GetId());
- BattleGroundMap *map = new BattleGroundMap(GetId(), GetGridExpiry(), InstanceId, this);
+ // 0-59 normal spawn 60-69 difficulty_1, 70-79 difficulty_2, 80 dufficulty_3
+ uint8 spawnMode = (bg->GetQueueId() > QUEUE_ID_MAX_LEVEL_59) ? (bg->GetQueueId() - QUEUE_ID_MAX_LEVEL_59) : 0;
+ while (!GetMapDifficultyData(GetId(), Difficulty(spawnMode)))
+ spawnMode--;
+ BattleGroundMap *map = new BattleGroundMap(GetId(), GetGridExpiry(), InstanceId, this, spawnMode);
ASSERT(map->IsBattleGroundOrArena());
+ map->SetBG(bg);
+ bg->SetBgMap(map);
m_InstancedMaps[InstanceId] = map;
return map;
@@ -235,4 +262,3 @@ bool MapInstanced::CanEnter(Player *player)
//assert(false);
return true;
}
-
diff --git a/src/game/MapInstanced.h b/src/game/MapInstanced.h
index 22622d362ce..90aa5f5508e 100644
--- a/src/game/MapInstanced.h
+++ b/src/game/MapInstanced.h
@@ -23,6 +23,7 @@
#include "Map.h"
#include "InstanceSaveMgr.h"
+#include "DBCEnums.h"
class TRINITY_DLL_DECL MapInstanced : public Map
{
@@ -41,7 +42,7 @@ class TRINITY_DLL_DECL MapInstanced : public Map
void UnloadAll();
bool CanEnter(Player* player);
- Map* CreateInstance(const uint32 mapId, Player * player, uint32 instanceId);
+ Map* CreateInstance(const uint32 mapId, Player * player);
Map* FindMap(uint32 InstanceId) const { return _FindMap(InstanceId); }
bool DestroyInstance(InstancedMaps::iterator &itr);
@@ -63,8 +64,8 @@ class TRINITY_DLL_DECL MapInstanced : public Map
private:
- InstanceMap* CreateInstance(uint32 InstanceId, InstanceSave *save, uint8 difficulty);
- BattleGroundMap* CreateBattleGround(uint32 InstanceId);
+ InstanceMap* CreateInstance(uint32 InstanceId, InstanceSave *save, Difficulty difficulty);
+ BattleGroundMap* CreateBattleGround(uint32 InstanceId, BattleGround* bg);
InstancedMaps m_InstancedMaps;
@@ -77,4 +78,3 @@ class TRINITY_DLL_DECL MapInstanced : public Map
uint16 GridMapReference[MAX_NUMBER_OF_GRIDS][MAX_NUMBER_OF_GRIDS];
};
#endif
-
diff --git a/src/game/MapManager.cpp b/src/game/MapManager.cpp
index 5121b9dc574..d1457b5adee 100644
--- a/src/game/MapManager.cpp
+++ b/src/game/MapManager.cpp
@@ -82,7 +82,7 @@ MapManager::Initialize()
void MapManager::InitializeVisibilityDistanceInfo()
{
- for (MapMapType::iterator iter = i_maps.begin(); iter != i_maps.end(); ++iter)
+ for (MapMapType::iterator iter=i_maps.begin(); iter != i_maps.end(); ++iter)
(*iter).second->InitVisibilityDistance();
}
@@ -90,9 +90,9 @@ void MapManager::InitializeVisibilityDistanceInfo()
void MapManager::checkAndCorrectGridStatesArray()
{
bool ok = true;
- for (uint8 i = 0; i < MAX_GRID_STATE; ++i)
+ for (int i=0; i<MAX_GRID_STATE; i++)
{
- if (i_GridStates[i] != si_GridStates[i])
+ if(i_GridStates[i] != si_GridStates[i])
{
sLog.outError("MapManager::checkGridStates(), GridState: si_GridStates is currupt !!!");
ok = false;
@@ -107,10 +107,8 @@ void MapManager::checkAndCorrectGridStatesArray()
}
#endif
}
- if (!ok)
+ if(!ok)
++i_GridStateErrorCount;
- if (i_GridStateErrorCount > 2)
- assert(false); // force a crash. Too many errors
}
Map*
@@ -127,13 +125,9 @@ MapManager::_createBaseMap(uint32 id)
{
m = new MapInstanced(id, i_gridCleanUpDelay);
}
- else if (entry)
- {
- m = new Map(id, i_gridCleanUpDelay, 0, 0);
- }
else
{
- assert(false);
+ m = new Map(id, i_gridCleanUpDelay, 0, REGULAR_DIFFICULTY);
}
i_maps[id] = m;
}
@@ -148,7 +142,7 @@ Map* MapManager::CreateMap(uint32 id, const WorldObject* obj, uint32 instanceId)
//if(!obj->IsInWorld()) sLog.outError("GetMap: called for map %d with object (typeid %d, guid %d, mapid %d, instanceid %d) who is not in world!", id, obj->GetTypeId(), obj->GetGUIDLow(), obj->GetMapId(), obj->GetInstanceId());
Map *m = _createBaseMap(id);
- if (m && (obj->GetTypeId() == TYPEID_PLAYER) && m->Instanceable()) m = ((MapInstanced*)m)->CreateInstance(id, (Player*)obj, instanceId);
+ if (m && (obj->GetTypeId() == TYPEID_PLAYER) && m->Instanceable()) m = ((MapInstanced*)m)->CreateInstance(id, (Player*)obj);
return m;
}
@@ -192,14 +186,22 @@ bool MapManager::CanPlayerEnter(uint32 mapid, Player* player)
sLog.outDebug("MAP: Player '%s' must be in a raid group to enter instance of '%s'", player->GetName(), mapName);
return false;
}
+ // Åñëè ÈÊ èëè È×, òî ïðîâåðÿòü óðîâåíü øìîòà îäåòîãî íà ïåðñå.
+ //if(mapid==649)
}
}
//The player has a heroic mode and tries to enter into instance which has no a heroic mode
- if (!entry->SupportsHeroicMode() && player->GetDifficulty() == DIFFICULTY_HEROIC)
+ MapDifficulty const* mapDiff = GetMapDifficultyData(entry->MapID,player->GetDifficulty(entry->map_type == MAP_RAID));
+ if (!mapDiff)
{
+ bool isNormalTargetMap = entry->map_type == MAP_RAID
+ ? (player->GetRaidDifficulty() == RAID_DIFFICULTY_10MAN_NORMAL)
+ : (player->GetDungeonDifficulty() == DUNGEON_DIFFICULTY_NORMAL);
+
//Send aborted message
- player->SendTransferAborted(mapid, TRANSFER_ABORT_DIFFICULTY, DIFFICULTY_HEROIC);
+ // FIX ME: what about absent normal/heroic mode with specific players limit...
+ player->SendTransferAborted(mapid, TRANSFER_ABORT_DIFFICULTY, isNormalTargetMap ? DUNGEON_DIFFICULTY_NORMAL : DUNGEON_DIFFICULTY_HEROIC);
return false;
}
@@ -240,13 +242,13 @@ bool MapManager::CanPlayerEnter(uint32 mapid, Player* player)
//Get instance where player's group is bound & its map
if (player->GetGroup())
{
- InstanceGroupBind* boundedInstance = player->GetGroup()->GetBoundInstance(mapid, player->GetDifficulty());
+ InstanceGroupBind* boundedInstance = player->GetGroup()->GetBoundInstance(player);
if (boundedInstance && boundedInstance->save)
{
if (Map *boundedMap = MapManager::Instance().FindMap(mapid,boundedInstance->save->GetInstanceId()))
{
//Player permanently bounded to different instance than groups one
- InstancePlayerBind* playerBoundedInstance = player->GetBoundInstance(mapid, player->GetDifficulty());
+ InstancePlayerBind* playerBoundedInstance = player->GetBoundInstance(mapid, player->GetDungeonDifficulty());
if (playerBoundedInstance && playerBoundedInstance->perm && playerBoundedInstance->save &&
boundedInstance->save->GetInstanceId() != playerBoundedInstance->save->GetInstanceId())
{
@@ -263,7 +265,8 @@ bool MapManager::CanPlayerEnter(uint32 mapid, Player* player)
}
//Instance is full
- int8 maxPlayers = (player->GetDifficulty() == DIFFICULTY_HEROIC) ? instance->maxPlayersHeroic : instance->maxPlayers;
+ MapDifficulty const* mapDiff = ((InstanceMap*)player)->GetMapDifficulty();
+ int8 maxPlayers = mapDiff ? mapDiff->maxPlayers : 0;
if (maxPlayers != -1) //-1: unlimited access
{
if (boundedMap->GetPlayersCountExceptGMs() >= maxPlayers)
@@ -336,17 +339,6 @@ MapManager::Update(uint32 diff)
void MapManager::DoDelayedMovesAndRemoves()
{
- /*
- std::vector<Map*> update_queue(i_maps.size());
- for (MapMapType::iterator iter = i_maps.begin(), uint32 i = 0; iter != i_maps.end(); ++iter, ++i)
- update_queue[i] = iter->second;
-
- omp_set_num_threads(sWorld.getConfig(CONFIG_NUMTHREADS));
-
-#pragma omp parallel for schedule(dynamic) private(i) shared(update_queue)
- for (uint32 i = 0; i < i_maps.size(); ++i)
- update_queue[i]->DoDelayedMovesAndRemoves();
- */
}
bool MapManager::ExistMapAndVMap(uint32 mapid, float x,float y)
@@ -427,4 +419,3 @@ uint32 MapManager::GetNumPlayersInInstances()
}
return ret;
}
-
diff --git a/src/game/MapManager.h b/src/game/MapManager.h
index 05fd3db9951..f4bc5feafa2 100644
--- a/src/game/MapManager.h
+++ b/src/game/MapManager.h
@@ -156,4 +156,3 @@ class MANGOS_DLL_DECL MapManager : public MaNGOS::Singleton<MapManager, MaNGOS::
MapUpdater m_updater;
};
#endif
-
diff --git a/src/game/MiscHandler.cpp b/src/game/MiscHandler.cpp
index c51ca063e48..85e1a497a25 100644
--- a/src/game/MiscHandler.cpp
+++ b/src/game/MiscHandler.cpp
@@ -47,6 +47,7 @@
#include "AccountMgr.h"
#include "Vehicle.h"
#include "CreatureAI.h"
+#include "DBCEnums.h"
void WorldSession::HandleRepopRequestOpcode( WorldPacket & recv_data )
{
@@ -468,7 +469,7 @@ void WorldSession::HandleSetTargetOpcode( WorldPacket & recv_data )
uint64 guid ;
recv_data >> guid;
- _player->SetUInt32Value(UNIT_FIELD_TARGET,guid);
+ _player->SetUInt32Value(UNIT_FIELD_TARGET, guid);
// update reputation list if need
Unit* unit = ObjectAccessor::GetUnit(*_player, guid );
@@ -692,10 +693,8 @@ void WorldSession::HandleSetContactNotesOpcode( WorldPacket & recv_data )
void WorldSession::HandleBugOpcode( WorldPacket & recv_data )
{
- uint32 suggestion, contentlen;
- std::string content;
- uint32 typelen;
- std::string type;
+ uint32 suggestion, contentlen, typelen;
+ std::string content, type;
recv_data >> suggestion >> contentlen >> content;
@@ -737,7 +736,7 @@ void WorldSession::HandleReclaimCorpseOpcode(WorldPacket &recv_data)
if(corpse->GetGhostTime() + GetPlayer()->GetCorpseReclaimDelay(corpse->GetType()==CORPSE_RESURRECTABLE_PVP) > time(NULL))
return;
- if (!corpse->IsWithinDist(GetPlayer(), CORPSE_RECLAIM_RADIUS, true))
+ if (!corpse->IsWithinDistInMap(GetPlayer(), CORPSE_RECLAIM_RADIUS, true))
return;
uint64 guid;
@@ -988,8 +987,8 @@ void WorldSession::HandleRequestAccountData(WorldPacket& recv_data)
dest.resize(destSize);
- WorldPacket data (SMSG_UPDATE_ACCOUNT_DATA, 8+4+4+4+destSize);
- data << uint64(_player->GetGUID()); // player guid
+ WorldPacket data(SMSG_UPDATE_ACCOUNT_DATA, 8+4+4+4+destSize);
+ data << uint64(_player ? _player->GetGUID() : 0); // player guid
data << uint32(type); // type (0-7)
data << uint32(adata->Time); // unix time
data << uint32(size); // decompressed length
@@ -1053,7 +1052,12 @@ void WorldSession::HandleMoveTimeSkippedOpcode( WorldPacket & recv_data )
/* WorldSession::Update( getMSTime() );*/
DEBUG_LOG( "WORLD: Time Lag/Synchronization Resent/Update" );
- recv_data.read_skip<uint64>();
+ uint64 guid;
+ if(!recv_data.readPackGUID(guid))
+ {
+ recv_data.rpos(recv_data.wpos());
+ return;
+ }
recv_data.read_skip<uint32>();
/*
uint64 guid;
@@ -1441,10 +1445,16 @@ void WorldSession::HandleResetInstancesOpcode( WorldPacket & /*recv_data*/ )
if(pGroup)
{
if(pGroup->IsLeader(_player->GetGUID()))
- pGroup->ResetInstances(INSTANCE_RESET_ALL, _player);
+ {
+ pGroup->ResetInstances(INSTANCE_RESET_ALL, false, _player);
+ pGroup->ResetInstances(INSTANCE_RESET_ALL, true,_player);
+ }
}
else
- _player->ResetInstances(INSTANCE_RESET_ALL);
+ {
+ _player->ResetInstances(INSTANCE_RESET_ALL, false);
+ _player->ResetInstances(INSTANCE_RESET_ALL, true);
+ }
}
void WorldSession::HandleSetDungeonDifficultyOpcode( WorldPacket & recv_data )
@@ -1454,15 +1464,15 @@ void WorldSession::HandleSetDungeonDifficultyOpcode( WorldPacket & recv_data )
uint32 mode;
recv_data >> mode;
- if(mode == _player->GetDifficulty())
- return;
-
- if(mode > DIFFICULTY_HEROIC)
+ if(mode >= MAX_DUNGEON_DIFFICULTY)
{
sLog.outError("WorldSession::HandleSetDungeonDifficultyOpcode: player %d sent an invalid instance mode %d!", _player->GetGUIDLow(), mode);
return;
}
+ if(Difficulty(mode) == _player->GetDungeonDifficulty())
+ return;
+
// cannot reset while in an instance
Map *map = _player->GetMap();
if(map && map->IsDungeon())
@@ -1480,21 +1490,64 @@ void WorldSession::HandleSetDungeonDifficultyOpcode( WorldPacket & recv_data )
{
// the difficulty is set even if the instances can't be reset
//_player->SendDungeonDifficulty(true);
- pGroup->ResetInstances(INSTANCE_RESET_CHANGE_DIFFICULTY, _player);
- pGroup->SetDifficulty(mode);
+ pGroup->ResetInstances(INSTANCE_RESET_CHANGE_DIFFICULTY, false, _player);
+ pGroup->SetDungeonDifficulty(Difficulty(mode));
}
}
else
{
- _player->ResetInstances(INSTANCE_RESET_CHANGE_DIFFICULTY);
- _player->SetDifficulty(mode);
+ _player->ResetInstances(INSTANCE_RESET_CHANGE_DIFFICULTY, false);
+ _player->SetDungeonDifficulty(Difficulty(mode));
+ }
+}
+
+void WorldSession::HandleSetRaidDifficultyOpcode( WorldPacket & recv_data )
+{
+ sLog.outDebug("MSG_SET_RAID_DIFFICULTY");
+
+ uint32 mode;
+ recv_data >> mode;
+
+ if(mode >= MAX_RAID_DIFFICULTY)
+ {
+ sLog.outError("WorldSession::HandleSetRaidDifficultyOpcode: player %d sent an invalid instance mode %d!", _player->GetGUIDLow(), mode);
+ return;
+ }
+
+ // cannot reset while in an instance
+ Map *map = _player->GetMap();
+ if(map && map->IsDungeon())
+ {
+ sLog.outError("WorldSession::HandleSetRaidDifficultyOpcode: player %d tried to reset the instance while inside!", _player->GetGUIDLow());
+ return;
}
+
+ if(Difficulty(mode) == _player->GetRaidDifficulty())
+ return;
+
+ if(_player->getLevel() < LEVELREQUIREMENT_HEROIC)
+ return;
+
+ if(Group *pGroup = _player->GetGroup())
+ {
+ if(pGroup->IsLeader(_player->GetGUID()))
+ {
+ // the difficulty is set even if the instances can't be reset
+ //_player->SendDungeonDifficulty(true);
+ pGroup->ResetInstances(INSTANCE_RESET_CHANGE_DIFFICULTY, true, _player);
+ pGroup->SetRaidDifficulty(Difficulty(mode));
+ }
+ }
+ else
+ {
+ _player->ResetInstances(INSTANCE_RESET_CHANGE_DIFFICULTY, true);
+ _player->SetRaidDifficulty(Difficulty(mode));
+ }
}
void WorldSession::HandleCancelMountAuraOpcode( WorldPacket & /*recv_data*/ )
{
sLog.outDebug("WORLD: CMSG_CANCEL_MOUNT_AURA");
- //recv_data.hexlike();
//If player is not mounted, so go out :)
if (!_player->IsMounted()) // not blizz like; no any messages on blizz
@@ -1519,7 +1572,10 @@ void WorldSession::HandleMoveSetCanFlyAckOpcode( WorldPacket & recv_data )
sLog.outDebug("WORLD: CMSG_MOVE_SET_CAN_FLY_ACK");
//recv_data.hexlike();
- recv_data.read_skip<uint64>(); // guid
+ uint64 guid; // guid - unused
+ if(!recv_data.readPackGUID(guid))
+ return;
+
recv_data.read_skip<uint32>(); // unk
MovementInfo movementInfo;
@@ -1558,3 +1614,13 @@ void WorldSession::HandleQueryInspectAchievements( WorldPacket & recv_data )
player->GetAchievementMgr().SendRespondInspectAchievements(_player);
}
+
+void WorldSession::HandleWorldStateUITimerUpdate(WorldPacket& recv_data)
+{
+ // empty opcode
+ sLog.outDebug("WORLD: CMSG_WORLD_STATE_UI_TIMER_UPDATE");
+
+ WorldPacket data(SMSG_WORLD_STATE_UI_TIMER_UPDATE, 4);
+ data << uint32(time(NULL));
+ SendPacket(&data);
+}
diff --git a/src/game/MotionMaster.cpp b/src/game/MotionMaster.cpp
index 705cb20053a..c49765ded54 100644
--- a/src/game/MotionMaster.cpp
+++ b/src/game/MotionMaster.cpp
@@ -589,4 +589,3 @@ bool MotionMaster::GetDestination(float &x, float &y, float &z)
return top()->GetDestination(x,y,z);
}
-
diff --git a/src/game/MovementHandler.cpp b/src/game/MovementHandler.cpp
index a718d1601a2..7968fe06fb7 100644
--- a/src/game/MovementHandler.cpp
+++ b/src/game/MovementHandler.cpp
@@ -149,10 +149,14 @@ void WorldSession::HandleMoveWorldportAckOpcode()
}
}
- if((mEntry->IsRaid() || (mEntry->IsNonRaidDungeon() && mEntry->SupportsHeroicMode() && GetPlayer()->IsHeroic())) && mInstance)
+ if (mInstance && mEntry->IsDungeon())
{
- uint32 timeleft = sInstanceSaveManager.GetResetTimeFor(GetPlayer()->GetMapId()) - time(NULL);
- GetPlayer()->SendInstanceResetWarning(GetPlayer()->GetMapId(), GetPlayer()->GetDifficulty(), timeleft);
+ Difficulty diff = GetPlayer()->GetDifficulty(mEntry->IsRaid());
+ if (uint32 timeReset = sInstanceSaveManager.GetResetTimeFor(GetPlayer()->GetMapId(),diff))
+ {
+ uint32 timeleft = timeReset - time(NULL);
+ GetPlayer()->SendInstanceResetWarning(GetPlayer()->GetMapId(), diff, timeleft);
+ }
}
// mount allow check
@@ -179,9 +183,11 @@ void WorldSession::HandleMoveTeleportAck(WorldPacket& recv_data)
{
sLog.outDebug("MSG_MOVE_TELEPORT_ACK");
uint64 guid;
- uint32 flags, time;
- recv_data >> guid;
+ if(!recv_data.readPackGUID(guid))
+ return;
+
+ uint32 flags, time;
recv_data >> flags >> time;
DEBUG_LOG("Guid " UI64FMTD, guid);
DEBUG_LOG("Flags %u, time %u", flags, time/IN_MILISECONDS);
@@ -226,6 +232,7 @@ void WorldSession::HandleMovementOpcodes( WorldPacket & recv_data )
{
uint16 opcode = recv_data.GetOpcode();
//sLog.outDebug("WORLD: Recvd %s (%u, 0x%X) opcode", LookupOpcodeName(opcode), opcode, opcode);
+ recv_data.hexlike();
Unit *mover = _player->m_mover;
@@ -241,17 +248,23 @@ void WorldSession::HandleMovementOpcodes( WorldPacket & recv_data )
}
/* extract packet */
+ uint64 guid;
+
+ if(!recv_data.readPackGUID(guid))
+ return;
+
MovementInfo movementInfo;
+ movementInfo.guid = guid;
ReadMovementInfo(recv_data, &movementInfo);
/*----------------*/
- if (recv_data.size() != recv_data.rpos())
+ /* if(recv_data.size() != recv_data.rpos())
{
sLog.outError("MovementHandler: player %s (guid %d, account %u) sent a packet (opcode %u) that is " SIZEFMTD " bytes larger than it should be. Kicked as cheater.", _player->GetName(), _player->GetGUIDLow(), _player->GetSession()->GetAccountId(), recv_data.GetOpcode(), recv_data.size() - recv_data.rpos());
- KickPlayer();
+ KickPlayer();*/
recv_data.rpos(recv_data.wpos()); // prevent warnings spam
- return;
- }
+ /* return;
+ }*/
if (!Trinity::IsValidMapCoord(movementInfo.x, movementInfo.y, movementInfo.z, movementInfo.o))
{
@@ -320,10 +333,10 @@ void WorldSession::HandleMovementOpcodes( WorldPacket & recv_data )
/*----------------------*/
/* process position-change */
- recv_data.put<uint32>(6, getMSTime()); // fix time, offset flags(4) + unk(2)
- WorldPacket data(recv_data.GetOpcode(), (mover->GetPackGUID().size()+recv_data.size()));
- data.append(mover->GetPackGUID()); // use mover guid
- data.append(recv_data.contents(), recv_data.size());
+ WorldPacket data(opcode, recv_data.size());
+ movementInfo.time = getMSTime();
+ movementInfo.guid = mover->GetGUID();
+ WriteMovementInfo(&data, &movementInfo);
GetPlayer()->SendMessageToSet(&data, false);
mover->m_movementInfo = movementInfo;
@@ -338,7 +351,7 @@ void WorldSession::HandleMovementOpcodes( WorldPacket & recv_data )
if (plMover) // nothing is charmed, or player charmed
{
plMover->SetPosition(movementInfo.x, movementInfo.y, movementInfo.z, movementInfo.o);
- plMover->UpdateFallInformationIfNeed(movementInfo, recv_data.GetOpcode());
+ plMover->UpdateFallInformationIfNeed(movementInfo, opcode);
if (movementInfo.z < -500.0f)
{
@@ -389,14 +402,16 @@ void WorldSession::HandleMovementOpcodes( WorldPacket & recv_data )
void WorldSession::HandleForceSpeedChangeAck(WorldPacket &recv_data)
{
- //sLog.outDebug("WORLD: Recvd %s (%u, 0x%X) opcode", LookupOpcodeName(recv_data.GetOpcode()), recv_data.GetOpcode(), recv_data.GetOpcode());
-
+ uint32 opcode = recv_data.GetOpcode();
+ sLog.outDebug("WORLD: Recvd %s (%u, 0x%X) opcode", LookupOpcodeName(opcode), opcode, opcode);
+
/* extract packet */
uint64 guid;
uint32 unk1;
float newspeed;
- recv_data >> guid;
+ if(!recv_data.readPackGUID(guid))
+ return;
// now can skip not our packet
if(_player->GetGUID() != guid)
@@ -410,6 +425,7 @@ void WorldSession::HandleForceSpeedChangeAck(WorldPacket &recv_data)
recv_data >> unk1; // counter or moveEvent
MovementInfo movementInfo;
+ movementInfo.guid = guid;
ReadMovementInfo(recv_data, &movementInfo);
recv_data >> newspeed;
@@ -422,7 +438,6 @@ void WorldSession::HandleForceSpeedChangeAck(WorldPacket &recv_data)
static char const* move_type_name[MAX_MOVE_TYPE] = { "Walk", "Run", "RunBack", "Swim", "SwimBack", "TurnRate", "Flight", "FlightBack", "PitchRate" };
- uint16 opcode = recv_data.GetOpcode();
switch(opcode)
{
case CMSG_FORCE_WALK_SPEED_CHANGE_ACK: move_type = MOVE_WALK; force_move_type = MOVE_WALK; break;
@@ -498,7 +513,8 @@ void WorldSession::HandleMoveNotActiveMover(WorldPacket &recv_data)
sLog.outDebug("WORLD: Recvd CMSG_MOVE_NOT_ACTIVE_MOVER");
uint64 old_mover_guid;
- recv_data >> old_mover_guid;
+ if(!recv_data.readPackGUID(old_mover_guid))
+ return;
/*if(_player->m_mover->GetGUID() == old_mover_guid)
{
@@ -507,7 +523,12 @@ void WorldSession::HandleMoveNotActiveMover(WorldPacket &recv_data)
return;
}*/
- ReadMovementInfo(recv_data, &_player->m_mover->m_movementInfo);
+ MovementInfo mi;
+ mi.guid = old_mover_guid;
+ ReadMovementInfo(recv_data, &mi);
+
+ //ReadMovementInfo(recv_data, &_player->m_mover->m_movementInfo);
+ _player->m_movementInfo = mi;
}
void WorldSession::HandleDismissControlledVehicle(WorldPacket &recv_data)
@@ -523,7 +544,19 @@ void WorldSession::HandleDismissControlledVehicle(WorldPacket &recv_data)
return;
}
- ReadMovementInfo(recv_data, &_player->m_mover->m_movementInfo);
+ uint64 guid;
+
+ if(!recv_data.readPackGUID(guid))
+ return;
+
+ MovementInfo mi;
+ mi.guid = guid;
+ ReadMovementInfo(recv_data, &mi);
+
+ _player->m_movementInfo = mi;
+
+ /*
+ ReadMovementInfo(recv_data, &_player->m_mover->m_movementInfo);*/
_player->ExitVehicle();
}
@@ -584,7 +617,10 @@ void WorldSession::HandleMoveKnockBackAck( WorldPacket & recv_data )
{
sLog.outDebug("CMSG_MOVE_KNOCK_BACK_ACK");
- recv_data.read_skip<uint64>(); // guid
+ uint64 guid; // guid - unused
+ if(!recv_data.readPackGUID(guid))
+ return;
+
recv_data.read_skip<uint32>(); // unk
MovementInfo movementInfo;
@@ -595,7 +631,10 @@ void WorldSession::HandleMoveHoverAck( WorldPacket& recv_data )
{
sLog.outDebug("CMSG_MOVE_HOVER_ACK");
- recv_data.read_skip<uint64>(); // guid
+ uint64 guid; // guid - unused
+ if(!recv_data.readPackGUID(guid))
+ return;
+
recv_data.read_skip<uint32>(); // unk
MovementInfo movementInfo;
@@ -608,7 +647,10 @@ void WorldSession::HandleMoveWaterWalkAck(WorldPacket& recv_data)
{
sLog.outDebug("CMSG_MOVE_WATER_WALK_ACK");
- recv_data.read_skip<uint64>(); // guid
+ uint64 guid; // guid - unused
+ if(!recv_data.readPackGUID(guid))
+ return;
+
recv_data.read_skip<uint32>(); // unk
MovementInfo movementInfo;
@@ -629,4 +671,3 @@ void WorldSession::HandleSummonResponseOpcode(WorldPacket& recv_data)
_player->SummonIfPossible(agree);
}
-
diff --git a/src/game/Object.cpp b/src/game/Object.cpp
index 6aa4b3949c5..f3cff243e93 100644
--- a/src/game/Object.cpp
+++ b/src/game/Object.cpp
@@ -1398,6 +1398,16 @@ bool WorldObject::IsInBetween(const WorldObject *obj1, const WorldObject *obj2,
return abs(sin(angle)) * GetExactDist2d(obj1->GetPositionX(), obj1->GetPositionY()) < size;
}
+bool WorldObject::isInFront(WorldObject const* target, float distance, float arc) const
+{
+ return IsWithinDist(target, distance) && HasInArc( arc, target );
+}
+
+bool WorldObject::isInBack(WorldObject const* target, float distance, float arc) const
+{
+ return IsWithinDist(target, distance) && !HasInArc( 2 * M_PI - arc, target );
+}
+
void WorldObject::GetRandomPoint(const Position &pos, float distance, float &rand_x, float &rand_y, float &rand_z) const
{
if(!distance)
@@ -1932,38 +1942,52 @@ Creature* WorldObject::SummonTrigger(float x, float y, float z, float ang, uint3
return summon;
}
-Creature* WorldObject::FindNearestCreature(uint32 uiEntry, float fMaxSearchRange, bool bAlive)
+Creature* WorldObject::FindNearestCreature(uint32 entry, float range, bool alive)
{
- Creature *pCreature = NULL;
- Trinity::NearestCreatureEntryWithLiveStateInObjectRangeCheck checker(*this, uiEntry, bAlive, fMaxSearchRange);
- Trinity::CreatureLastSearcher<Trinity::NearestCreatureEntryWithLiveStateInObjectRangeCheck> searcher(this, pCreature, checker);
- VisitNearbyObject(fMaxSearchRange, searcher);
- return pCreature;
+ Creature *creature = NULL;
+ Trinity::NearestCreatureEntryWithLiveStateInObjectRangeCheck checker(*this, entry, alive, range);
+ Trinity::CreatureLastSearcher<Trinity::NearestCreatureEntryWithLiveStateInObjectRangeCheck> searcher(this, creature, checker);
+ VisitNearbyObject(range, searcher);
+ return creature;
}
-GameObject* WorldObject::FindNearestGameObject(uint32 uiEntry, float fMaxSearchRange)
+GameObject* WorldObject::FindNearestGameObject(uint32 entry, float range)
{
- GameObject *pGO = NULL;
- Trinity::NearestGameObjectEntryInObjectRangeCheck checker(*this, uiEntry, fMaxSearchRange);
- Trinity::GameObjectLastSearcher<Trinity::NearestGameObjectEntryInObjectRangeCheck> searcher(this, pGO, checker);
- VisitNearbyGridObject(fMaxSearchRange, searcher);
- return pGO;
+ GameObject *go = NULL;
+ Trinity::NearestGameObjectEntryInObjectRangeCheck checker(*this, entry, range);
+ Trinity::GameObjectLastSearcher<Trinity::NearestGameObjectEntryInObjectRangeCheck> searcher(this, go, checker);
+ VisitNearbyGridObject(range, searcher);
+ return go;
+}
+
+void WorldObject::GetGameObjectListWithEntryInGrid(std::list<GameObject*>& lList, uint32 uiEntry, float fMaxSearchRange)
+{
+ CellPair pair(Trinity::ComputeCellPair(this->GetPositionX(), this->GetPositionY()));
+ Cell cell(pair);
+ cell.data.Part.reserved = ALL_DISTRICT;
+ cell.SetNoCreate();
+
+ Trinity::AllGameObjectsWithEntryInRange check(this, uiEntry, fMaxSearchRange);
+ Trinity::GameObjectListSearcher<Trinity::AllGameObjectsWithEntryInRange> searcher(this, lList, check);
+ TypeContainerVisitor<Trinity::GameObjectListSearcher<Trinity::AllGameObjectsWithEntryInRange>, GridTypeMapContainer> visitor(searcher);
+
+ CellLock<GridReadGuard> cell_lock(cell, pair);
+ cell_lock->Visit(cell_lock, visitor, *(this->GetMap()));
}
void WorldObject::GetCreatureListWithEntryInGrid(std::list<Creature*>& lList, uint32 uiEntry, float fMaxSearchRange)
{
+ CellPair pair(Trinity::ComputeCellPair(this->GetPositionX(), this->GetPositionY()));
+ Cell cell(pair);
+ cell.data.Part.reserved = ALL_DISTRICT;
+ cell.SetNoCreate();
+
Trinity::AllCreaturesOfEntryInRange check(this, uiEntry, fMaxSearchRange);
Trinity::CreatureListSearcher<Trinity::AllCreaturesOfEntryInRange> searcher(this, lList, check);
TypeContainerVisitor<Trinity::CreatureListSearcher<Trinity::AllCreaturesOfEntryInRange>, GridTypeMapContainer> visitor(searcher);
- VisitNearbyObject(fMaxSearchRange, searcher);
-}
-void WorldObject::GetGameObjectListWithEntryInGrid(std::list<GameObject*>& lList, uint32 uiEntry, float fMaxSearchRange)
-{
- Trinity::AllGameObjectsWithEntryInRange check(this, uiEntry, fMaxSearchRange);
- Trinity::GameObjectListSearcher<Trinity::AllGameObjectsWithEntryInRange> searcher(this, lList, check);
- TypeContainerVisitor<Trinity::GameObjectListSearcher<Trinity::AllGameObjectsWithEntryInRange>, GridTypeMapContainer> visitor(searcher);
- VisitNearbyGridObject(fMaxSearchRange, searcher);
+ CellLock<GridReadGuard> cell_lock(cell, pair);
+ cell_lock->Visit(cell_lock, visitor, *(this->GetMap()));
}
/*
diff --git a/src/game/Object.h b/src/game/Object.h
index b068033bdf3..83189f30b23 100644
--- a/src/game/Object.h
+++ b/src/game/Object.h
@@ -237,8 +237,7 @@ class TRINITY_DLL_SPEC Object
bool HasFlag( uint16 index, uint32 flag ) const
{
- if(index >= m_valuesCount && !PrintIndexError(index , false))
- return false;
+ if( index >= m_valuesCount && !PrintIndexError( index , false ) ) return false;
return (m_uint32Values[ index ] & flag) != 0;
}
@@ -549,6 +548,8 @@ class TRINITY_DLL_SPEC WorldObject : public Object, public WorldLocation
bool IsInRange(WorldObject const* obj, float minRange, float maxRange, bool is3D = true) const;
bool IsInRange2d(float x, float y, float minRange, float maxRange) const;
bool IsInRange3d(float x, float y, float z, float minRange, float maxRange) const;
+ bool isInFront(WorldObject const* target,float distance, float arc = M_PI) const;
+ bool isInBack(WorldObject const* target, float distance, float arc = M_PI) const;
bool IsInBetween(const WorldObject *obj1, const WorldObject *obj2, float size = 0) const;
@@ -611,11 +612,11 @@ class TRINITY_DLL_SPEC WorldObject : public Object, public WorldLocation
GameObject* SummonGameObject(uint32 entry, float x, float y, float z, float ang, float rotation0, float rotation1, float rotation2, float rotation3, uint32 respawnTime);
Creature* SummonTrigger(float x, float y, float z, float ang, uint32 dur, CreatureAI* (*GetAI)(Creature*) = NULL);
- Creature* FindNearestCreature(uint32 uiEntry, float fMaxSearchRange, bool bAlive = true);
- GameObject* FindNearestGameObject(uint32 uiEntry, float fMaxSearchRange);
+ Creature* FindNearestCreature(uint32 entry, float range, bool alive = true);
+ GameObject* FindNearestGameObject(uint32 entry, float range);
- void GetCreatureListWithEntryInGrid(std::list<Creature*>& lList, uint32 uiEntry, float fMaxSearchRange);
void GetGameObjectListWithEntryInGrid(std::list<GameObject*>& lList, uint32 uiEntry, float fMaxSearchRange);
+ void GetCreatureListWithEntryInGrid(std::list<Creature*>& lList, uint32 uiEntry, float fMaxSearchRange);
void DestroyForNearbyPlayers();
@@ -655,4 +656,3 @@ class TRINITY_DLL_SPEC WorldObject : public Object, public WorldLocation
uint32 m_phaseMask; // in area phase state
};
#endif
-
diff --git a/src/game/ObjectAccessor.cpp b/src/game/ObjectAccessor.cpp
index 2dfd9c9ae7b..e52423eabd8 100644
--- a/src/game/ObjectAccessor.cpp
+++ b/src/game/ObjectAccessor.cpp
@@ -49,7 +49,10 @@ ObjectAccessor::ObjectAccessor() {}
ObjectAccessor::~ObjectAccessor()
{
for (Player2CorpsesMapType::const_iterator itr = i_player2corpse.begin(); itr != i_player2corpse.end(); ++itr)
+ {
+ itr->second->RemoveFromWorld();
delete itr->second;
+ }
}
Creature*
@@ -351,6 +354,10 @@ ObjectAccessor::ConvertCorpseForPlayer(uint64 player_guid, bool insignia)
// remove corpse from DB
corpse->DeleteFromDB();
+ // we don't want bones to save some cpu.. :)
+ delete corpse;
+ return NULL;
+
Corpse *bones = NULL;
// create the bones only if the map and the grid is loaded at the corpse's location
// ignore bones creating option in case insignia
@@ -521,4 +528,3 @@ template Creature* ObjectAccessor::GetObjectInWorld<Creature>(uint32 mapid, floa
template Corpse* ObjectAccessor::GetObjectInWorld<Corpse>(uint32 mapid, float x, float y, uint64 guid, Corpse* /*fake*/);
template GameObject* ObjectAccessor::GetObjectInWorld<GameObject>(uint32 mapid, float x, float y, uint64 guid, GameObject* /*fake*/);
template DynamicObject* ObjectAccessor::GetObjectInWorld<DynamicObject>(uint32 mapid, float x, float y, uint64 guid, DynamicObject* /*fake*/);
-
diff --git a/src/game/ObjectAccessor.h b/src/game/ObjectAccessor.h
index 79afa78fb6a..780c108e5e4 100644
--- a/src/game/ObjectAccessor.h
+++ b/src/game/ObjectAccessor.h
@@ -267,4 +267,3 @@ class MANGOS_DLL_DECL ObjectAccessor : public MaNGOS::Singleton<ObjectAccessor,
LockType i_petGuard;
};
#endif
-
diff --git a/src/game/ObjectMgr.cpp b/src/game/ObjectMgr.cpp
index 1d9f2d64878..d1b7d58c54f 100644
--- a/src/game/ObjectMgr.cpp
+++ b/src/game/ObjectMgr.cpp
@@ -204,10 +204,6 @@ ObjectMgr::~ObjectMgr()
for (GuildMap::iterator itr = mGuildMap.begin(); itr != mGuildMap.end(); ++itr)
delete itr->second;
- mGuildMap.clear();
-
- for (CachePlayerInfoMap::iterator itr = m_mPlayerInfoMap.begin(); itr != m_mPlayerInfoMap.end(); ++itr)
- delete itr->second;
for (ArenaTeamMap::iterator itr = mArenaTeamMap.begin(); itr != mArenaTeamMap.end(); ++itr)
delete itr->second;
@@ -219,61 +215,6 @@ ObjectMgr::~ObjectMgr()
itr->second.Clear();
}
-void ObjectMgr::LoadPlayerInfoInCache()
-{
- QueryResult *result = CharacterDatabase.PQuery("SELECT guid, name, data, class FROM characters");
- if(!result)
- {
- sLog.outError( "Loading Player Cache failed.");
- return;
- }
-
- PCachePlayerInfo pPPlayerInfo = NULL;
- Field *fields = NULL;
- Tokens tdata;
- barGoLink bar( result->GetRowCount() );
- do
- {
- bar.step();
- fields = result->Fetch();
- pPPlayerInfo = new CachePlayerInfo();
-
- pPPlayerInfo->sPlayerName = fields[1].GetString();
-
- tdata.clear();
- tdata = StrSplit(fields[2].GetCppString(), " ");
-
- pPPlayerInfo->unLevel = Player::GetUInt32ValueFromArray(tdata,UNIT_FIELD_LEVEL);
- pPPlayerInfo->unfield = Player::GetUInt32ValueFromArray(tdata,UNIT_FIELD_BYTES_0);
-
- pPPlayerInfo->unArenaInfoId0 = Player::GetUInt32ValueFromArray(tdata,PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + 0 * 6);
- pPPlayerInfo->unArenaInfoId1 = Player::GetUInt32ValueFromArray(tdata,PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + 1 * 6);
- pPPlayerInfo->unArenaInfoId2 = Player::GetUInt32ValueFromArray(tdata,PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + 2 * 6);
-
- pPPlayerInfo->unArenaInfoSlot0 = Player::GetUInt32ValueFromArray(tdata,PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + 0 * 6 + 5);
- pPPlayerInfo->unArenaInfoSlot1 = Player::GetUInt32ValueFromArray(tdata,PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + 1 * 6 + 5);
- pPPlayerInfo->unArenaInfoSlot2 = Player::GetUInt32ValueFromArray(tdata,PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + 2 * 6 + 5);
-
- pPPlayerInfo->unClass = (uint32)fields[3].GetUInt32();
- m_mPlayerInfoMap[fields[0].GetUInt32()] = pPPlayerInfo;
- }
- while (result->NextRow());
- delete result;
-
- sLog.outString();
- sLog.outString( ">> Loaded info about %d players", m_mPlayerInfoMap.size());
-}
-
-PCachePlayerInfo ObjectMgr::GetPlayerInfoFromCache(uint32 unPlayerGuid) const
-{
- //Now m_mPlayerInfoMap is using only for search, but when dinamic inserting/removing
- //will be implemented we should lock it to prevent simultaneous access.
- //Inserting - when new created player is saving
- //Removing - when player has been deleted
- CachePlayerInfoMap::const_iterator ipos = m_mPlayerInfoMap.find(unPlayerGuid);
- return ipos == m_mPlayerInfoMap.end() ? NULL : ipos->second;
-}
-
Group * ObjectMgr::GetGroupByLeader(const uint64 &guid) const
{
for (GroupSet::const_iterator itr = mGroupSet.begin(); itr != mGroupSet.end(); ++itr)
@@ -570,8 +511,8 @@ void ObjectMgr::LoadCreatureTemplates()
sLog.outString( ">> Loaded %u creature definitions", sCreatureStorage.RecordCount );
sLog.outString();
- std::set<uint32> heroicEntries; // already loaded heroic value in creatures
- std::set<uint32> hasHeroicEntries; // already loaded creatures with heroic entry values
+ std::set<uint32> difficultyEntries[MAX_DIFFICULTY - 1]; // already loaded difficulty 1 value in creatures
+ std::set<uint32> hasDifficultyEntries[MAX_DIFFICULTY - 1]; // already loaded creatures with difficulty 1 values
// check data correctness
for (uint32 i = 1; i < sCreatureStorage.MaxEntry; ++i)
@@ -580,84 +521,105 @@ void ObjectMgr::LoadCreatureTemplates()
if (!cInfo)
continue;
- if (cInfo->HeroicEntry)
+ bool ok = true; // bool to allow continue outside this loop
+ for (uint32 diff = 0; diff < MAX_DIFFICULTY - 1 && ok; ++diff)
{
- CreatureInfo const* heroicInfo = GetCreatureTemplate(cInfo->HeroicEntry);
- if (!heroicInfo)
- {
- sLog.outErrorDb("Creature (Entry: %u) have `heroic_entry`=%u but creature entry %u not exist.", i, cInfo->HeroicEntry, cInfo->HeroicEntry);
+ if (!cInfo->DifficultyEntry[diff])
continue;
- }
+ ok = false; // will be set to true at the end of this loop again
- if (heroicEntries.find(i)!=heroicEntries.end())
+ CreatureInfo const* difficultyInfo = GetCreatureTemplate(cInfo->DifficultyEntry[diff]);
+ if (!difficultyInfo)
{
- sLog.outErrorDb("Creature (Entry: %u) listed as heroic but have value in `heroic_entry`.",i);
+ sLog.outErrorDb("Creature (Entry: %u) have `difficulty_entry_%u`=%u but creature entry %u not exist.",
+ i, diff + 1, cInfo->DifficultyEntry[diff], cInfo->DifficultyEntry[diff]);
continue;
}
- if (heroicEntries.find(cInfo->HeroicEntry)!=heroicEntries.end())
+ if (difficultyEntries[diff].find(i) != difficultyEntries[diff].end())
{
- sLog.outErrorDb("Creature (Entry: %u) already listed as heroic for another entry.",cInfo->HeroicEntry);
+ sLog.outErrorDb("Creature (Entry: %u) listed as difficulty %u but have value in `difficulty_entry_1`.", i, diff + 1);
continue;
}
- if (hasHeroicEntries.find(cInfo->HeroicEntry)!=hasHeroicEntries.end())
+ bool ok2 = true;
+ for (uint32 diff2 = 0; diff2 < MAX_DIFFICULTY - 1 && ok2; ++diff2)
{
- sLog.outErrorDb("Creature (Entry: %u) have `heroic_entry`=%u but creature entry %u have heroic entry also.",i,cInfo->HeroicEntry,cInfo->HeroicEntry);
- continue;
+ ok2 = false;
+ if (difficultyEntries[diff2].find(cInfo->DifficultyEntry[diff]) != difficultyEntries[diff2].end())
+ {
+ sLog.outErrorDb("Creature (Entry: %u) already listed as difficulty %u for another entry.", cInfo->DifficultyEntry[diff], diff2 + 1);
+ continue;
+ }
+
+ if (hasDifficultyEntries[diff2].find(cInfo->DifficultyEntry[diff]) != hasDifficultyEntries[diff2].end())
+ {
+ sLog.outErrorDb("Creature (Entry: %u) have `difficulty_entry_%u`=%u but creature entry %u have difficulty %u entry also.",
+ i, diff + 1, cInfo->DifficultyEntry[diff], cInfo->DifficultyEntry[diff], diff2 + 1);
+ continue;
+ }
+ ok2 = true;
}
+ if (!ok2)
+ continue;
- if (cInfo->unit_class != heroicInfo->unit_class)
+ if (cInfo->unit_class != difficultyInfo->unit_class)
{
- sLog.outErrorDb("Creature (Entry: %u, class %u) has different `unit_class` in heroic mode (Entry: %u, class %u).",i, cInfo->unit_class, cInfo->HeroicEntry, heroicInfo->unit_class);
+ sLog.outErrorDb("Creature (Entry: %u, class %u) has different `unit_class` in difficulty %u mode (Entry: %u, class %u).",
+ i, cInfo->unit_class, diff + 1, cInfo->DifficultyEntry[diff], difficultyInfo->unit_class);
continue;
}
- if (cInfo->npcflag != heroicInfo->npcflag)
+ if (cInfo->npcflag != difficultyInfo->npcflag)
{
- sLog.outErrorDb("Creature (Entry: %u) listed in `creature_template_substitution` has different `npcflag` in heroic mode.",i);
+ sLog.outErrorDb("Creature (Entry: %u) has different `npcflag` in difficulty %u mode (Entry: %u).", i, diff + 1, cInfo->DifficultyEntry[diff]);
continue;
}
- if (cInfo->trainer_class != heroicInfo->trainer_class)
+ if (cInfo->trainer_class != difficultyInfo->trainer_class)
{
- sLog.outErrorDb("Creature (Entry: %u) has different `trainer_class` in heroic mode (Entry: %u).",i,cInfo->HeroicEntry);
+ sLog.outErrorDb("Creature (Entry: %u) has different `trainer_class` in difficulty %u mode (Entry: %u).", i, diff + 1, cInfo->DifficultyEntry[diff]);
continue;
}
- if (cInfo->trainer_race != heroicInfo->trainer_race)
+ if (cInfo->trainer_race != difficultyInfo->trainer_race)
{
- sLog.outErrorDb("Creature (Entry: %u) has different `trainer_race` in heroic mode (Entry: %u).",i,cInfo->HeroicEntry);
+ sLog.outErrorDb("Creature (Entry: %u) has different `trainer_race` in difficulty %u mode (Entry: %u).", i, diff + 1, cInfo->DifficultyEntry[diff]);
continue;
}
- if (cInfo->trainer_type != heroicInfo->trainer_type)
+ if (cInfo->trainer_type != difficultyInfo->trainer_type)
{
- sLog.outErrorDb("Creature (Entry: %u) listed in `creature_template_substitution` has different `trainer_type` in heroic mode.",i);
+ sLog.outErrorDb("Creature (Entry: %u) has different `trainer_type` in difficulty %u mode (Entry: %u).", i, diff + 1, cInfo->DifficultyEntry[diff]);
continue;
}
- if (cInfo->trainer_spell != heroicInfo->trainer_spell)
+ if (cInfo->trainer_spell != difficultyInfo->trainer_spell)
{
- sLog.outErrorDb("Creature (Entry: %u) listed in `creature_template_substitution` has different `trainer_spell` in heroic mode.",i);
+ sLog.outErrorDb("Creature (Entry: %u) has different `trainer_spell` in difficulty %u mode (Entry: %u).", i, diff + 1, cInfo->DifficultyEntry[diff]);
continue;
}
- if (heroicInfo->AIName && *heroicInfo->AIName)
+ if (difficultyInfo->AIName && *difficultyInfo->AIName)
{
- sLog.outErrorDb("Heroic mode creature (Entry: %u) has `AIName`, but in any case will used normal mode creature (Entry: %u) AIName.",cInfo->HeroicEntry,i);
+ sLog.outErrorDb("Difficulty %u mode creature (Entry: %u) has `AIName`, but in any case will used difficulty 0 mode creature (Entry: %u) AIName.",
+ diff, cInfo->DifficultyEntry[diff], i);
continue;
}
- if (heroicInfo->ScriptID)
+ if (difficultyInfo->ScriptID)
{
- sLog.outErrorDb("Heroic mode creature (Entry: %u) has `ScriptName`, but in any case will used normal mode creature (Entry: %u) ScriptName.",cInfo->HeroicEntry,i);
+ sLog.outErrorDb("Difficulty %u mode creature (Entry: %u) has `ScriptName`, but in any case will used difficulty 0 mode creature (Entry: %u) ScriptName.",
+ diff, cInfo->DifficultyEntry[diff], i);
continue;
}
- hasHeroicEntries.insert(i);
- heroicEntries.insert(cInfo->HeroicEntry);
+ hasDifficultyEntries[diff].insert(i);
+ difficultyEntries[diff].insert(cInfo->DifficultyEntry[diff]);
+ ok = true;
}
+ if (!ok)
+ continue;
FactionTemplateEntry const* factionTemplate = sFactionTemplateStore.LookupEntry(cInfo->faction_A);
if (!factionTemplate)
@@ -1232,11 +1194,20 @@ void ObjectMgr::LoadCreatures()
}
// build single time for check creature data
- std::set<uint32> heroicCreatures;
+ std::set<uint32> difficultyCreatures[MAX_DIFFICULTY - 1];
for (uint32 i = 0; i < sCreatureStorage.MaxEntry; ++i)
- if(CreatureInfo const* cInfo = sCreatureStorage.LookupEntry<CreatureInfo>(i))
- if(cInfo->HeroicEntry)
- heroicCreatures.insert(cInfo->HeroicEntry);
+ if (CreatureInfo const* cInfo = sCreatureStorage.LookupEntry<CreatureInfo>(i))
+ for (uint32 diff = 0; diff < MAX_DIFFICULTY - 1; ++diff)
+ if (cInfo->DifficultyEntry[diff])
+ difficultyCreatures[diff].insert(cInfo->DifficultyEntry[diff]);
+
+ // build single time for check spawnmask
+ std::map<uint32,uint32> spawnMasks;
+ for(uint32 i = 0; i < sMapStore.GetNumRows(); ++i)
+ if(sMapStore.LookupEntry(i))
+ for(int k = 0; k < MAX_DIFFICULTY; ++k)
+ if (GetMapDifficultyData(i,Difficulty(k)))
+ spawnMasks[i] |= (1 << k);
//TODO: remove this
//gameeventmgr.mGameEventCreatureGuids.resize(52*2-1);
@@ -1280,12 +1251,29 @@ void ObjectMgr::LoadCreatures()
int16 gameEvent = fields[18].GetInt16();
int16 PoolId = fields[19].GetInt16();
- if(heroicCreatures.find(data.id)!=heroicCreatures.end())
+ MapEntry const* mapEntry = sMapStore.LookupEntry(data.mapid);
+ if(!mapEntry)
{
- sLog.outErrorDb("Table `creature` have creature (GUID: %u) that listed as heroic template (entry: %u) in `creature_template_substitution`, skipped.",guid,data.id );
+ sLog.outErrorDb("Table `creature` have creature (GUID: %u) that spawned at not existed map (Id: %u), skipped.",guid, data.mapid );
continue;
}
+ if (data.spawnMask & ~spawnMasks[data.mapid])
+ sLog.outErrorDb("Table `creature` have creature (GUID: %u) that have wrong spawn mask %u including not supported difficulty modes for map (Id: %u).",guid, data.spawnMask, data.mapid );
+
+ bool ok = true;
+ for (uint32 diff = 0; diff < MAX_DIFFICULTY - 1 && ok; ++diff)
+ {
+ if (difficultyCreatures[diff].find(data.id) != difficultyCreatures[diff].end())
+ {
+ sLog.outErrorDb("Table `creature` have creature (GUID: %u) that listed as difficulty %u template (entry: %u) in `creature_template`, skipped.",
+ guid, diff + 1, data.id );
+ ok = false;
+ }
+ }
+ if (!ok)
+ continue;
+
// I do not know why but in db most display id are not zero
/*if(data.displayid == 11686 || data.displayid == 24719)
{
@@ -1313,8 +1301,7 @@ void ObjectMgr::LoadCreatures()
if(cInfo->flags_extra & CREATURE_FLAG_EXTRA_INSTANCE_BIND)
{
- MapEntry const* map = sMapStore.LookupEntry(data.mapid);
- if(!map || !map->IsDungeon())
+ if(!mapEntry || !mapEntry->IsDungeon())
sLog.outErrorDb("Table `creature` have creature (GUID: %u Entry: %u) with `creature_template`.`flags_extra` including CREATURE_FLAG_EXTRA_INSTANCE_BIND but creature are not in instance.",guid,data.id);
}
@@ -1569,6 +1556,14 @@ void ObjectMgr::LoadGameobjects()
return;
}
+ // build single time for check spawnmask
+ std::map<uint32,uint32> spawnMasks;
+ for(uint32 i = 0; i < sMapStore.GetNumRows(); ++i)
+ if(sMapStore.LookupEntry(i))
+ for(int k = 0; k < MAX_DIFFICULTY; ++k)
+ if (GetMapDifficultyData(i,Difficulty(k)))
+ spawnMasks[i] |= (1 << k);
+
barGoLink bar(result->GetRowCount());
do
@@ -1580,12 +1575,18 @@ void ObjectMgr::LoadGameobjects()
uint32 entry = fields[ 1].GetUInt32();
GameObjectInfo const* gInfo = GetGameObjectInfo(entry);
- if (!gInfo)
+ if(!gInfo)
{
sLog.outErrorDb("Table `gameobject` has gameobject (GUID: %u) with non existing gameobject entry %u, skipped.", guid, entry);
continue;
}
+ if(!gInfo->displayId)
+ {
+ sLog.outErrorDb("Gameobject (GUID: %u Entry %u GoType: %u) doesn't have displayId (%u), not loaded.", guid, entry, gInfo->type, gInfo->displayId);
+ continue;
+ }
+
if (gInfo->displayId && !sGameObjectDisplayInfoStore.LookupEntry(gInfo->displayId))
{
sLog.outErrorDb("Gameobject (GUID: %u Entry %u GoType: %u) have invalid displayId (%u), not loaded.",guid, entry, gInfo->type, gInfo->displayId);
@@ -1606,6 +1607,13 @@ void ObjectMgr::LoadGameobjects()
data.rotation3 = fields[10].GetFloat();
data.spawntimesecs = fields[11].GetInt32();
+ MapEntry const* mapEntry = sMapStore.LookupEntry(data.mapid);
+ if(!mapEntry)
+ {
+ sLog.outErrorDb("Table `gameobject` have gameobject (GUID: %u Entry: %u) that spawned at not existed map (Id: %u), skip", guid, data.id, data.mapid);
+ continue;
+ }
+
if (data.spawntimesecs==0 && gInfo->IsDespawnAtAction())
{
sLog.outErrorDb("Table `gameobject` have gameobject (GUID: %u Entry: %u) with `spawntimesecs` (0) value, but gameobejct marked as despawnable at action.",guid,data.id);
@@ -1623,6 +1631,10 @@ void ObjectMgr::LoadGameobjects()
data.go_state = GOState(go_state);
data.spawnMask = fields[14].GetUInt8();
+
+ if (data.spawnMask & ~spawnMasks[data.mapid])
+ sLog.outErrorDb("Table `gameobject` have gameobject (GUID: %u Entry: %u) that have wrong spawn mask %u including not supported difficulty modes for map (Id: %u), skip", guid, data.id, data.spawnMask, data.mapid);
+
data.phaseMask = fields[15].GetUInt16();
int16 gameEvent = fields[16].GetInt16();
int16 PoolId = fields[17].GetInt16();
@@ -1804,13 +1816,6 @@ bool ObjectMgr::GetPlayerNameByGUID(const uint64 &guid, std::string &name) const
return true;
}
- PCachePlayerInfo pInfo = GetPlayerInfoFromCache(GUID_LOPART(guid));
- if(pInfo)
- {
- name = pInfo->sPlayerName.c_str();
- return true;
- }
-
QueryResult *result = CharacterDatabase.PQuery("SELECT name FROM characters WHERE guid = '%u'", GUID_LOPART(guid));
if(result)
@@ -1825,6 +1830,12 @@ bool ObjectMgr::GetPlayerNameByGUID(const uint64 &guid, std::string &name) const
uint32 ObjectMgr::GetPlayerTeamByGUID(const uint64 &guid) const
{
+ // prevent DB access for online player
+ if(Player* player = GetPlayer(guid))
+ {
+ return Player::TeamForRace(player->getRace());
+ }
+
QueryResult *result = CharacterDatabase.PQuery("SELECT race FROM characters WHERE guid = '%u'", GUID_LOPART(guid));
if(result)
@@ -1839,6 +1850,12 @@ uint32 ObjectMgr::GetPlayerTeamByGUID(const uint64 &guid) const
uint32 ObjectMgr::GetPlayerAccountIdByGUID(const uint64 &guid) const
{
+ // prevent DB access for online player
+ if(Player* player = GetPlayer(guid))
+ {
+ return player->GetSession()->GetAccountId();
+ }
+
QueryResult *result = CharacterDatabase.PQuery("SELECT account FROM characters WHERE guid = '%u'", GUID_LOPART(guid));
if(result)
{
@@ -3319,9 +3336,9 @@ void ObjectMgr::LoadGroups()
Group *group = NULL;
uint64 leaderGuid = 0;
uint32 count = 0;
- // 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
- QueryResult *result = CharacterDatabase.Query("SELECT mainTank, mainAssistant, lootMethod, looterGuid, lootThreshold, icon1, icon2, icon3, icon4, icon5, icon6, icon7, icon8, isRaid, difficulty, leaderGuid FROM groups");
-
+ // 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
+ QueryResult *result = CharacterDatabase.Query("SELECT mainTank, mainAssistant, lootMethod, looterGuid, lootThreshold, icon1, icon2, icon3, icon4, icon5, icon6, icon7, icon8, isRaid, difficulty, raiddifficulty, leaderGuid FROM groups");
+
if( !result )
{
barGoLink bar( 1 );
@@ -3340,7 +3357,7 @@ void ObjectMgr::LoadGroups()
bar.step();
Field *fields = result->Fetch();
++count;
- leaderGuid = MAKE_NEW_GUID(fields[15].GetUInt32(),0,HIGHGUID_PLAYER);
+ leaderGuid = MAKE_NEW_GUID(fields[16].GetUInt32(),0,HIGHGUID_PLAYER);
group = new Group;
if(!group->LoadGroupFromDB(leaderGuid, result, false))
@@ -3454,7 +3471,14 @@ void ObjectMgr::LoadGroups()
continue;
}
- InstanceSave *save = sInstanceSaveManager.AddInstanceSave(mapEntry->MapID, fields[2].GetUInt32(), fields[4].GetUInt8(), (time_t)fields[5].GetUInt64(), (fields[6].GetUInt32() == 0), true);
+ uint32 diff = fields[4].GetUInt8();
+ if(diff >= (mapEntry->IsRaid() ? MAX_RAID_DIFFICULTY : MAX_DUNGEON_DIFFICULTY))
+ {
+ sLog.outErrorDb("Wrong dungeon difficulty use in group_instance table: %d", diff + 1);
+ diff = 0; // default for both difficaly types
+ }
+
+ InstanceSave *save = sInstanceSaveManager.AddInstanceSave(mapEntry->MapID, fields[2].GetUInt32(), Difficulty(diff), (time_t)fields[5].GetUInt64(), (fields[6].GetUInt32() == 0), true);
group->BindToInstance(save, fields[3].GetBool(), true);
}while( result->NextRow() );
delete result;
@@ -3484,31 +3508,31 @@ void ObjectMgr::LoadQuests()
"QuestFlags, SpecialFlags, CharTitleId, PlayersSlain, BonusTalents, PrevQuestId, NextQuestId, ExclusiveGroup, NextQuestInChain, SrcItemId, SrcItemCount, SrcSpell,"
// 29 30 31 32 33 34 35 36 37 38
"Title, Details, Objectives, OfferRewardText, RequestItemsText, EndText, ObjectiveText1, ObjectiveText2, ObjectiveText3, ObjectiveText4,"
- // 39 40 41 42 43 44 45 46
- "ReqItemId1, ReqItemId2, ReqItemId3, ReqItemId4, ReqItemCount1, ReqItemCount2, ReqItemCount3, ReqItemCount4,"
- // 47 48 49 50 51 52 53 54
+ // 39 40 41 42 43 44 45 46 47 48 49 50
+ "ReqItemId1, ReqItemId2, ReqItemId3, ReqItemId4, ReqItemId5, ReqItemId6, ReqItemCount1, ReqItemCount2, ReqItemCount3, ReqItemCount4, ReqItemCount5, ReqItemCount6,"
+ // 51 52 53 54 55 56 57 58
"ReqSourceId1, ReqSourceId2, ReqSourceId3, ReqSourceId4, ReqSourceCount1, ReqSourceCount2, ReqSourceCount3, ReqSourceCount4,"
- // 55 56 57 58 59 60 61 62
+ // 59 60 61 62 63 64 65 66
"ReqCreatureOrGOId1, ReqCreatureOrGOId2, ReqCreatureOrGOId3, ReqCreatureOrGOId4, ReqCreatureOrGOCount1, ReqCreatureOrGOCount2, ReqCreatureOrGOCount3, ReqCreatureOrGOCount4,"
- // 63 64 65 66
+ // 67 68 69 70
"ReqSpellCast1, ReqSpellCast2, ReqSpellCast3, ReqSpellCast4,"
- // 67 68 69 70 71 72
+ // 71 72 73 74 75 76
"RewChoiceItemId1, RewChoiceItemId2, RewChoiceItemId3, RewChoiceItemId4, RewChoiceItemId5, RewChoiceItemId6,"
- // 73 74 75 76 77 78
+ // 77 78 79 80 81 82
"RewChoiceItemCount1, RewChoiceItemCount2, RewChoiceItemCount3, RewChoiceItemCount4, RewChoiceItemCount5, RewChoiceItemCount6,"
- // 79 80 81 82 83 84 85 86
+ // 83 84 85 86 87 88 89 90
"RewItemId1, RewItemId2, RewItemId3, RewItemId4, RewItemCount1, RewItemCount2, RewItemCount3, RewItemCount4,"
- // 87 88 89 90 91 92 93 94 95 96
+ // 91 92 93 94 95 96 97 98 99 100
"RewRepFaction1, RewRepFaction2, RewRepFaction3, RewRepFaction4, RewRepFaction5, RewRepValue1, RewRepValue2, RewRepValue3, RewRepValue4, RewRepValue5,"
- // 97 98 99 100 101 102 103 104 105 106 107
+ // 101 102 103 104 105 106 107 108 109 110 111
"RewHonorableKills, RewOrReqMoney, RewMoneyMaxLevel, RewSpell, RewSpellCast, RewMailTemplateId, RewMailDelaySecs, PointMapId, PointX, PointY, PointOpt,"
- // 108 109 110 111 112 113 114 115
+ // 112 113 114 115 116 117 118 119
"DetailsEmote1, DetailsEmote2, DetailsEmote3, DetailsEmote4, DetailsEmoteDelay1, DetailsEmoteDelay2, DetailsEmoteDelay3, DetailsEmoteDelay4,"
- // 116 117 118 119 120 121
+ // 120 121 122 123 124 125
"IncompleteEmote, CompleteEmote, OfferRewardEmote1, OfferRewardEmote2, OfferRewardEmote3, OfferRewardEmote4,"
- // 122 123 124 125
+ // 126 127 128 129
"OfferRewardEmoteDelay1, OfferRewardEmoteDelay2, OfferRewardEmoteDelay3, OfferRewardEmoteDelay4,"
- // 126 127
+ // 130 131
"StartScript, CompleteScript"
" FROM quest_template");
if(result == NULL)
@@ -3537,8 +3561,7 @@ void ObjectMgr::LoadQuests()
delete result;
-
- std::map<uint32,uint32> usedMailTemplates;
+ std::map<uint32,uint32> usedMailTemplates;
// Post processing
for (QuestMap::iterator iter = mQuestTemplates.begin(); iter != mQuestTemplates.end(); ++iter)
@@ -3765,7 +3788,7 @@ void ObjectMgr::LoadQuests()
}
}
- for (uint8 j = 0; j < QUEST_OBJECTIVES_COUNT; ++j )
+ for (uint8 j = 0; j < QUEST_ITEM_OBJECTIVES_COUNT; ++j )
{
uint32 id = qinfo->ReqItemId[j];
if(id)
@@ -4057,7 +4080,7 @@ void ObjectMgr::LoadQuests()
if (qinfo->NextQuestInChain)
{
QuestMap::iterator qNextItr = mQuestTemplates.find(qinfo->NextQuestInChain);
- if (qNextItr == mQuestTemplates.end())
+ if(qNextItr == mQuestTemplates.end())
{
sLog.outErrorDb("Quest %u has `NextQuestInChain` = %u but quest %u does not exist, quest chain will not work.",
qinfo->GetQuestId(),qinfo->NextQuestInChain ,qinfo->NextQuestInChain );
@@ -4068,7 +4091,7 @@ void ObjectMgr::LoadQuests()
}
// fill additional data stores
- if (qinfo->PrevQuestId)
+ if(qinfo->PrevQuestId)
{
if (mQuestTemplates.find(abs(qinfo->GetPrevQuestId())) == mQuestTemplates.end())
{
@@ -4080,7 +4103,7 @@ void ObjectMgr::LoadQuests()
}
}
- if (qinfo->NextQuestId)
+ if(qinfo->NextQuestId)
{
QuestMap::iterator qNextItr = mQuestTemplates.find(abs(qinfo->GetNextQuestId()));
if (qNextItr == mQuestTemplates.end())
@@ -4094,9 +4117,9 @@ void ObjectMgr::LoadQuests()
}
}
- if (qinfo->ExclusiveGroup)
+ if(qinfo->ExclusiveGroup)
mExclusiveQuestGroups.insert(std::pair<int32, uint32>(qinfo->ExclusiveGroup, qinfo->GetQuestId()));
- if (qinfo->LimitTime)
+ if(qinfo->LimitTime)
qinfo->SetFlag(QUEST_TRINITY_FLAGS_TIMED);
}
@@ -4666,36 +4689,36 @@ void ObjectMgr::LoadWaypointScripts()
void ObjectMgr::LoadItemTexts()
{
QueryResult *result = CharacterDatabase.Query("SELECT id, text FROM item_text");
-
+
uint32 count = 0;
-
+
if( !result )
{
barGoLink bar( 1 );
bar.step();
-
+
sLog.outString();
sLog.outString( ">> Loaded %u item pages", count );
return;
}
-
+
barGoLink bar( result->GetRowCount() );
-
+
Field* fields;
do
{
bar.step();
-
+
fields = result->Fetch();
-
+
mItemTexts[ fields[0].GetUInt32() ] = fields[1].GetCppString();
-
+
++count;
-
+
} while ( result->NextRow() );
-
+
delete result;
-
+
sLog.outString();
sLog.outString( ">> Loaded %u item texts", count );
}
@@ -4813,37 +4836,17 @@ void ObjectMgr::LoadInstanceTemplate()
for (uint32 i = 0; i < sInstanceTemplate.MaxEntry; i++)
{
InstanceTemplate* temp = (InstanceTemplate*)GetInstanceTemplate(i);
- if(!temp) continue;
- const MapEntry* entry = sMapStore.LookupEntry(temp->map);
- if(!entry)
- {
- sLog.outErrorDb("ObjectMgr::LoadInstanceTemplate: bad mapid %d for template!", temp->map);
- continue;
- }
- else if(!entry->HasResetTime())
+ if(!temp)
continue;
- //FIXME: now exist heroic instance, normal/heroic raid instances
- // entry->resetTimeHeroic store reset time for both heroic mode instance (raid and non-raid)
- // entry->resetTimeRaid store reset time for normal raid only
- // for current state entry->resetTimeRaid == entry->resetTimeHeroic in case raid instances with heroic mode.
- // but at some point wee need implement reset time dependent from raid instance mode
- if(temp->reset_delay == 0)
+ if(!MapManager::IsValidMAP(temp->map))
+ sLog.outErrorDb("ObjectMgr::LoadInstanceTemplate: bad mapid %d for template!", temp->map);
+
+ if(!MapManager::IsValidMapCoord(temp->parent,temp->startLocX,temp->startLocY,temp->startLocZ,temp->startLocO))
{
- // use defaults from the DBC
- if(entry->resetTimeHeroic) // for both raid and non raids, read above
- {
- temp->reset_delay = entry->resetTimeHeroic / DAY;
- }
- else if (entry->resetTimeRaid && entry->map_type == MAP_RAID)
- // for normal raid only
- {
- temp->reset_delay = entry->resetTimeRaid / DAY;
- }
+ sLog.outErrorDb("ObjectMgr::LoadInstanceTemplate: bad parent entrance coordinates for map id %d template!", temp->map);
+ temp->parent = 0; // will have wrong continent 0 parent, at least existed
}
-
- // the reset_delay must be at least one day
- temp->reset_delay = std::max((uint32)1, (uint32)(temp->reset_delay * sWorld.getRate(RATE_INSTANCE_RESET_TIME)));
}
sLog.outString( ">> Loaded %u Instance Template definitions", sInstanceTemplate.RecordCount );
@@ -5250,6 +5253,7 @@ void ObjectMgr::LoadAreaTriggerScripts()
sLog.outString( ">> Loaded %u areatrigger scripts", count );
}
+// use searched_node for search some known node
uint32 ObjectMgr::GetNearestTaxiNode( float x, float y, float z, uint32 mapid, uint32 team )
{
bool found = false;
@@ -5259,7 +5263,8 @@ uint32 ObjectMgr::GetNearestTaxiNode( float x, float y, float z, uint32 mapid, u
for (uint32 i = 1; i < sTaxiNodesStore.GetNumRows(); ++i)
{
TaxiNodesEntry const* node = sTaxiNodesStore.LookupEntry(i);
- if(!node || node->map_id != mapid || !node->MountCreatureID[team == ALLIANCE ? 1 : 0] && node->MountCreatureID[0] != 32981) // dk flight
+
+ if(!node || node->map_id != mapid || !node->MountCreatureID[team == ALLIANCE ? 1 : 0] && node->MountCreatureID[0] != 32981) // dk flight
continue;
uint8 field = (uint8)((i - 1) / 32);
@@ -5269,7 +5274,7 @@ uint32 ObjectMgr::GetNearestTaxiNode( float x, float y, float z, uint32 mapid, u
if((sTaxiNodesMask[field] & submask)==0)
continue;
- float dist2 = (node->x - x)*(node->x - x)+(node->y - y)*(node->y - y)+(node->z - z)*(node->z - z);
+ float dist2 = (node->x - x)*(node->x - x)+(node->y - y)*(node->y - y)+(node->z - z)*(node->z - z);
if(found)
{
if(dist2 < dist)
@@ -5479,7 +5484,7 @@ WorldSafeLocsEntry const *ObjectMgr::GetClosestGraveYard(float x, float y, float
if(graveLow==graveUp && !map->IsBattleArena())
{
- sLog.outErrorDb("Table `game_graveyard_zone` incomplete: Zone %u Team %u does not have a linked graveyard.",zoneId,team);
+ //sLog.outErrorDb("Table `game_graveyard_zone` incomplete: Zone %u Team %u does not have a linked graveyard.",zoneId,team);
return NULL;
}
diff --git a/src/game/ObjectMgr.h b/src/game/ObjectMgr.h
index 1c5367387fc..440763c21cc 100644
--- a/src/game/ObjectMgr.h
+++ b/src/game/ObjectMgr.h
@@ -257,23 +257,6 @@ enum ConditionType
#define MAX_CONDITION 14 // maximum value in ConditionType enum
-//Player's info
-typedef struct _tagCachePlayerInfo
-{
- std::string sPlayerName;
- uint32 unfield;
- uint32 unLevel;
- uint8 unClass;
-//Arena
- uint32 unArenaInfoId0;
- uint32 unArenaInfoId1;
- uint32 unArenaInfoId2;
- uint32 unArenaInfoSlot0;
- uint32 unArenaInfoSlot1;
- uint32 unArenaInfoSlot2;
-}CachePlayerInfo, *PCachePlayerInfo;
-typedef UNORDERED_MAP<uint32, PCachePlayerInfo> CachePlayerInfoMap;
-
struct PlayerCondition
{
ConditionType condition; // additional condition type
@@ -641,10 +624,6 @@ class ObjectMgr
uint32 GenerateMailID();
uint32 GeneratePetNumber();
- void LoadPlayerInfoInCache();
- PCachePlayerInfo GetPlayerInfoFromCache(uint32 unPlayerGuid) const;
- CachePlayerInfoMap m_mPlayerInfoMap;
-
uint32 CreateItemText(std::string text);
void AddItemText(uint32 itemTextId, std::string text) { mItemTexts[itemTextId] = text; }
std::string GetItemText( uint32 id )
diff --git a/src/game/Opcodes.cpp b/src/game/Opcodes.cpp
index ba1deaeff7c..6dc88c9d37a 100644
--- a/src/game/Opcodes.cpp
+++ b/src/game/Opcodes.cpp
@@ -347,7 +347,7 @@ OpcodeHandler opcodeTable[NUM_MSG_TYPES] =
/*0x13C*/ { "SMSG_AI_REACTION", STATUS_NEVER, &WorldSession::Handle_ServerSide },
/*0x13D*/ { "CMSG_SET_SELECTION", STATUS_LOGGEDIN, &WorldSession::HandleSetSelectionOpcode },
/*0x13E*/ { "CMSG_EQUIPMENT_SET_DELETE", STATUS_LOGGEDIN, &WorldSession::HandleEquipmentSetDelete },
- /*0x13F*/ { "CMSG_INSTANCE_LOCK_RESPONSE", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x13F*/ { "CMSG_INSTANCE_LOCK_WARNING_RESPONSE", STATUS_NEVER, &WorldSession::Handle_NULL },
/*0x140*/ { "CMSG_UNUSED2", STATUS_NEVER, &WorldSession::Handle_NULL },
/*0x141*/ { "CMSG_ATTACKSWING", STATUS_LOGGEDIN, &WorldSession::HandleAttackSwingOpcode },
/*0x142*/ { "CMSG_ATTACKSTOP", STATUS_LOGGEDIN, &WorldSession::HandleAttackStopOpcode },
@@ -355,7 +355,7 @@ OpcodeHandler opcodeTable[NUM_MSG_TYPES] =
/*0x144*/ { "SMSG_ATTACKSTOP", STATUS_NEVER, &WorldSession::Handle_ServerSide },
/*0x145*/ { "SMSG_ATTACKSWING_NOTINRANGE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
/*0x146*/ { "SMSG_ATTACKSWING_BADFACING", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x147*/ { "SMSG_ATTACKSWING_NOTSTANDING", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x147*/ { "SMSG_INSTANCE_LOCK_WARNING_QUERY", STATUS_NEVER, &WorldSession::Handle_ServerSide },
/*0x148*/ { "SMSG_ATTACKSWING_DEADTARGET", STATUS_NEVER, &WorldSession::Handle_ServerSide },
/*0x149*/ { "SMSG_ATTACKSWING_CANT_ATTACK", STATUS_NEVER, &WorldSession::Handle_ServerSide },
/*0x14A*/ { "SMSG_ATTACKERSTATEUPDATE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
@@ -547,11 +547,11 @@ OpcodeHandler opcodeTable[NUM_MSG_TYPES] =
/*0x204*/ { "CMSG_DECHARGE", STATUS_NEVER, &WorldSession::Handle_NULL },
/*0x205*/ { "CMSG_GMTICKET_CREATE", STATUS_LOGGEDIN, &WorldSession::HandleGMTicketCreateOpcode },
/*0x206*/ { "SMSG_GMTICKET_CREATE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x207*/ { "CMSG_GMTICKET_UPDATETEXT", STATUS_LOGGEDIN, &WorldSession::HandleGMTicketUpdateOpcode },
+ /*0x207*/ { "CMSG_GMTICKET_UPDATETEXT", STATUS_LOGGEDIN, &WorldSession::HandleGMTicketUpdateOpcode },
/*0x208*/ { "SMSG_GMTICKET_UPDATETEXT", STATUS_NEVER, &WorldSession::Handle_ServerSide },
/*0x209*/ { "SMSG_ACCOUNT_DATA_TIMES", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x20A*/ { "CMSG_REQUEST_ACCOUNT_DATA", STATUS_LOGGEDIN, &WorldSession::HandleRequestAccountData },
- /*0x20B*/ { "CMSG_UPDATE_ACCOUNT_DATA", STATUS_LOGGEDIN_OR_RECENTLY_LOGGOUT, &WorldSession::HandleUpdateAccountData},
+ /*0x20A*/ { "CMSG_REQUEST_ACCOUNT_DATA", STATUS_AUTHED, &WorldSession::HandleRequestAccountData },
+ /*0x20B*/ { "CMSG_UPDATE_ACCOUNT_DATA", STATUS_AUTHED, &WorldSession::HandleUpdateAccountData },
/*0x20C*/ { "SMSG_UPDATE_ACCOUNT_DATA", STATUS_NEVER, &WorldSession::Handle_ServerSide },
/*0x20D*/ { "SMSG_CLEAR_FAR_SIGHT_IMMEDIATE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
/*0x20E*/ { "SMSG_POWERGAINLOG_OBSOLETE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
@@ -686,8 +686,8 @@ OpcodeHandler opcodeTable[NUM_MSG_TYPES] =
/*0x28F*/ { "CMSG_GROUP_ASSISTANT_LEADER", STATUS_LOGGEDIN, &WorldSession::HandleGroupAssistantLeaderOpcode},
/*0x290*/ { "CMSG_BUYBACK_ITEM", STATUS_LOGGEDIN, &WorldSession::HandleBuybackItem },
/*0x291*/ { "SMSG_SERVER_MESSAGE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x292*/ { "CMSG_MEETINGSTONE_JOIN", STATUS_NEVER, &WorldSession::Handle_NULL },
- /*0x293*/ { "CMSG_MEETINGSTONE_LEAVE", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x292*/ { "CMSG_SET_SAVED_INSTANCE_EXTEND", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x293*/ { "CMSG_MEETINGSTONE_LEAVE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
/*0x294*/ { "CMSG_MEETINGSTONE_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL },
/*0x295*/ { "SMSG_MEETINGSTONE_SETQUEUE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
/*0x296*/ { "CMSG_MEETINGSTONE_INFO", STATUS_LOGGEDIN, &WorldSession::HandleMeetingStoneInfo },
@@ -1069,7 +1069,7 @@ OpcodeHandler opcodeTable[NUM_MSG_TYPES] =
/*0x40E*/ { "CMSG_REFER_A_FRIEND", STATUS_NEVER, &WorldSession::Handle_NULL },
/*0x40F*/ { "CMSG_DECLINE_CHANNEL_INVITE", STATUS_LOGGEDIN, &WorldSession::HandleChannelDeclineInvite },
/*0x410*/ { "CMSG_DECLINE_CHANNEL_INVITE", STATUS_NEVER, &WorldSession::Handle_NULL },
- /*0x411*/ { "CMSG_GROUPACTION_THROTTLED", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x411*/ { "SMSG_GROUPACTION_THROTTLED", STATUS_NEVER, &WorldSession::Handle_ServerSide },
/*0x412*/ { "SMSG_OVERRIDE_LIGHT", STATUS_NEVER, &WorldSession::Handle_ServerSide },
/*0x413*/ { "SMSG_TOTEM_CREATED", STATUS_NEVER, &WorldSession::Handle_ServerSide },
/*0x414*/ { "CMSG_TOTEM_DESTROYED", STATUS_LOGGEDIN, &WorldSession::HandleTotemDestroyed },
@@ -1230,12 +1230,12 @@ OpcodeHandler opcodeTable[NUM_MSG_TYPES] =
/*0x4AF*/ { "UMSG_UNKNOWN_1199", STATUS_NEVER, &WorldSession::Handle_NULL },
/*0x4B0*/ { "UMSG_UNKNOWN_1200", STATUS_NEVER, &WorldSession::Handle_NULL },
/*0x4B1*/ { "UMSG_UNKNOWN_1201", STATUS_NEVER, &WorldSession::Handle_NULL },
- /*0x4B2*/ { "SMSG_UNKNOWN_1202", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x4B3*/ { "UMSG_UNKNOWN_1203", STATUS_NEVER, &WorldSession::Handle_NULL },
- /*0x4B4*/ { "UMSG_UNKNOWN_1204", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x4B2*/ { "SMSG_ITEM_REFUND_TIMER", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x4B3*/ { "CMSG_ITEM_REFUND_INFO_REQUEST", STATUS_LOGGEDIN, &WorldSession::HandleItemRefundInfoRequest },
+ /*0x4B4*/ { "CMSG_ITEM_REFUND", STATUS_LOGGEDIN, &WorldSession::HandleItemRefund },
/*0x4B5*/ { "SMSG_UNKNOWN_1205", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x4B6*/ { "CMSG_UNKNOWN_1206", STATUS_NEVER, &WorldSession::Handle_NULL },
- /*0x4B7*/ { "SMSG_UNKNOWN_1207", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x4B6*/ { "CMSG_CORPSE_MAP_POSITION_QUERY", STATUS_LOGGEDIN, &WorldSession::HandleCorpseMapPositionQuery },
+ /*0x4B7*/ { "CMSG_CORPSE_MAP_POSITION_QUERY_RESPONSE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
/*0x4B8*/ { "CMSG_LFG_SET_ROLES", STATUS_LOGGEDIN, &WorldSession::HandleLfgSetRoles },
/*0x4B9*/ { "UMSG_UNKNOWN_1209", STATUS_NEVER, &WorldSession::Handle_NULL },
/*0x4BA*/ { "CMSG_UNKNOWN_1210", STATUS_NEVER, &WorldSession::Handle_NULL },
@@ -1255,7 +1255,50 @@ OpcodeHandler opcodeTable[NUM_MSG_TYPES] =
/*0x4C8*/ { "SMSG_UNKNOWN_1224", STATUS_NEVER, &WorldSession::Handle_ServerSide },
/*0x4C9*/ { "UMSG_UNKNOWN_1225", STATUS_NEVER, &WorldSession::Handle_NULL },
/*0x4CA*/ { "UMSG_UNKNOWN_1226", STATUS_NEVER, &WorldSession::Handle_NULL },
- /*0x4CB*/ { "CMSG_EQUIPMENT_SET_USE", STATUS_LOGGEDIN, &WorldSession::HandleEquipmentSetUse },
- /*0x4CC*/ { "SMSG_EQUIPMENT_SET_USE_RESULT", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x4CB*/ { "UMSG_UNKNOWN_1227", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x4CC*/ { "UMSG_UNKNOWN_1228", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x4CD*/ { "SMSG_UNKNOWN_1229", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x4CE*/ { "SMSG_UNKNOWN_1230", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x4CF*/ { "CMSG_UNKNOWN_1231_ACK", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x4D0*/ { "SMSG_UNKNOWN_1232", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x4D1*/ { "CMSG_UNKNOWN_1233_ACK", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x4D2*/ { "SMSG_UNKNOWN_1234", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x4D3*/ { "SMSG_UNKNOWN_1235", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x4D4*/ { "SMSG_UNKNOWN_1236", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x4D5*/ { "CMSG_EQUIPMENT_SET_USE", STATUS_LOGGEDIN, &WorldSession::HandleEquipmentSetUse },
+ /*0x4D6*/ { "SMSG_EQUIPMENT_SET_USE_RESULT", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x4D7*/ { "UMSG_UNKNOWN_1239", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x4D8*/ { "SMSG_UNKNOWN_1240", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x4D9*/ { "CMSG_UNKNOWN_1241", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x4DA*/ { "SMSG_UNKNOWN_1242", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x4DB*/ { "UMSG_UNKNOWN_1243", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x4DC*/ { "UMSG_UNKNOWN_1244", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x4DD*/ { "UMSG_UNKNOWN_1245", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x4DE*/ { "SMSG_UNKNOWN_1246", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x4DF*/ { "CMSG_UNKNOWN_1247", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x4E0*/ { "SMSG_UNKNOWN_1248", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x4E1*/ { "SMSG_UNKNOWN_1249", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x4E2*/ { "CMSG_UNKNOWN_1250", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x4E3*/ { "CMSG_UNKNOWN_1251", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x4E4*/ { "SMSG_UNKNOWN_1252", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x4E5*/ { "SMSG_UNKNOWN_1253", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x4E6*/ { "SMSG_UNKNOWN_1254", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x4E7*/ { "CMSG_UNKNOWN_1255", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x4E8*/ { "SMSG_UNKNOWN_1256", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x4E9*/ { "UMSG_UNKNOWN_1257", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x4EA*/ { "UMSG_UNKNOWN_1258", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x4EB*/ { "MSG_SET_RAID_DIFFICULTY", STATUS_LOGGEDIN, &WorldSession::HandleSetRaidDifficultyOpcode },
+ /*0x4EC*/ { "UMSG_UNKNOWN_1260", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x4ED*/ { "SMSG_TOGGLE_XP_GAIN", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x4EE*/ { "SMSG_UNKNOWN_1262", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x4EF*/ { "SMSG_UNKNOWN_1263", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x4F0*/ { "CMSG_UNKNOWN_1264", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x4F1*/ { "SMSG_UNKNOWN_1265", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x4F2*/ { "UMSG_UNKNOWN_1266", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x4F3*/ { "UMSG_UNKNOWN_1267", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x4F4*/ { "UMSG_UNKNOWN_1268", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x4F5*/ { "UMSG_UNKNOWN_1269", STATUS_NEVER, &WorldSession::Handle_NULL },
+ /*0x4F6*/ { "CMSG_WORLD_STATE_UI_TIMER_UPDATE", STATUS_LOGGEDIN, &WorldSession::HandleWorldStateUITimerUpdate },
+ /*0x4F7*/ { "SMSG_WORLD_STATE_UI_TIMER_UPDATE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
+ /*0x4F8*/ { "CMSG_UNKNOWN_1272", STATUS_NEVER, &WorldSession::Handle_NULL },
};
-
diff --git a/src/game/Opcodes.h b/src/game/Opcodes.h
index c3371f866b6..007e17f1687 100644
--- a/src/game/Opcodes.h
+++ b/src/game/Opcodes.h
@@ -355,7 +355,7 @@ enum Opcodes
SMSG_AI_REACTION = 0x13C,
CMSG_SET_SELECTION = 0x13D,
CMSG_EQUIPMENT_SET_DELETE = 0x13E,
- CMSG_INSTANCE_LOCK_RESPONSE = 0x13F,
+ CMSG_INSTANCE_LOCK_WARNING_RESPONSE = 0x13F,
CMSG_UNUSED2 = 0x140,
CMSG_ATTACKSWING = 0x141,
CMSG_ATTACKSTOP = 0x142,
@@ -363,7 +363,7 @@ enum Opcodes
SMSG_ATTACKSTOP = 0x144,
SMSG_ATTACKSWING_NOTINRANGE = 0x145,
SMSG_ATTACKSWING_BADFACING = 0x146,
- SMSG_INSTANCE_LOCK_QUERY = 0x147,
+ SMSG_INSTANCE_LOCK_WARNING_QUERY = 0x147,
SMSG_ATTACKSWING_DEADTARGET = 0x148,
SMSG_ATTACKSWING_CANT_ATTACK = 0x149,
SMSG_ATTACKERSTATEUPDATE = 0x14A,
@@ -519,8 +519,8 @@ enum Opcodes
CMSG_SETSHEATHED = 0x1E0,
SMSG_COOLDOWN_CHEAT = 0x1E1,
SMSG_SPELL_DELAYED = 0x1E2,
- CMSG_PLAYER_MACRO_OBSOLETE = 0x1E3,
- SMSG_PLAYER_MACRO_OBSOLETE = 0x1E4,
+ CMSG_QUEST_POI_QUERY = 0x1E3,
+ SMSG_QUEST_POI_QUERY_RESPONSE = 0x1E4,
CMSG_GHOST = 0x1E5,
CMSG_GM_INVIS = 0x1E6,
SMSG_INVALID_PROMOTION_CODE = 0x1E7,
@@ -694,7 +694,7 @@ enum Opcodes
CMSG_GROUP_ASSISTANT_LEADER = 0x28F,
CMSG_BUYBACK_ITEM = 0x290,
SMSG_SERVER_MESSAGE = 0x291,
- CMSG_MEETINGSTONE_JOIN = 0x292, // lua: SetSavedInstanceExtend
+ CMSG_SET_SAVED_INSTANCE_EXTEND = 0x292, // lua: SetSavedInstanceExtend
SMSG_MEETINGSTONE_LEAVE = 0x293,
CMSG_MEETINGSTONE_CHEAT = 0x294,
SMSG_MEETINGSTONE_SETQUEUE = 0x295,
@@ -1077,7 +1077,7 @@ enum Opcodes
CMSG_REFER_A_FRIEND = 0x40E,
MSG_GM_CHANGE_ARENA_RATING = 0x40F,
CMSG_DECLINE_CHANNEL_INVITE = 0x410,
- CMSG_GROUPACTION_THROTTLED = 0x411,
+ SMSG_GROUPACTION_THROTTLED = 0x411, // SMSG?
SMSG_OVERRIDE_LIGHT = 0x412,
SMSG_TOTEM_CREATED = 0x413,
CMSG_TOTEM_DESTROYED = 0x414,
@@ -1226,7 +1226,7 @@ enum Opcodes
SMSG_SERVER_BUCK_DATA_START = 0x4A3, // not found
CMSG_QUERY_VEHICLE_STATUS = 0x4A4, // not found
UMSG_UNKNOWN_1189 = 0x4A5, // not found, old SMSG_PET_GUIDS
- SMSG_UNKNOWN_1190 = 0x4A6, // smsg unk, old SMSG_CLIENTCACHE_VERSION
+ SMSG_UNKNOWN_1190 = 0x4A6, // smsg unk, "You can't do that yet"
SMSG_UNKNOWN_1191 = 0x4A7, // smsg guid+uint32 (vehicle)
CMSG_UNKNOWN_1192 = 0x4A8, // cmsg uint64
CMSG_EJECT_PASSENGER = 0x4A9, // cmsg uint64
@@ -1238,12 +1238,12 @@ enum Opcodes
UMSG_UNKNOWN_1199 = 0x4AF, // not found
UMSG_UNKNOWN_1200 = 0x4B0, // not found
UMSG_UNKNOWN_1201 = 0x4B1, // not found
- SMSG_UNKNOWN_1202 = 0x4B2, // refund something
- CMSG_UNKNOWN_1203 = 0x4B3, // refund request?
- CMSG_UNKNOWN_1204 = 0x4B4, // lua: ContainerRefundItemPurchase
- SMSG_UNKNOWN_1205 = 0x4B5, // refund something
- CMSG_UNKNOWN_1206 = 0x4B6, // CMSG, uint32
- SMSG_UNKNOWN_1207 = 0x4B7, // SMSG, string+float
+ SMSG_ITEM_REFUND_TIMER = 0x4B2, // refund something
+ CMSG_ITEM_REFUND_INFO_REQUEST = 0x4B3, // refund request?
+ CMSG_ITEM_REFUND = 0x4B4, // lua: ContainerRefundItemPurchase
+ SMSG_ITEM_REFUND = 0x4B5, // refund something
+ CMSG_CORPSE_MAP_POSITION_QUERY = 0x4B6, // CMSG, uint32
+ CMSG_CORPSE_MAP_POSITION_QUERY_RESPONSE = 0x4B7, // SMSG, 3*float+float
CMSG_LFG_SET_ROLES = 0x4B8, // CMSG, empty, lua: SetLFGRoles
UMSG_UNKNOWN_1209 = 0x4B9, // not found
CMSG_UNKNOWN_1210 = 0x4BA, // CMSG, uint64, lua: CalendarContextEventSignUp
@@ -1255,17 +1255,61 @@ enum Opcodes
SMSG_TALENTS_INFO = 0x4C0, // SMSG, talents related
CMSG_LEARN_PREVIEW_TALENTS = 0x4C1, // CMSG, lua: LearnPreviewTalents (for player?)
CMSG_LEARN_PREVIEW_TALENTS_PET = 0x4C2, // CMSG, lua: LearnPreviewTalents (for pet?)
- UMSG_UNKNOWN_1219 = 0x4C3, // not found
- UMSG_UNKNOWN_1220 = 0x4C4, // not found
- UMSG_UNKNOWN_1221 = 0x4C5, // not found
- UMSG_UNKNOWN_1222 = 0x4C6, // not found
- SMSG_UNKNOWN_1223 = 0x4C7, // uint64, arena pet?
- SMSG_UNKNOWN_1224 = 0x4C8, // uint32 "Can't change arena team..."
- UMSG_UNKNOWN_1225 = 0x4C9, // not found
- UMSG_UNKNOWN_1226 = 0x4CA, // not found
- CMSG_EQUIPMENT_SET_USE = 0x4CB, // CMSG, lua: UseEquipmentSet
- SMSG_EQUIPMENT_SET_USE_RESULT = 0x4CC, // SMSG, UseEquipmentSetResult?
- NUM_MSG_TYPES = 0x4CD
+ UMSG_UNKNOWN_1219 = 0x4C3, // not found 3.2
+ UMSG_UNKNOWN_1220 = 0x4C4, // not found 3.2
+ UMSG_UNKNOWN_1221 = 0x4C5, // not found 3.2
+ UMSG_UNKNOWN_1222 = 0x4C6, // not found 3.2
+ SMSG_UNKNOWN_1223 = 0x4C7, // uint64, arena pet? 3.2
+ SMSG_UNKNOWN_1224 = 0x4C8, // uint32 "Can't modify arena team while queued or in a match." 3.2
+ UMSG_UNKNOWN_1225 = 0x4C9, // not found 3.2
+ UMSG_UNKNOWN_1226 = 0x4CA, // not found 3.2
+ UMSG_UNKNOWN_1227 = 0x4CB, // not found 3.2
+ UMSG_UNKNOWN_1228 = 0x4CC, // not found 3.2
+ SMSG_UNKNOWN_1229 = 0x4CD, // SMSG, any opcode?
+ SMSG_UNKNOWN_1230 = 0x4CE, // SMSG, movement related
+ CMSG_UNKNOWN_1231_ACK = 0x4CF, // movement related
+ SMSG_UNKNOWN_1232 = 0x4D0, // SMSG, movement related
+ CMSG_UNKNOWN_1233_ACK = 0x4D1, // movement related
+ SMSG_UNKNOWN_1234 = 0x4D2, // SMSG, movement related
+ SMSG_UNKNOWN_1235 = 0x4D3, // SMSG, movement related
+ SMSG_UNKNOWN_1236 = 0x4D4, // SMSG, movement related
+ CMSG_EQUIPMENT_SET_USE = 0x4D5, // CMSG, lua: UseEquipmentSet
+ SMSG_EQUIPMENT_SET_USE_RESULT = 0x4D6, // SMSG, UseEquipmentSetResult?
+ UMSG_UNKNOWN_1239 = 0x4D7, // not found 3.2
+ SMSG_UNKNOWN_1240 = 0x4D8, // SMSG, uint64, string
+ CMSG_CHAR_FACTION_CHANGE = 0x4D9, // lua: CreateCharacter (PFC client response)
+ SMSG_CHAR_FACTION_CHANGE = 0x4DA, // response to 1241 (PFC server response)
+ UMSG_UNKNOWN_1243 = 0x4DB, // not found 3.2
+ UMSG_UNKNOWN_1244 = 0x4DC, // not found 3.2
+ UMSG_UNKNOWN_1245 = 0x4DD, // not found 3.2
+ SMSG_UNKNOWN_1246 = 0x4DE, // uint32, BattlefieldMgrEntryInvite
+ CMSG_UNKNOWN_1247 = 0x4DF, // lua: BattlefieldMgrEntryInviteResponse
+ SMSG_UNKNOWN_1248 = 0x4E0, // uint32, uint8, uint8
+ SMSG_UNKNOWN_1249 = 0x4E1, // uint32 BattlefieldMgrQueueInvite
+ CMSG_UNKNOWN_1250 = 0x4E2, // lua: BattlefieldMgrQueueInviteResponse
+ CMSG_UNKNOWN_1251 = 0x4E3, // lua: BattlefieldMgrQueueRequest
+ SMSG_UNKNOWN_1252 = 0x4E4, // uint32, uint8 queue full/can't join
+ SMSG_UNKNOWN_1253 = 0x4E5, // uint32 wintergrasp is full, you'll be ejected soon
+ SMSG_UNKNOWN_1254 = 0x4E6, // uint32, uint32, uint8
+ CMSG_UNKNOWN_1255 = 0x4E7, // lua: BattlefieldMgrExitRequest
+ SMSG_UNKNOWN_1256 = 0x4E8, // uint32, uint32
+ UMSG_UNKNOWN_1257 = 0x4E9, // not found 3.2
+ UMSG_UNKNOWN_1258 = 0x4EA, // not found 3.2
+ MSG_SET_RAID_DIFFICULTY = 0x4EB, // lua: SetRaidDifficulty
+ UMSG_UNKNOWN_1260 = 0x4EC, // not found 3.2
+ SMSG_TOGGLE_XP_GAIN = 0x4ED, // enable/disable XP gain console message
+ SMSG_UNKNOWN_1262 = 0x4EE,
+ SMSG_UNKNOWN_1263 = 0x4EF,
+ CMSG_UNKNOWN_1264 = 0x4F0, // lua: GMResponseResolve
+ SMSG_UNKNOWN_1265 = 0x4F1,
+ UMSG_UNKNOWN_1266 = 0x4F2, // not found 3.2
+ UMSG_UNKNOWN_1267 = 0x4F3, // not found 3.2
+ UMSG_UNKNOWN_1268 = 0x4F4, // not found 3.2
+ UMSG_UNKNOWN_1269 = 0x4F5, // not found 3.2
+ CMSG_WORLD_STATE_UI_TIMER_UPDATE = 0x4F6,
+ SMSG_WORLD_STATE_UI_TIMER_UPDATE = 0x4F7,
+ CMSG_UNKNOWN_1272 = 0x4F8, // called from lua: CreateCharacter, paid race change
+ NUM_MSG_TYPES = 0x4F9
};
/// Player state
@@ -1298,4 +1342,3 @@ inline const char* LookupOpcodeName(uint16 id)
}
#endif
/// @}
-
diff --git a/src/game/OutdoorPvPWG.cpp b/src/game/OutdoorPvPWG.cpp
index 28cf16645e6..94389f1c812 100644
--- a/src/game/OutdoorPvPWG.cpp
+++ b/src/game/OutdoorPvPWG.cpp
@@ -801,14 +801,14 @@ void OutdoorPvPWG::SendInitWorldStatesTo(Player *player) const
data << uint32(571);
data << uint32(ZONE_WINTERGRASP);
data << uint32(0);
- data << uint16(4+5+4+m_buildingStates.size());
+ data << uint16(4+2+4+m_buildingStates.size());
data << uint32(3803) << uint32(getDefenderTeam() == TEAM_ALLIANCE ? 1 : 0);
data << uint32(3802) << uint32(getDefenderTeam() != TEAM_ALLIANCE ? 1 : 0);
data << uint32(3801) << uint32(isWarTime() ? 0 : 1);
data << uint32(3710) << uint32(isWarTime() ? 1 : 0);
- for (uint32 i = 0; i < 5; ++i)
+ for (uint32 i = 0; i < 2; ++i)
data << ClockWorldState[i] << m_clock[i];
data << uint32(3490) << uint32(m_vehicles[TEAM_HORDE].size());
@@ -1219,19 +1219,17 @@ void OutdoorPvPWG::UpdateClockDigit(uint32 &timer, uint32 digit, uint32 mod)
if (m_clock[digit] != value)
{
m_clock[digit] = value;
- SendUpdateWorldState(ClockWorldState[digit], value);
+ SendUpdateWorldState(ClockWorldState[digit], (timer + time(NULL)));
}
}
void OutdoorPvPWG::UpdateClock()
{
uint32 timer = m_timer / 1000;
- UpdateClockDigit(timer, 0, 10);
- UpdateClockDigit(timer, 1, 6);
- UpdateClockDigit(timer, 2, 10);
- UpdateClockDigit(timer, 3, 6);
if (!isWarTime())
- UpdateClockDigit(timer, 4, 10);
+ UpdateClockDigit(timer, 1, 10);
+ else
+ UpdateClockDigit(timer, 0, 10);
}
bool OutdoorPvPWG::Update(uint32 diff)
diff --git a/src/game/OutdoorPvPWG.h b/src/game/OutdoorPvPWG.h
index 63381b15f7b..c9700fe5123 100644
--- a/src/game/OutdoorPvPWG.h
+++ b/src/game/OutdoorPvPWG.h
@@ -29,7 +29,7 @@ const uint32 WintergraspFaction[3] = {1732, 1735, 35};
const uint32 WG_MARK_OF_HONOR = 43589;
const uint32 VehNumWorldState[2] = {3680,3490};
const uint32 MaxVehNumWorldState[2] = {3681,3491};
-const uint32 ClockWorldState[5] = {3785,3784,3782,3976,3975};
+const uint32 ClockWorldState[2] = {3781,4354};
enum OutdoorPvPWGSpell
{
@@ -268,7 +268,7 @@ class OutdoorPvPWG : public OutdoorPvP
bool m_wartime;
bool m_changeDefender;
uint32 m_timer;
- uint32 m_clock[5];
+ uint32 m_clock[2];
uint32 m_workshopCount[2];
uint32 m_towerDestroyedCount[2];
uint32 m_towerDamagedCount[2];
diff --git a/src/game/Pet.cpp b/src/game/Pet.cpp
index 95f1300a1bb..373f611094b 100644
--- a/src/game/Pet.cpp
+++ b/src/game/Pet.cpp
@@ -435,8 +435,7 @@ void Pet::SavePetToDB(PetSaveMode mode)
<< curmana << ", "
<< GetPower(POWER_HAPPINESS) << ", '";
- // save only spell slots from action bar
- for (uint32 i = ACTION_BAR_INDEX_PET_SPELL_START; i < ACTION_BAR_INDEX_PET_SPELL_END; ++i)
+ for(uint32 i = ACTION_BAR_INDEX_START; i < ACTION_BAR_INDEX_END; ++i)
{
ss << uint32(m_charmInfo->GetActionBarEntry(i)->GetType()) << " "
<< uint32(m_charmInfo->GetActionBarEntry(i)->GetAction()) << " ";
diff --git a/src/game/PetHandler.cpp b/src/game/PetHandler.cpp
index 41cafc3c7a4..1b2503eed0b 100644
--- a/src/game/PetHandler.cpp
+++ b/src/game/PetHandler.cpp
@@ -400,22 +400,64 @@ void WorldSession::HandlePetSetAction( WorldPacket & recv_data )
}
count = (recv_data.size() == 24) ? 2 : 1;
- for (uint8 i = 0; i < count; ++i)
- {
- uint32 position;
- uint32 data;
-
- recv_data >> position;
- recv_data >> data;
-
- uint32 spell_id = UNIT_ACTION_BUTTON_ACTION(data);
- uint8 act_state = UNIT_ACTION_BUTTON_TYPE(data);
-
- sLog.outDetail( "Player %s has changed pet spell action. Position: %u, Spell: %u, State: 0x%X", _player->GetName(), position, spell_id, uint32(act_state));
+ uint32 position[2];
+ uint32 data[2];
+ bool move_command = false;
+
+ for(uint8 i = 0; i < count; ++i)
+ {
+ recv_data >> position[i];
+ recv_data >> data[i];
+
+ uint8 act_state = UNIT_ACTION_BUTTON_TYPE(data[i]);
+
//ignore invalid position
- if(position >= MAX_UNIT_ACTION_BAR_INDEX)
+ if(position[i] >= MAX_UNIT_ACTION_BAR_INDEX)
return;
+
+ // in the normal case, command and reaction buttons can only be moved, not removed
+ // at moving count ==2, at removing count == 1
+ // ignore attempt to remove command|reaction buttons (not possible at normal case)
+ if (act_state == ACT_COMMAND || act_state == ACT_REACTION)
+ {
+ if (count == 1)
+ return;
+
+ move_command = true;
+ }
+ }
+
+ // check swap (at command->spell swap client remove spell first in another packet, so check only command move correctness)
+ if (move_command)
+ {
+ uint8 act_state_0 = UNIT_ACTION_BUTTON_TYPE(data[0]);
+ if(act_state_0 == ACT_COMMAND || act_state_0 == ACT_REACTION)
+ {
+ uint32 spell_id_0 = UNIT_ACTION_BUTTON_ACTION(data[0]);
+ UnitActionBarEntry const* actionEntry_1 = charmInfo->GetActionBarEntry(position[1]);
+ if (!actionEntry_1 || spell_id_0 != actionEntry_1->GetAction() ||
+ act_state_0 != actionEntry_1->GetType())
+ return;
+ }
+
+ uint8 act_state_1 = UNIT_ACTION_BUTTON_TYPE(data[1]);
+ if(act_state_1 == ACT_COMMAND || act_state_1 == ACT_REACTION)
+ {
+ uint32 spell_id_1 = UNIT_ACTION_BUTTON_ACTION(data[1]);
+ UnitActionBarEntry const* actionEntry_0 = charmInfo->GetActionBarEntry(position[0]);
+ if (!actionEntry_0 || spell_id_1 != actionEntry_0->GetAction() ||
+ act_state_1 != actionEntry_0->GetType())
+ return;
+ }
+ }
+
+ for(uint8 i = 0; i < count; ++i)
+ {
+ uint32 spell_id = UNIT_ACTION_BUTTON_ACTION(data[i]);
+ uint8 act_state = UNIT_ACTION_BUTTON_TYPE(data[i]);
+
+ sLog.outDetail( "Player %s has changed pet spell action. Position: %u, Spell: %u, State: 0x%X", _player->GetName(), position[i], spell_id, uint32(act_state));
//if it's act for spell (en/disable/cast) and there is a spell given (0 = remove spell) which pet doesn't know, don't add
if(!((act_state == ACT_ENABLED || act_state == ACT_DISABLED || act_state == ACT_PASSIVE) && spell_id && !pet->HasSpell(spell_id)))
@@ -438,7 +480,7 @@ void WorldSession::HandlePetSetAction( WorldPacket & recv_data )
}
- charmInfo->SetActionBar(position,spell_id,ActiveStates(act_state));
+ charmInfo->SetActionBar(position[i],spell_id,ActiveStates(act_state));
}
}
}
diff --git a/src/game/PetitionsHandler.cpp b/src/game/PetitionsHandler.cpp
index 718f063beca..aac54ad99e5 100644
--- a/src/game/PetitionsHandler.cpp
+++ b/src/game/PetitionsHandler.cpp
@@ -50,30 +50,35 @@
void WorldSession::HandlePetitionBuyOpcode(WorldPacket & recv_data)
{
sLog.outDebug("Received opcode CMSG_PETITION_BUY");
- //recv_data.hexlike();
+ recv_data.hexlike();
uint64 guidNPC;
- uint64 unk1, unk3, unk4, unk5, unk6, unk7;
- uint32 unk2;
+ uint32 clientIndex; // 1 for guild and arenaslot+1 for arenas in client
std::string name;
- uint16 unk8;
- uint8 unk9;
- uint32 unk10; // selected index
- uint32 unk11;
+
recv_data >> guidNPC; // NPC GUID
- recv_data >> unk1; // 0
- recv_data >> unk2; // 0
+ recv_data.read_skip<uint32>(); // 0
+ recv_data.read_skip<uint64>(); // 0
recv_data >> name; // name
+ recv_data.read_skip<std::string>(); // some string
+ recv_data.read_skip<uint32>(); // 0
+ recv_data.read_skip<uint32>(); // 0
+ recv_data.read_skip<uint32>(); // 0
+ recv_data.read_skip<uint32>(); // 0
+ recv_data.read_skip<uint32>(); // 0
+ recv_data.read_skip<uint32>(); // 0
+ recv_data.read_skip<uint32>(); // 0
+ recv_data.read_skip<uint16>(); // 0
+ recv_data.read_skip<uint32>(); // 0
+ recv_data.read_skip<uint32>(); // 0
+ recv_data.read_skip<uint32>(); // 0
+
+ for (int i = 0; i < 10; ++i)
+ recv_data.read_skip<std::string>();
+
+ recv_data >> clientIndex; // index
+ recv_data.read_skip<uint32>(); // 0
- recv_data >> unk3; // 0
- recv_data >> unk4; // 0
- recv_data >> unk5; // 0
- recv_data >> unk6; // 0
- recv_data >> unk7; // 0
- recv_data >> unk8; // 0
- recv_data >> unk9; // 0
- recv_data >> unk10; // index
- recv_data >> unk11; // 0
sLog.outDebug("Petitioner with GUID %u tried sell petition: name %s", GUID_LOPART(guidNPC), name.c_str());
// prevent cheating
@@ -111,7 +116,7 @@ void WorldSession::HandlePetitionBuyOpcode(WorldPacket & recv_data)
return;
}
- switch(unk10)
+ switch(clientIndex) // arenaSlot+1 as received from client (1 from 3 case)
{
case 1:
charterid = ARENA_TEAM_CHARTER_2v2;
@@ -129,11 +134,11 @@ void WorldSession::HandlePetitionBuyOpcode(WorldPacket & recv_data)
type = 5; // 5v5
break;
default:
- sLog.outDebug("unknown selection at buy petition: %u", unk10);
+ sLog.outDebug("unknown selection at buy arena petition: %u", clientIndex);
return;
}
- if(_player->GetArenaTeamId(unk10-1))
+ if(_player->GetArenaTeamId(clientIndex - 1)) // arenaSlot+1 as received from client
{
SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, name, "", ERR_ALREADY_IN_ARENA_TEAM);
return;
@@ -208,7 +213,6 @@ void WorldSession::HandlePetitionBuyOpcode(WorldPacket & recv_data)
if (result)
{
-
do
{
Field *fields = result->Fetch();
@@ -328,11 +332,11 @@ void WorldSession::SendPetitionQueryOpcode(uint64 petitionguid)
return;
}
- WorldPacket data(SMSG_PETITION_QUERY_RESPONSE, (4+8+name.size()+1+1+4*13));
- data << GUID_LOPART(petitionguid); // guild/team guid (in Trinity always same as GUID_LOPART(petition guid)
- data << ownerguid; // charter owner guid
+ WorldPacket data(SMSG_PETITION_QUERY_RESPONSE, (4+8+name.size()+1+1+4*12+2+10));
+ data << uint32(GUID_LOPART(petitionguid)); // guild/team guid (in Trinity always same as GUID_LOPART(petition guid)
+ data << uint64(ownerguid); // charter owner guid
data << name; // name (guild/arena team)
- data << uint8(0); // 1
+ data << uint8(0); // some string
if(type == 9)
{
data << uint32(9);
@@ -341,9 +345,9 @@ void WorldSession::SendPetitionQueryOpcode(uint64 petitionguid)
}
else
{
- data << type-1;
- data << type-1;
- data << type; // bypass client - side limitation, a different value is needed here for each petition
+ data << uint32(type-1);
+ data << uint32(type-1);
+ data << uint32(type); // bypass client - side limitation, a different value is needed here for each petition
}
data << uint32(0); // 5
data << uint32(0); // 6
@@ -353,11 +357,17 @@ void WorldSession::SendPetitionQueryOpcode(uint64 petitionguid)
data << uint32(0); // 10
data << uint32(0); // 11
data << uint32(0); // 13 count of next strings?
+
+ for(int i = 0; i < 10; ++i)
+ data << uint8(0); // some string
+
data << uint32(0); // 14
+
if(type == 9)
data << uint32(0); // 15 0 - guild, 1 - arena team
else
data << uint32(1);
+
SendPacket(&data);
}
@@ -949,4 +959,3 @@ void WorldSession::SendPetitionShowList(uint64 guid)
SendPacket(&data);
sLog.outDebug("Sent SMSG_PETITION_SHOWLIST");
}
-
diff --git a/src/game/Player.cpp b/src/game/Player.cpp
index 5d33d75f92b..c1e4a9aa5ef 100644
--- a/src/game/Player.cpp
+++ b/src/game/Player.cpp
@@ -119,6 +119,14 @@ enum CharacterFlags
CHARACTER_FLAG_UNK32 = 0x80000000
};
+enum CharacterCustomizeFlags
+{
+ CHAR_CUSTOMIZE_FLAG_NONE = 0x00000000,
+ CHAR_CUSTOMIZE_FLAG_CUSTOMIZE = 0x00000001, // name, gender, etc...
+ CHAR_CUSTOMIZE_FLAG_FACTION = 0x00010000, // name, gender, faction, etc...
+ CHAR_CUSTOMIZE_FLAG_RACE = 0x00100000 // name, gender, race, etc...
+};
+
// corpse reclaim times
#define DEATH_EXPIRE_STEP (5*MINUTE)
#define MAX_DEATH_COUNT 3
@@ -422,7 +430,8 @@ Player::Player (WorldSession *session): Unit(), m_achievementMgr(this), m_reputa
m_HomebindTimer = 0;
m_InstanceValid = true;
- m_dungeonDifficulty = DIFFICULTY_NORMAL;
+ m_dungeonDifficulty = DUNGEON_DIFFICULTY_NORMAL;
+ m_raidDifficulty = RAID_DIFFICULTY_10MAN_NORMAL;
m_lastPotionId = 0;
@@ -449,6 +458,7 @@ Player::Player (WorldSession *session): Unit(), m_achievementMgr(this), m_reputa
m_baseSpellPower = 0;
m_baseFeralAP = 0;
m_baseManaRegen = 0;
+ m_baseHealthRegen = 0;
// Honor System
m_lastHonorUpdateTime = time(NULL);
@@ -541,7 +551,7 @@ void Player::CleanupsBeforeDelete()
m_transport->RemovePassenger(this);
// clean up player-instance binds, may unload some instance saves
- for (uint8 i = 0; i < TOTAL_DIFFICULTIES; ++i)
+ for (uint8 i = 0; i < MAX_DIFFICULTY; ++i)
for (BoundInstancesMap::iterator itr = m_boundInstances[i].begin(); itr != m_boundInstances[i].end(); ++itr)
itr->second.save->RemovePlayer(this);
}
@@ -1142,7 +1152,7 @@ void Player::Update( uint32 p_time )
//sLog.outCrash("Player has m_pad %u during update!", m_pad);
//if(m_spellModTakingSpell)
sLog.outCrash("Player has m_spellModTakingSpell %u during update!", m_spellModTakingSpell->m_spellInfo->Id);
- return;
+ return;
m_spellModTakingSpell = NULL;
}
@@ -1515,8 +1525,8 @@ bool Player::BuildEnumData( QueryResult * result, WorldPacket * p_data )
char_flags |= CHARACTER_FLAG_DECLINED;
*p_data << uint32(char_flags); // character flags
- // character customize (flags?)
- *p_data << uint32(atLoginFlags & AT_LOGIN_CUSTOMIZE ? 1 : 0);
+ // character customize flags
+ *p_data << uint32(atLoginFlags & AT_LOGIN_CUSTOMIZE ? CHAR_CUSTOMIZE_FLAG_CUSTOMIZE : CHAR_CUSTOMIZE_FLAG_NONE);
*p_data << uint8(1); // unknown
// Pets info
@@ -1707,6 +1717,7 @@ bool Player::TeleportTo(uint32 mapid, float x, float y, float z, float orientati
m_movementInfo.t_z = 0.0f;
m_movementInfo.t_o = 0.0f;
m_movementInfo.t_time = 0;
+ m_movementInfo.t_seat = -1;
}
}
@@ -2170,6 +2181,7 @@ void Player::RegenerateHealth()
// always regeneration bonus (including combat)
addvalue += GetTotalAuraModifier(SPELL_AURA_MOD_HEALTH_REGEN_IN_COMBAT);
+ addvalue += m_baseHealthRegen / 2.5f;
if (addvalue < 0)
addvalue = 0;
@@ -2448,6 +2460,9 @@ void Player::GiveXP(uint32 xp, Unit* victim)
if(!isAlive())
return;
+ if(HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_NO_XP_GAIN))
+ return;
+
uint8 level = getLevel();
// Favored experience increase START
@@ -2617,6 +2632,9 @@ void Player::InitStatsForLevel(bool reapplyMods)
SetUInt32Value(PLAYER_FIELD_MAX_LEVEL, sWorld.getConfig(CONFIG_MAX_PLAYER_LEVEL) );
SetUInt32Value(PLAYER_NEXT_LEVEL_XP, objmgr.GetXPForLevel(getLevel()));
+ // reset before any aura state sources (health set/aura apply)
+ SetUInt32Value(UNIT_FIELD_AURASTATE, 0);
+
UpdateSkillsForLevel ();
// set default cast time multiplier
@@ -2916,7 +2934,7 @@ bool Player::AddTalent(uint32 spell_id, uint8 spec, bool learning)
return false;
}
- if (!SpellMgr::IsSpellValid(spellInfo,this,false))
+ if(!SpellMgr::IsSpellValid(spellInfo,this,false))
{
// do character spell book cleanup (all characters)
if(!IsInWorld() && !learning) // spell load case
@@ -2968,7 +2986,7 @@ bool Player::addSpell(uint32 spell_id, bool active, bool learning, bool dependen
if (!spellInfo)
{
// do character spell book cleanup (all characters)
- if (!IsInWorld() && !learning) // spell load case
+ if(!IsInWorld() && !learning) // spell load case
{
sLog.outError("Player::addSpell: Non-existed in SpellStore spell #%u request, deleting for all characters in `character_spell`.",spell_id);
CharacterDatabase.PExecute("DELETE FROM character_spell WHERE spell = '%u'",spell_id);
@@ -2979,7 +2997,7 @@ bool Player::addSpell(uint32 spell_id, bool active, bool learning, bool dependen
return false;
}
- if (!SpellMgr::IsSpellValid(spellInfo,this,false))
+ if(!SpellMgr::IsSpellValid(spellInfo,this,false))
{
// do character spell book cleanup (all characters)
if(!IsInWorld() && !learning) // spell load case
@@ -3008,11 +3026,11 @@ bool Player::addSpell(uint32 spell_id, bool active, bool learning, bool dependen
{
uint32 next_active_spell_id = 0;
// fix activate state for non-stackable low rank (and find next spell for !active case)
- if (!SpellMgr::canStackSpellRanks(spellInfo) && spellmgr.GetSpellRank(spellInfo->Id) != 0)
+ if(!SpellMgr::canStackSpellRanks(spellInfo) && spellmgr.GetSpellRank(spellInfo->Id) != 0)
{
- if (uint32 next = spellmgr.GetNextSpellInChain(spell_id))
+ if(uint32 next = spellmgr.GetNextSpellInChain(spell_id))
{
- if (HasSpell(next))
+ if(HasSpell(next))
{
// high rank already known so this must !active
active = false;
@@ -3022,10 +3040,10 @@ bool Player::addSpell(uint32 spell_id, bool active, bool learning, bool dependen
}
// not do anything if already known in expected state
- if (itr->second->state != PLAYERSPELL_REMOVED && itr->second->active == active &&
+ if(itr->second->state != PLAYERSPELL_REMOVED && itr->second->active == active &&
itr->second->dependent == dependent && itr->second->disabled == disabled)
{
- if (!IsInWorld() && !learning) // explicitly load from DB and then exist in it already and set correctly
+ if(!IsInWorld() && !learning) // explicitly load from DB and then exist in it already and set correctly
itr->second->state = PLAYERSPELL_UNCHANGED;
return false;
@@ -3041,21 +3059,21 @@ bool Player::addSpell(uint32 spell_id, bool active, bool learning, bool dependen
}
// update active state for known spell
- if (itr->second->active != active && itr->second->state != PLAYERSPELL_REMOVED && !itr->second->disabled)
+ if(itr->second->active != active && itr->second->state != PLAYERSPELL_REMOVED && !itr->second->disabled)
{
itr->second->active = active;
- if (!IsInWorld() && !learning && !dependent_set) // explicitly load from DB and then exist in it already and set correctly
+ if(!IsInWorld() && !learning && !dependent_set) // explicitly load from DB and then exist in it already and set correctly
itr->second->state = PLAYERSPELL_UNCHANGED;
- else if (itr->second->state != PLAYERSPELL_NEW)
+ else if(itr->second->state != PLAYERSPELL_NEW)
itr->second->state = PLAYERSPELL_CHANGED;
- if (active)
+ if(active)
{
if (IsPassiveSpell(spell_id) && IsNeedCastPassiveSpellAtLearn(spellInfo))
- CastSpell(this, spell_id, true);
+ CastSpell (this,spell_id,true);
}
- else if (IsInWorld())
+ else if(IsInWorld())
{
if(next_active_spell_id)
{
@@ -3063,7 +3081,7 @@ bool Player::addSpell(uint32 spell_id, bool active, bool learning, bool dependen
WorldPacket data(SMSG_SUPERCEDED_SPELL, 4 + 4);
data << uint32(spell_id);
data << uint32(next_active_spell_id);
- GetSession()->SendPacket(&data);
+ GetSession()->SendPacket( &data );
}
else
{
@@ -3076,18 +3094,18 @@ bool Player::addSpell(uint32 spell_id, bool active, bool learning, bool dependen
return active; // learn (show in spell book if active now)
}
- if (itr->second->disabled != disabled && itr->second->state != PLAYERSPELL_REMOVED)
+ if(itr->second->disabled != disabled && itr->second->state != PLAYERSPELL_REMOVED)
{
- if (itr->second->state != PLAYERSPELL_NEW)
+ if(itr->second->state != PLAYERSPELL_NEW)
itr->second->state = PLAYERSPELL_CHANGED;
itr->second->disabled = disabled;
- if (disabled)
+ if(disabled)
return false;
disabled_case = true;
}
- else switch (itr->second->state)
+ else switch(itr->second->state)
{
case PLAYERSPELL_UNCHANGED: // known saved spell
return false;
@@ -3101,7 +3119,7 @@ bool Player::addSpell(uint32 spell_id, bool active, bool learning, bool dependen
default: // known not saved yet spell (new or modified)
{
// can be in case spell loading but learned at some previous spell loading
- if (!IsInWorld() && !learning && !dependent_set)
+ if(!IsInWorld() && !learning && !dependent_set)
itr->second->state = PLAYERSPELL_UNCHANGED;
return false;
@@ -3109,19 +3127,18 @@ bool Player::addSpell(uint32 spell_id, bool active, bool learning, bool dependen
}
}
- // skip new spell adding if spell already known (disabled spells case)
- if (!disabled_case)
+ if(!disabled_case) // skip new spell adding if spell already known (disabled spells case)
{
// talent: unlearn all other talent ranks (high and low)
- if (TalentSpellPos const *talentPos = GetTalentSpellPos(spell_id))
+ if(TalentSpellPos const *talentPos = GetTalentSpellPos(spell_id))
{
- if (TalentEntry const *talentInfo = sTalentStore.LookupEntry( talentPos->talent_id ))
+ if(TalentEntry const *talentInfo = sTalentStore.LookupEntry( talentPos->talent_id ))
{
for (uint8 rank = 0; rank < MAX_TALENT_RANK; ++rank)
{
// skip learning spell and no rank spell case
uint32 rankSpellId = talentInfo->RankID[rank];
- if (!rankSpellId || rankSpellId == spell_id)
+ if(!rankSpellId || rankSpellId == spell_id)
continue;
removeSpell(rankSpellId,false,false);
@@ -3129,9 +3146,9 @@ bool Player::addSpell(uint32 spell_id, bool active, bool learning, bool dependen
}
}
// non talent spell: learn low ranks (recursive call)
- else if (uint32 prev_spell = spellmgr.GetPrevSpellInChain(spell_id))
+ else if(uint32 prev_spell = spellmgr.GetPrevSpellInChain(spell_id))
{
- if (!IsInWorld() || disabled) // at spells loading, no output, but allow save
+ if(!IsInWorld() || disabled) // at spells loading, no output, but allow save
addSpell(prev_spell,active,true,true,disabled);
else // at normal learning
learnSpell(prev_spell,true);
@@ -3144,23 +3161,21 @@ bool Player::addSpell(uint32 spell_id, bool active, bool learning, bool dependen
newspell->disabled = disabled;
// replace spells in action bars and spellbook to bigger rank if only one spell rank must be accessible
- if (newspell->active && !newspell->disabled && !SpellMgr::canStackSpellRanks(spellInfo) && spellmgr.GetSpellRank(spellInfo->Id) != 0)
+ if(newspell->active && !newspell->disabled && !SpellMgr::canStackSpellRanks(spellInfo) && spellmgr.GetSpellRank(spellInfo->Id) != 0)
{
for (PlayerSpellMap::iterator itr2 = m_spells.begin(); itr2 != m_spells.end(); ++itr2 )
{
- if (itr2->second->state == PLAYERSPELL_REMOVED)
- continue;
+ if(itr2->second->state == PLAYERSPELL_REMOVED) continue;
SpellEntry const *i_spellInfo = sSpellStore.LookupEntry(itr2->first);
- if (!i_spellInfo)
- continue;
+ if(!i_spellInfo) continue;
- if (spellmgr.IsRankSpellDueToSpell(spellInfo,itr2->first))
+ if( spellmgr.IsRankSpellDueToSpell(spellInfo,itr2->first) )
{
- if (itr2->second->active)
+ if(itr2->second->active)
{
- if (spellmgr.IsHighRankOfSpell(spell_id,itr2->first))
+ if(spellmgr.IsHighRankOfSpell(spell_id,itr2->first))
{
- if (IsInWorld()) // not send spell (re-/over-)learn packets at loading
+ if(IsInWorld()) // not send spell (re-/over-)learn packets at loading
{
WorldPacket data(SMSG_SUPERCEDED_SPELL, 4 + 4);
data << uint32(itr2->first);
@@ -3174,19 +3189,19 @@ bool Player::addSpell(uint32 spell_id, bool active, bool learning, bool dependen
itr2->second->state = PLAYERSPELL_CHANGED;
superceded_old = true; // new spell replace old in action bars and spell book.
}
- else if (spellmgr.IsHighRankOfSpell(itr2->first, spell_id))
+ else if(spellmgr.IsHighRankOfSpell(itr2->first,spell_id))
{
- if (IsInWorld()) // not send spell (re-/over-)learn packets at loading
+ if(IsInWorld()) // not send spell (re-/over-)learn packets at loading
{
WorldPacket data(SMSG_SUPERCEDED_SPELL, 4 + 4);
data << uint32(spell_id);
data << uint32(itr2->first);
- GetSession()->SendPacket(&data);
+ GetSession()->SendPacket( &data );
}
// mark new spell as disable (not learned yet for client and will not learned)
newspell->active = false;
- if (newspell->state != PLAYERSPELL_NEW)
+ if(newspell->state != PLAYERSPELL_NEW)
newspell->state = PLAYERSPELL_CHANGED;
}
}
@@ -3228,7 +3243,7 @@ bool Player::addSpell(uint32 spell_id, bool active, bool learning, bool dependen
// update free primary prof.points (if any, can be none in case GM .learn prof. learning)
if (uint32 freeProfs = GetFreePrimaryProfessionPoints())
{
- if (spellmgr.IsPrimaryProfessionFirstRankSpell(spell_id))
+ if(spellmgr.IsPrimaryProfessionFirstRankSpell(spell_id))
SetFreePrimaryProfessions(freeProfs-1);
}
@@ -3252,7 +3267,7 @@ bool Player::addSpell(uint32 spell_id, bool active, bool learning, bool dependen
if (skill_max_value < new_skill_max_value)
skill_max_value = new_skill_max_value;
- SetSkill(spellLearnSkill->skill, skill_value, skill_max_value);
+ SetSkill(spellLearnSkill->skill,skill_value,skill_max_value);
}
else
{
@@ -3270,16 +3285,16 @@ bool Player::addSpell(uint32 spell_id, bool active, bool learning, bool dependen
// lockpicking/runeforging special case, not have ABILITY_LEARNED_ON_GET_RACE_OR_CLASS_SKILL
((pSkill->id==SKILL_LOCKPICKING || pSkill->id==SKILL_RUNEFORGING) && _spell_idx->second->max_value==0))
{
- switch (GetSkillRangeType(pSkill,_spell_idx->second->racemask!=0))
+ switch(GetSkillRangeType(pSkill,_spell_idx->second->racemask!=0))
{
case SKILL_RANGE_LANGUAGE:
- SetSkill(pSkill->id, 300, 300);
+ SetSkill(pSkill->id, 300, 300 );
break;
case SKILL_RANGE_LEVEL:
- SetSkill(pSkill->id, 1, GetMaxSkillValueForLevel());
+ SetSkill(pSkill->id, 1, GetMaxSkillValueForLevel() );
break;
case SKILL_RANGE_MONO:
- SetSkill(pSkill->id, 1, 1);
+ SetSkill(pSkill->id, 1, 1 );
break;
default:
break;
@@ -3296,9 +3311,9 @@ bool Player::addSpell(uint32 spell_id, bool active, bool learning, bool dependen
if (!itr2->second.autoLearned)
{
if (!IsInWorld() || !itr2->second.active) // at spells loading, no output, but allow save
- addSpell(itr2->second.spell, itr2->second.active, true, true, false);
+ addSpell(itr2->second.spell,itr2->second.active,true,true,false);
else // at normal learning
- learnSpell(itr2->second.spell, true);
+ learnSpell(itr2->second.spell,true);
}
}
@@ -3398,13 +3413,13 @@ void Player::removeSpell(uint32 spell_id, bool disabled, bool learn_low_rank)
if (SpellChainNode const* node = spellmgr.GetSpellChainNode(spell_id))
{
if (HasSpell(node->next) && !GetTalentSpellPos(node->next))
- removeSpell(node->next,disabled);
+ removeSpell(node->next,disabled);
}
//unlearn spells dependent from recently removed spells
SpellsRequiringSpellMap const &reqMap = spellmgr.GetSpellsRequiringSpell();
SpellsRequiringSpellMap::const_iterator itr2 = reqMap.find(spell_id);
for (uint32 i = reqMap.count(spell_id); i > 0; --i, ++itr2)
- removeSpell(itr2->second, disabled, false);
+ removeSpell(itr2->second,disabled,false);
// re-search, it can be corrupted in prev loop
itr = m_spells.find(spell_id);
@@ -3510,7 +3525,7 @@ void Player::removeSpell(uint32 spell_id, bool disabled, bool learn_low_rank)
((pSkill->id == SKILL_LOCKPICKING || pSkill->id == SKILL_RUNEFORGING) && _spell_idx->second->max_value == 0))
{
// not reset skills for professions and racial abilities
- if ((pSkill->categoryId == SKILL_CATEGORY_SECONDARY || pSkill->categoryId == SKILL_CATEGORY_PROFESSION) &&
+ if ((pSkill->categoryId==SKILL_CATEGORY_SECONDARY || pSkill->categoryId==SKILL_CATEGORY_PROFESSION) &&
(IsProfessionSkill(pSkill->id) || _spell_idx->second->racemask!=0))
continue;
@@ -3722,7 +3737,7 @@ void Player::_SaveSpellCooldowns()
}
// if something changed execute
if (!first_round)
- CharacterDatabase.Execute(ss.str().c_str());
+ CharacterDatabase.Execute( ss.str().c_str() );
}
uint32 Player::resetTalentsCost() const
@@ -3858,19 +3873,19 @@ Mail* Player::GetMail(uint32 id)
void Player::_SetCreateBits(UpdateMask *updateMask, Player *target) const
{
- if (target == this)
+ if(target == this)
Object::_SetCreateBits(updateMask, target);
else
{
for (uint16 index = 0; index < m_valuesCount; index++)
- if (GetUInt32Value(index) != 0 && updateVisualBits.GetBit(index))
+ if(GetUInt32Value(index) != 0 && updateVisualBits.GetBit(index))
updateMask->SetBit(index);
}
}
void Player::_SetUpdateBits(UpdateMask *updateMask, Player *target) const
{
- if (target == this)
+ if(target == this)
Object::_SetUpdateBits(updateMask, target);
else
{
@@ -4248,6 +4263,7 @@ void Player::DeleteFromDB(uint64 playerguid, uint32 accountId, bool updateRealmC
CharacterDatabase.PExecute("DELETE FROM group_instance WHERE leaderGuid = '%u'",guid);
CharacterDatabase.PExecute("DELETE FROM groups WHERE leaderGuid = '%u'",guid);
CharacterDatabase.PExecute("DELETE FROM group_member WHERE leaderGuid = '%u' OR memberGuid = '%u'",guid,guid);
+ CharacterDatabase.PExecute("DELETE FROM groups WHERE leaderGuid = '%u'",guid);
CharacterDatabase.PExecute("DELETE FROM character_inventory WHERE guid = '%u'",guid);
CharacterDatabase.PExecute("DELETE FROM character_queststatus WHERE guid = '%u'",guid);
CharacterDatabase.PExecute("DELETE FROM character_reputation WHERE guid = '%u'",guid);
@@ -4272,8 +4288,12 @@ void Player::DeleteFromDB(uint64 playerguid, uint32 accountId, bool updateRealmC
CharacterDatabase.PExecute("DELETE FROM character_battleground_data WHERE guid = '%u'",guid);
CharacterDatabase.PExecute("DELETE FROM character_glyphs WHERE guid = '%u'",guid);
CharacterDatabase.PExecute("DELETE FROM character_queststatus_daily WHERE guid = '%u'",guid);
+ CharacterDatabase.PExecute("DELETE FROM character_battleground_data WHERE guid = '%u'",guid);
+ CharacterDatabase.PExecute("DELETE FROM character_glyphs WHERE guid = '%u'",guid);
+ CharacterDatabase.PExecute("DELETE FROM character_queststatus_daily WHERE guid = '%u'",guid);
CharacterDatabase.PExecute("DELETE FROM character_talent WHERE guid = '%u'",guid);
CharacterDatabase.PExecute("DELETE FROM character_skills WHERE guid = '%u'",guid);
+
CharacterDatabase.CommitTransaction();
//loginDatabase.PExecute("UPDATE realmcharacters SET numchars = numchars - 1 WHERE acctid = %d AND realmid = %d", accountId, realmID);
@@ -4540,17 +4560,17 @@ void Player::CreateCorpse()
corpse->SetUInt32Value( CORPSE_FIELD_GUILD, GetGuildId() );
uint32 iDisplayID;
- uint16 iIventoryType;
+ uint32 iIventoryType;
uint32 _cfi;
for (uint8 i = 0; i < EQUIPMENT_SLOT_END; i++)
{
if(m_items[i])
{
iDisplayID = m_items[i]->GetProto()->DisplayInfoID;
- iIventoryType = (uint16)m_items[i]->GetProto()->InventoryType;
+ iIventoryType = m_items[i]->GetProto()->InventoryType;
- _cfi = (uint16(iDisplayID)) | (iIventoryType)<< 24;
- corpse->SetUInt32Value(CORPSE_FIELD_ITEM + i,_cfi);
+ _cfi = iDisplayID | (iIventoryType << 24);
+ corpse->SetUInt32Value(CORPSE_FIELD_ITEM + i, _cfi);
}
}
@@ -5111,6 +5131,15 @@ uint32 Player::GetMeleeCritDamageReduction(uint32 damage) const
return uint32 (melee * damage /100.0f);
}
+uint32 Player::GetMeleeDamageReduction(uint32 damage) const
+{
+ float rate = GetRatingBonusValue(CR_CRIT_TAKEN_MELEE);
+ // Resilience not limited (limit it by 100%)
+ if (rate > 100.0f)
+ rate = 100.0f;
+ return uint32 (rate * damage / 100.0f);
+}
+
uint32 Player::GetRangedCritDamageReduction(uint32 damage) const
{
float ranged = GetRatingBonusValue(CR_CRIT_TAKEN_RANGED)*2.2f;
@@ -5118,6 +5147,15 @@ uint32 Player::GetRangedCritDamageReduction(uint32 damage) const
return uint32 (ranged * damage /100.0f);
}
+uint32 Player::GetRangedDamageReduction(uint32 damage) const
+{
+ float rate = GetRatingBonusValue(CR_CRIT_TAKEN_RANGED);
+ // Resilience not limited (limit it by 100%)
+ if (rate > 100.0f)
+ rate = 100.0f;
+ return uint32 (rate * damage / 100.0f);
+}
+
uint32 Player::GetSpellCritDamageReduction(uint32 damage) const
{
float spell = GetRatingBonusValue(CR_CRIT_TAKEN_SPELL)*2.2f;
@@ -5127,13 +5165,13 @@ uint32 Player::GetSpellCritDamageReduction(uint32 damage) const
return uint32 (spell * damage / 100.0f);
}
-uint32 Player::GetDotDamageReduction(uint32 damage) const
+uint32 Player::GetSpellDamageReduction(uint32 damage) const
{
- float spellDot = GetRatingBonusValue(CR_CRIT_TAKEN_SPELL);
- // Dot resilience not limited (limit it by 100%)
- if (spellDot > 100.0f)
- spellDot = 100.0f;
- return uint32 (spellDot * damage / 100.0f);
+ float rate = GetRatingBonusValue(CR_CRIT_TAKEN_SPELL);
+ // Resilience not limited (limit it by 100%)
+ if (rate > 100.0f)
+ rate = 100.0f;
+ return uint32 (rate * damage / 100.0f);
}
float Player::GetExpertiseDodgeOrParryReduction(WeaponAttackType attType) const
@@ -5456,7 +5494,7 @@ bool Player::UpdateSkillPro(uint16 SkillId, int32 Chance, uint32 step)
uint16 SkillValue = SKILL_VALUE(data);
uint16 MaxValue = SKILL_MAX(data);
- if (!MaxValue || !SkillValue || SkillValue >= MaxValue )
+ if ( !MaxValue || !SkillValue || SkillValue >= MaxValue )
return false;
int32 Roll = irand(1,1000);
@@ -5874,7 +5912,7 @@ ActionButton* Player::addActionButton(uint8 button, uint32 action, uint8 type)
{
if(button >= MAX_ACTION_BUTTONS)
{
- sLog.outError( "Action %u not added into button %u for player %s: button must be < 132", action, button, GetName() );
+ sLog.outError( "Action %u not added into button %u for player %s: button must be < 144", action, button, GetName() );
return NULL;
}
@@ -6001,7 +6039,6 @@ void Player::SendMessageToSet(WorldPacket *data, bool self)
// we use World::GetMaxVisibleDistance() because i cannot see why not use a distance
// update: replaced by GetMap()->GetVisibilityDistance()
-
Trinity::MessageDistDeliverer notifier(this, data, GetMap()->GetVisibilityDistance());
VisitNearbyWorldObject(GetMap()->GetVisibilityDistance(), notifier);
}
@@ -6025,7 +6062,7 @@ void Player::SendMessageToSetInRange(WorldPacket *data, float dist, bool self, b
}
void Player::SendDirectMessage(WorldPacket *data)
-{
+{
if (m_session)
m_session->SendPacket(data);
}
@@ -6212,7 +6249,7 @@ void Player::RewardReputation(Unit *pVictim, float rate)
Map const *pMap = GetMap();
if(pMap && pMap->IsDungeon())
{
- bool Heroic = pMap->IsHeroic();
+ bool Heroic = ((InstanceMap*)pMap)->GetDifficulty() == DUNGEON_DIFFICULTY_HEROIC;
InstanceTemplate const *pInstance = objmgr.GetInstanceTemplate(pMap->GetId());
if(pInstance)
@@ -6348,6 +6385,7 @@ bool Player::RewardHonor(Unit *uVictim, uint32 groupsize, float honor, bool pvpt
uint64 victim_guid = 0;
uint32 victim_rank = 0;
+ uint32 rank_diff = 0;
time_t now = time(NULL);
// need call before fields update to have chance move yesterday data to appropriate fields before today data change.
@@ -6500,7 +6538,7 @@ bool Player::RewardHonor(Unit *uVictim, uint32 groupsize, float honor, bool pvpt
return true;
}
-void Player::ModifyHonorPoints( int32 value )
+void Player::ModifyHonorPoints(int32 value)
{
if(value < 0)
{
@@ -6513,7 +6551,7 @@ void Player::ModifyHonorPoints( int32 value )
SetUInt32Value(PLAYER_FIELD_HONOR_CURRENCY, GetHonorPoints() < sWorld.getConfig(CONFIG_MAX_HONOR_POINTS) - value ? GetHonorPoints() + value : sWorld.getConfig(CONFIG_MAX_HONOR_POINTS));
}
-void Player::ModifyArenaPoints( int32 value )
+void Player::ModifyArenaPoints(int32 value)
{
if(value < 0)
{
@@ -6809,7 +6847,7 @@ void Player::DuelComplete(DuelCompleteType type)
duel->opponent->AttackStop();
}
break;
- case DUEL_WON:
+ case DUEL_WON:
GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_LOSE_DUEL, 1);
if (duel->opponent)
{
@@ -7092,6 +7130,9 @@ void Player::_ApplyItemBonuses(ItemPrototype const *proto, uint8 slot, bool appl
case ITEM_MOD_SPELL_POWER:
ApplySpellPowerBonus(int32(val), apply);
break;
+ case ITEM_MOD_HEALTH_REGEN:
+ ApplyHealthRegenBonus(int32(val), apply);
+ break;
// depricated item mods
case ITEM_MOD_SPELL_HEALING_DONE:
case ITEM_MOD_SPELL_DAMAGE_DONE:
@@ -7855,13 +7896,13 @@ void Player::SendLoot(uint64 guid, LootType loot_type)
if (go->getLootState() == GO_READY)
{
- uint32 lootid = go->GetGOInfo()->GetLootId();
+ uint32 lootid = go->GetGOInfo()->GetLootId();
//TODO: fix this big hack
if((go->GetEntry() == BG_AV_OBJECTID_MINE_N || go->GetEntry() == BG_AV_OBJECTID_MINE_S))
if( BattleGround *bg = GetBattleGround())
if(bg->GetTypeID() == BATTLEGROUND_AV)
- if(!(((BattleGroundAV*)bg)->PlayerCanDoMineQuest(go->GetEntry(), GetTeam())))
+ if(!(((BattleGroundAV*)bg)->PlayerCanDoMineQuest(go->GetEntry(),GetTeam())))
{
SendLootRelease(guid);
return;
@@ -7875,7 +7916,7 @@ void Player::SendLoot(uint64 guid, LootType loot_type)
}
if (loot_type == LOOT_FISHING)
- go->getFishLoot(loot, this);
+ go->getFishLoot(loot,this);
go->SetLootState(GO_ACTIVATED);
}
@@ -7900,17 +7941,17 @@ void Player::SendLoot(uint64 guid, LootType loot_type)
switch (loot_type)
{
case LOOT_DISENCHANTING:
- loot->FillLoot(item->GetProto()->DisenchantID, LootTemplates_Disenchant, this, true);
+ loot->FillLoot(item->GetProto()->DisenchantID, LootTemplates_Disenchant, this,true);
break;
case LOOT_PROSPECTING:
- loot->FillLoot(item->GetEntry(), LootTemplates_Prospecting, this, true);
+ loot->FillLoot(item->GetEntry(), LootTemplates_Prospecting, this,true);
break;
case LOOT_MILLING:
- loot->FillLoot(item->GetEntry(), LootTemplates_Milling, this, true);
+ loot->FillLoot(item->GetEntry(), LootTemplates_Milling, this,true);
break;
default:
- loot->FillLoot(item->GetEntry(), LootTemplates_Item, this, true);
- loot->generateMoneyLoot(item->GetProto()->MinMoneyLoot, item->GetProto()->MaxMoneyLoot);
+ loot->FillLoot(item->GetEntry(), LootTemplates_Item, this,true);
+ loot->generateMoneyLoot(item->GetProto()->MinMoneyLoot,item->GetProto()->MaxMoneyLoot);
break;
}
}
@@ -8177,10 +8218,16 @@ void Player::SendInitWorldStates(uint32 zoneid, uint32 areaid)
case 3968:
NumberOfFields = 11;
break;
+ case 4378:
+ NumberOfFields = 11;
+ break;
case 3703:
NumberOfFields = 11;
break;
- default:
+ case 4384:
+ NumberOfFields = 30;
+ break;
+ default:
NumberOfFields = 12;
break;
}
@@ -8200,6 +8247,13 @@ void Player::SendInitWorldStates(uint32 zoneid, uint32 areaid)
data << uint32(0xC77) << uint32(sWorld.getConfig(CONFIG_ARENA_SEASON_IN_PROGRESS));
// 8 Arena season id
data << uint32(0xF3D) << uint32(sWorld.getConfig(CONFIG_ARENA_SEASON_ID));
+
+ // May be send timer to start Wintergrasp
+ //if(sWorld.GetWintergrapsState()==4354)
+ // data << uint32(0x1102) << sWorld.GetWintergrapsTimer();
+ //else
+ // data << uint32(0xEC5) << sWorld.GetWintergrapsTimer();
+ // ---
if(mapid == 530) // Outland
{
data << uint32(0x9bf) << uint32(0x0); // 7
@@ -8287,7 +8341,7 @@ void Player::SendInitWorldStates(uint32 zoneid, uint32 areaid)
data << uint32(0x532) << uint32(0x1); // 8 frostwolfhut hc
data << uint32(0x531) << uint32(0x0); // 9 frostwolfhut ac
data << uint32(0x52e) << uint32(0x0); // 10 stormpike firstaid a_a
- data << uint32(0x571) << uint32(0x0); // 11 east frostwolf tower horde assaulted - unused
+ data << uint32(0x571) << uint32(0x0); // 11 east frostwolf tower horde assaulted -unused
data << uint32(0x570) << uint32(0x0); // 12 west frostwolf tower horde assaulted - unused
data << uint32(0x567) << uint32(0x1); // 13 frostwolfe c
data << uint32(0x566) << uint32(0x1); // 14 frostwolfw c
@@ -8298,7 +8352,7 @@ void Player::SendInitWorldStates(uint32 zoneid, uint32 areaid)
data << uint32(0x518) << uint32(0x0); // 19 stoneheart grave a_a
data << uint32(0x517) << uint32(0x0); // 20 stoneheart grave h_a
data << uint32(0x574) << uint32(0x0); // 21 1396 unk
- data << uint32(0x573) << uint32(0x0); // 22 iceblood tower horde assaulted - unused
+ data << uint32(0x573) << uint32(0x0); // 22 iceblood tower horde assaulted -unused
data << uint32(0x572) << uint32(0x0); // 23 towerpoint horde assaulted - unused
data << uint32(0x56f) << uint32(0x0); // 24 1391 unk
data << uint32(0x56e) << uint32(0x0); // 25 iceblood a
@@ -8625,7 +8679,52 @@ void Player::SendInitWorldStates(uint32 zoneid, uint32 areaid)
data << uint32(0xbba) << uint32(0x0); // 9 show
}
break;
+ case 4378: // Dalaran Sewers
+ if (bg && bg->GetTypeID() == BATTLEGROUND_DS)
+ bg->FillInitialWorldStates(data);
+ else
+ {
+ data << uint32(3601) << uint32(0x0); // 7 gold
+ data << uint32(3600) << uint32(0x0); // 8 green
+ data << uint32(3610) << uint32(0x0); // 9 show
+ }
+ break;
case 3703: // Shattrath City
+ case 4384: // SA
+ /*if (bg && bg->GetTypeID() == BATTLEGROUND_SA)
+ bg->FillInitialWorldStates(data);
+ else
+ {*/
+ // 1-3 A defend, 4-6 H defend, 7-9 unk defend, 1 - ok, 2 - half destroyed, 3 - destroyed
+ data << uint32(0xf09) << uint32(0x4); // 7 3849 Gate of Temple
+ data << uint32(0xe36) << uint32(0x4); // 8 3638 Gate of Yellow Moon
+ data << uint32(0xe27) << uint32(0x4); // 9 3623 Gate of Green Emerald
+ data << uint32(0xe24) << uint32(0x4); // 10 3620 Gate of Blue Sapphire
+ data << uint32(0xe21) << uint32(0x4); // 11 3617 Gate of Red Sun
+ data << uint32(0xe1e) << uint32(0x4); // 12 3614 Gate of Purple Ametyst
+
+ data << uint32(0xdf3) << uint32(0x0); // 13 3571 bonus timer (1 - on, 0 - off)
+ data << uint32(0xded) << uint32(0x0); // 14 3565 Horde Attacker
+ data << uint32(0xdec) << uint32(0x1); // 15 3564 Alliance Attacker
+ // End Round (timer), better explain this by example, eg. ends in 19:59 -> A:BC
+ data << uint32(0xde9) << uint32(0x9); // 16 3561 C
+ data << uint32(0xde8) << uint32(0x5); // 17 3560 B
+ data << uint32(0xde7) << uint32(0x19); // 18 3559 A
+ data << uint32(0xe35) << uint32(0x1); // 19 3637 East g - Horde control
+ data << uint32(0xe34) << uint32(0x1); // 20 3636 West g - Horde control
+ data << uint32(0xe33) << uint32(0x1); // 21 3635 South g - Horde control
+ data << uint32(0xe32) << uint32(0x0); // 22 3634 East g - Alliance control
+ data << uint32(0xe31) << uint32(0x0); // 23 3633 West g - Alliance control
+ data << uint32(0xe30) << uint32(0x0); // 24 3632 South g - Alliance control
+ data << uint32(0xe2f) << uint32(0x1); // 25 3631 Chamber of Ancients - Horde control
+ data << uint32(0xe2e) << uint32(0x0); // 26 3630 Chamber of Ancients - Alliance control
+ data << uint32(0xe2d) << uint32(0x0); // 27 3629 Beach1 - Horde control
+ data << uint32(0xe2c) << uint32(0x0); // 28 3628 Beach2 - Horde control
+ data << uint32(0xe2b) << uint32(0x1); // 29 3627 Beach1 - Alliance control
+ data << uint32(0xe2a) << uint32(0x1); // 30 3626 Beach2 - Alliance control
+ // and many unks...
+ //}
+ break;
break;
case 4406: // Ring of Valor
if (bg && bg->GetTypeID() == BATTLEGROUND_RV)
@@ -8691,7 +8790,7 @@ void Player::SendPetSkillWipeConfirm()
/*** STORAGE SYSTEM ***/
/*********************************************************/
-void Player::SetVirtualItemSlot(uint8 i, Item *item)
+void Player::SetVirtualItemSlot( uint8 i, Item* item)
{
assert(i < 3);
if (i < 2 && item)
@@ -8711,7 +8810,7 @@ void Player::SetVirtualItemSlot(uint8 i, Item *item)
}
}
-void Player::SetSheath(SheathState sheathed)
+void Player::SetSheath( SheathState sheathed )
{
switch (sheathed)
{
@@ -8740,7 +8839,7 @@ void Player::SetSheath(SheathState sheathed)
Unit::SetSheath(sheathed); // this must visualize Sheath changing for other players...
}
-uint8 Player::FindEquipSlot(ItemPrototype const* proto, uint32 slot, bool swap) const
+uint8 Player::FindEquipSlot( ItemPrototype const* proto, uint32 slot, bool swap ) const
{
uint8 pClass = getClass();
@@ -8958,10 +9057,10 @@ uint8 Player::CanUnequipItems( uint32 item, uint32 count ) const
return res;
}
-uint32 Player::GetItemCount(uint32 item, bool inBankAlso, Item *skipItem) const
+uint32 Player::GetItemCount(uint32 item, bool inBankAlso, Item* skipItem) const
{
uint32 count = 0;
- for (uint8 i = EQUIPMENT_SLOT_START; i < INVENTORY_SLOT_ITEM_END; ++i)
+ for (uint8 i = EQUIPMENT_SLOT_START; i < INVENTORY_SLOT_ITEM_END; i++)
if (Item *pItem = GetItemByPos( INVENTORY_SLOT_BAG_0, i))
if (pItem != skipItem && pItem->GetEntry() == item)
count += pItem->GetCount();
@@ -9031,21 +9130,21 @@ Item* Player::GetItemByGuid( uint64 guid ) const
return NULL;
}
-Item* Player::GetItemByPos(uint16 pos) const
+Item* Player::GetItemByPos( uint16 pos ) const
{
uint8 bag = pos >> 8;
uint8 slot = pos & 255;
- return GetItemByPos(bag, slot);
+ return GetItemByPos( bag, slot );
}
Item* Player::GetItemByPos( uint8 bag, uint8 slot ) const
{
- if (bag == INVENTORY_SLOT_BAG_0 && (slot < BANK_SLOT_BAG_END || (slot >= KEYRING_SLOT_START && slot < CURRENCYTOKEN_SLOT_END)))
+ if (bag == INVENTORY_SLOT_BAG_0 && ( slot < BANK_SLOT_BAG_END || (slot >= KEYRING_SLOT_START && slot < CURRENCYTOKEN_SLOT_END) ))
return m_items[slot];
else if ((bag >= INVENTORY_SLOT_BAG_START && bag < INVENTORY_SLOT_BAG_END)
|| (bag >= BANK_SLOT_BAG_START && bag < BANK_SLOT_BAG_END))
{
- if (Bag *pBag = (Bag*)GetItemByPos(INVENTORY_SLOT_BAG_0, bag))
+ if (Bag *pBag = (Bag*)GetItemByPos( INVENTORY_SLOT_BAG_0, bag))
return pBag->GetItemByPos(slot);
}
return NULL;
@@ -9090,9 +9189,9 @@ Item* Player::GetShield(bool useable) const
return item;
}
-uint8 Player::GetAttackBySlot(uint8 slot)
+uint8 Player::GetAttackBySlot( uint8 slot )
{
- switch (slot)
+ switch(slot)
{
case EQUIPMENT_SLOT_MAINHAND: return BASE_ATTACK;
case EQUIPMENT_SLOT_OFFHAND: return OFF_ATTACK;
@@ -9101,35 +9200,35 @@ uint8 Player::GetAttackBySlot(uint8 slot)
}
}
-bool Player::IsInventoryPos(uint8 bag, uint8 slot)
+bool Player::IsInventoryPos( uint8 bag, uint8 slot )
{
- if (bag == INVENTORY_SLOT_BAG_0 && slot == NULL_SLOT)
+ if( bag == INVENTORY_SLOT_BAG_0 && slot == NULL_SLOT )
return true;
- if (bag == INVENTORY_SLOT_BAG_0 && slot >= INVENTORY_SLOT_ITEM_START && slot < INVENTORY_SLOT_ITEM_END)
+ if( bag == INVENTORY_SLOT_BAG_0 && ( slot >= INVENTORY_SLOT_ITEM_START && slot < INVENTORY_SLOT_ITEM_END ) )
return true;
- if (bag >= INVENTORY_SLOT_BAG_START && bag < INVENTORY_SLOT_BAG_END)
+ if( bag >= INVENTORY_SLOT_BAG_START && bag < INVENTORY_SLOT_BAG_END )
return true;
- if (bag == INVENTORY_SLOT_BAG_0 && slot >= KEYRING_SLOT_START && slot < CURRENCYTOKEN_SLOT_END)
+ if( bag == INVENTORY_SLOT_BAG_0 && ( slot >= KEYRING_SLOT_START && slot < CURRENCYTOKEN_SLOT_END ) )
return true;
return false;
}
-bool Player::IsEquipmentPos(uint8 bag, uint8 slot)
+bool Player::IsEquipmentPos( uint8 bag, uint8 slot )
{
- if (bag == INVENTORY_SLOT_BAG_0 && slot < EQUIPMENT_SLOT_END)
+ if( bag == INVENTORY_SLOT_BAG_0 && ( slot < EQUIPMENT_SLOT_END ) )
return true;
- if (bag == INVENTORY_SLOT_BAG_0 && slot >= INVENTORY_SLOT_BAG_START && slot < INVENTORY_SLOT_BAG_END)
+ if( bag == INVENTORY_SLOT_BAG_0 && ( slot >= INVENTORY_SLOT_BAG_START && slot < INVENTORY_SLOT_BAG_END ) )
return true;
return false;
}
-bool Player::IsBankPos(uint8 bag, uint8 slot)
+bool Player::IsBankPos( uint8 bag, uint8 slot )
{
- if (bag == INVENTORY_SLOT_BAG_0 && slot >= BANK_SLOT_ITEM_START && slot < BANK_SLOT_ITEM_END)
+ if( bag == INVENTORY_SLOT_BAG_0 && ( slot >= BANK_SLOT_ITEM_START && slot < BANK_SLOT_ITEM_END ) )
return true;
- if (bag == INVENTORY_SLOT_BAG_0 && slot >= BANK_SLOT_BAG_START && slot < BANK_SLOT_BAG_END)
+ if( bag == INVENTORY_SLOT_BAG_0 && ( slot >= BANK_SLOT_BAG_START && slot < BANK_SLOT_BAG_END ) )
return true;
- if (bag >= BANK_SLOT_BAG_START && bag < BANK_SLOT_BAG_END)
+ if( bag >= BANK_SLOT_BAG_START && bag < BANK_SLOT_BAG_END )
return true;
return false;
}
@@ -9138,14 +9237,14 @@ bool Player::IsBagPos( uint16 pos )
{
uint8 bag = pos >> 8;
uint8 slot = pos & 255;
- if (bag == INVENTORY_SLOT_BAG_0 && slot >= INVENTORY_SLOT_BAG_START && slot < INVENTORY_SLOT_BAG_END)
+ if( bag == INVENTORY_SLOT_BAG_0 && ( slot >= INVENTORY_SLOT_BAG_START && slot < INVENTORY_SLOT_BAG_END ) )
return true;
- if (bag == INVENTORY_SLOT_BAG_0 && slot >= BANK_SLOT_BAG_START && slot < BANK_SLOT_BAG_END)
+ if( bag == INVENTORY_SLOT_BAG_0 && ( slot >= BANK_SLOT_BAG_START && slot < BANK_SLOT_BAG_END ) )
return true;
return false;
}
-bool Player::IsValidPos(uint8 bag, uint8 slot)
+bool Player::IsValidPos( uint8 bag, uint8 slot )
{
// post selected
if(bag == NULL_BAG)
@@ -9188,7 +9287,7 @@ bool Player::IsValidPos(uint8 bag, uint8 slot)
if (bag >= INVENTORY_SLOT_BAG_START && bag < INVENTORY_SLOT_BAG_END)
{
Bag* pBag = (Bag*)GetItemByPos (INVENTORY_SLOT_BAG_0, bag);
- if (!pBag)
+ if(!pBag)
return false;
// any post selected
@@ -9202,7 +9301,7 @@ bool Player::IsValidPos(uint8 bag, uint8 slot)
if( bag >= BANK_SLOT_BAG_START && bag < BANK_SLOT_BAG_END )
{
Bag* pBag = (Bag*)GetItemByPos (INVENTORY_SLOT_BAG_0, bag);
- if (!pBag)
+ if(!pBag)
return false;
// any post selected
@@ -9219,66 +9318,66 @@ bool Player::IsValidPos(uint8 bag, uint8 slot)
bool Player::HasItemCount( uint32 item, uint32 count, bool inBankAlso ) const
{
uint32 tempcount = 0;
- for (uint8 i = EQUIPMENT_SLOT_START; i < INVENTORY_SLOT_ITEM_END; ++i)
+ for (uint8 i = EQUIPMENT_SLOT_START; i < INVENTORY_SLOT_ITEM_END; i++)
{
Item *pItem = GetItemByPos( INVENTORY_SLOT_BAG_0, i );
- if (pItem && pItem->GetEntry() == item)
+ if( pItem && pItem->GetEntry() == item )
{
tempcount += pItem->GetCount();
- if (tempcount >= count)
+ if( tempcount >= count )
return true;
}
}
for (uint8 i = KEYRING_SLOT_START; i < CURRENCYTOKEN_SLOT_END; ++i)
{
Item *pItem = GetItemByPos( INVENTORY_SLOT_BAG_0, i );
- if (pItem && pItem->GetEntry() == item)
+ if( pItem && pItem->GetEntry() == item )
{
tempcount += pItem->GetCount();
- if (tempcount >= count)
+ if( tempcount >= count )
return true;
}
}
- for (uint8 i = INVENTORY_SLOT_BAG_START; i < INVENTORY_SLOT_BAG_END; ++i)
+ for (uint8 i = INVENTORY_SLOT_BAG_START; i < INVENTORY_SLOT_BAG_END; i++)
{
- if (Bag* pBag = (Bag*)GetItemByPos(INVENTORY_SLOT_BAG_0, i))
+ if(Bag* pBag = (Bag*)GetItemByPos( INVENTORY_SLOT_BAG_0, i ))
{
- for (uint32 j = 0; j < pBag->GetBagSize(); ++j)
+ for (uint32 j = 0; j < pBag->GetBagSize(); j++)
{
Item* pItem = GetItemByPos( i, j );
- if (pItem && pItem->GetEntry() == item)
+ if( pItem && pItem->GetEntry() == item )
{
tempcount += pItem->GetCount();
- if (tempcount >= count)
+ if( tempcount >= count )
return true;
}
}
}
}
- if (inBankAlso)
+ if(inBankAlso)
{
- for (uint8 i = BANK_SLOT_ITEM_START; i < BANK_SLOT_ITEM_END; ++i)
+ for (uint8 i = BANK_SLOT_ITEM_START; i < BANK_SLOT_ITEM_END; i++)
{
- Item *pItem = GetItemByPos(INVENTORY_SLOT_BAG_0, i);
- if (pItem && pItem->GetEntry() == item)
+ Item *pItem = GetItemByPos( INVENTORY_SLOT_BAG_0, i );
+ if( pItem && pItem->GetEntry() == item )
{
tempcount += pItem->GetCount();
- if (tempcount >= count)
+ if( tempcount >= count )
return true;
}
}
- for (uint8 i = BANK_SLOT_BAG_START; i < BANK_SLOT_BAG_END; ++i)
+ for (uint8 i = BANK_SLOT_BAG_START; i < BANK_SLOT_BAG_END; i++)
{
- if(Bag* pBag = (Bag*)GetItemByPos( INVENTORY_SLOT_BAG_0, i))
+ if(Bag* pBag = (Bag*)GetItemByPos( INVENTORY_SLOT_BAG_0, i ))
{
- for (uint32 j = 0; j < pBag->GetBagSize(); ++j)
+ for (uint32 j = 0; j < pBag->GetBagSize(); j++)
{
- Item *pItem = GetItemByPos(i, j);
- if (pItem && pItem->GetEntry() == item)
+ Item* pItem = GetItemByPos( i, j );
+ if( pItem && pItem->GetEntry() == item )
{
tempcount += pItem->GetCount();
- if (tempcount >= count)
+ if( tempcount >= count )
return true;
}
}
@@ -9289,19 +9388,19 @@ bool Player::HasItemCount( uint32 item, uint32 count, bool inBankAlso ) const
return false;
}
-bool Player::HasItemOrGemWithIdEquipped(uint32 item, uint32 count, uint8 except_slot) const
+bool Player::HasItemOrGemWithIdEquipped( uint32 item, uint32 count, uint8 except_slot ) const
{
uint32 tempcount = 0;
for (uint8 i = EQUIPMENT_SLOT_START; i < EQUIPMENT_SLOT_END; ++i)
{
- if (i == except_slot)
+ if(i == except_slot)
continue;
- Item *pItem = GetItemByPos( INVENTORY_SLOT_BAG_0, i);
- if (pItem && pItem->GetEntry() == item)
+ Item *pItem = GetItemByPos( INVENTORY_SLOT_BAG_0, i );
+ if( pItem && pItem->GetEntry() == item)
{
tempcount += pItem->GetCount();
- if (tempcount >= count)
+ if( tempcount >= count )
return true;
}
}
@@ -9311,14 +9410,14 @@ bool Player::HasItemOrGemWithIdEquipped(uint32 item, uint32 count, uint8 except_
{
for (uint8 i = EQUIPMENT_SLOT_START; i < EQUIPMENT_SLOT_END; ++i)
{
- if (i == except_slot)
+ if(i == except_slot)
continue;
- Item *pItem = GetItemByPos( INVENTORY_SLOT_BAG_0, i);
- if (pItem && pItem->GetProto()->Socket[0].Color)
+ Item *pItem = GetItemByPos( INVENTORY_SLOT_BAG_0, i );
+ if( pItem && pItem->GetProto()->Socket[0].Color)
{
tempcount += pItem->GetGemCountWithID(item);
- if (tempcount >= count)
+ if( tempcount >= count )
return true;
}
}
@@ -12298,6 +12397,15 @@ void Player::ApplyEnchantment(Item *item, EnchantmentSlot slot, bool apply, bool
if (!ignore_condition && pEnchant->EnchantmentCondition && !((Player*)this)->EnchantmentFitsRequirements(pEnchant->EnchantmentCondition, -1))
return;
+ if ((pEnchant->requiredLevel) > ((Player*)this)->getLevel())
+ return;
+
+ if ((pEnchant->requiredSkill) > 0)
+ {
+ if ((pEnchant->requiredSkillValue) > (((Player*)this)->GetSkillValue(pEnchant->requiredSkill)))
+ return;
+ }
+
if (!item->IsBroken())
{
for (int s = 0; s < 3; ++s)
@@ -12560,6 +12668,10 @@ void Player::ApplyEnchantment(Item *item, EnchantmentSlot slot, bool apply, bool
((Player*)this)->ApplySpellPowerBonus(enchant_amount, apply);
sLog.outDebug("+ %u SPELL_POWER", enchant_amount);
break;
+ case ITEM_MOD_HEALTH_REGEN:
+ ((Player*)this)->ApplyHealthRegenBonus(enchant_amount, apply);
+ sLog.outDebug("+ %u HEALTH_REGENERATION", enchant_amount);
+ break;
case ITEM_MOD_SPELL_HEALING_DONE: // deprecated
case ITEM_MOD_SPELL_DAMAGE_DONE: // deprecated
default:
@@ -12936,7 +13048,7 @@ bool Player::CanCompleteQuest( uint32 quest_id )
if ( qInfo->HasFlag( QUEST_TRINITY_FLAGS_DELIVER ) )
{
- for (uint8 i = 0; i < QUEST_OBJECTIVES_COUNT; i++)
+ for (uint8 i = 0; i < QUEST_ITEM_OBJECTIVES_COUNT; i++)
{
if( qInfo->ReqItemCount[i]!= 0 && q_status.m_itemcount[i] < qInfo->ReqItemCount[i] )
return false;
@@ -12986,7 +13098,7 @@ bool Player::CanCompleteRepeatableQuest( Quest const *pQuest )
return false;
if (pQuest->HasFlag( QUEST_TRINITY_FLAGS_DELIVER) )
- for (uint8 i = 0; i < QUEST_OBJECTIVES_COUNT; i++)
+ for (uint8 i = 0; i < QUEST_ITEM_OBJECTIVES_COUNT; i++)
if( pQuest->ReqItemId[i] && pQuest->ReqItemCount[i] && !HasItemCount(pQuest->ReqItemId[i],pQuest->ReqItemCount[i]) )
return false;
@@ -13013,7 +13125,7 @@ bool Player::CanRewardQuest( Quest const *pQuest, bool msg )
// prevent receive reward with quest items in bank
if ( pQuest->HasFlag( QUEST_TRINITY_FLAGS_DELIVER ) )
{
- for (uint8 i = 0; i < QUEST_OBJECTIVES_COUNT; i++)
+ for (uint8 i = 0; i < QUEST_ITEM_OBJECTIVES_COUNT; i++)
{
if( pQuest->ReqItemCount[i]!= 0 &&
GetItemCount(pQuest->ReqItemId[i]) < pQuest->ReqItemCount[i] )
@@ -13088,7 +13200,7 @@ void Player::AddQuest( Quest const *pQuest, Object *questGiver )
if ( pQuest->HasFlag( QUEST_TRINITY_FLAGS_DELIVER ) )
{
- for (uint8 i = 0; i < QUEST_OBJECTIVES_COUNT; ++i)
+ for (uint8 i = 0; i < QUEST_ITEM_OBJECTIVES_COUNT; ++i)
questStatusData.m_itemcount[i] = 0;
}
@@ -13186,13 +13298,10 @@ void Player::RewardQuest( Quest const *pQuest, uint32 reward, Object* questGiver
uint32 quest_id = pQuest->GetQuestId();
- for (uint8 i = 0; i < QUEST_OBJECTIVES_COUNT; ++i)
+ for (uint8 i = 0; i < QUEST_ITEM_OBJECTIVES_COUNT; ++i)
if (pQuest->ReqItemId[i])
DestroyItemCount( pQuest->ReqItemId[i], pQuest->ReqItemCount[i], true);
-// This is wrong. If SrcItem is supposed to be destroyed on quest complete then the item will be either in ReqItemId or ReqSrcItemId
-// TakeQuestSourceItem(quest_id, true); // take quest src item from player on completing quest
-
for (uint8 i = 0; i < QUEST_SOURCE_ITEM_IDS_COUNT; ++i)
{
if (pQuest->ReqSourceId[i])
@@ -13864,7 +13973,7 @@ void Player::AdjustQuestReqItemCount(Quest const* pQuest, QuestStatusData& quest
{
if (pQuest->HasFlag( QUEST_TRINITY_FLAGS_DELIVER))
{
- for (uint8 i = 0; i < QUEST_OBJECTIVES_COUNT; ++i)
+ for (uint8 i = 0; i < QUEST_ITEM_OBJECTIVES_COUNT; ++i)
{
uint32 reqitemcount = pQuest->ReqItemCount[i];
if (reqitemcount != 0)
@@ -13944,7 +14053,7 @@ void Player::ItemAddedQuestCheck( uint32 entry, uint32 count)
if( !qInfo || !qInfo->HasFlag(QUEST_TRINITY_FLAGS_DELIVER))
continue;
- for (uint8 j = 0; j < QUEST_OBJECTIVES_COUNT; ++j)
+ for (uint8 j = 0; j < QUEST_ITEM_OBJECTIVES_COUNT; ++j)
{
uint32 reqitem = qInfo->ReqItemId[j];
if (reqitem == entry)
@@ -13981,7 +14090,7 @@ void Player::ItemRemovedQuestCheck( uint32 entry, uint32 count)
if( !qInfo->HasFlag(QUEST_TRINITY_FLAGS_DELIVER))
continue;
- for (uint8 j = 0; j < QUEST_OBJECTIVES_COUNT; ++j)
+ for (uint8 j = 0; j < QUEST_ITEM_OBJECTIVES_COUNT; ++j)
{
uint32 reqitem = qInfo->ReqItemId[j];
if (reqitem == entry)
@@ -14295,7 +14404,7 @@ bool Player::HasQuestForItem(uint32 itemid) const
// There should be no mixed ReqItem/ReqSource drop
// This part for ReqItem drop
- for (uint8 j = 0; j < QUEST_OBJECTIVES_COUNT; ++j)
+ for (uint8 j = 0; j < QUEST_ITEM_OBJECTIVES_COUNT; ++j)
{
if (itemid == qinfo->ReqItemId[j] && q_status.m_itemcount[j] < qinfo->ReqItemCount[j])
return true;
@@ -14369,7 +14478,7 @@ void Player::SendQuestFailed( uint32 quest_id )
if( quest_id )
{
WorldPacket data( SMSG_QUESTGIVER_QUEST_FAILED, 4+4 );
- data << quest_id;
+ data << uint32(quest_id);
data << uint32(0); // failed reason (4 for inventory is full)
GetSession()->SendPacket( &data );
sLog.outDebug("WORLD: Sent SMSG_QUESTGIVER_QUEST_FAILED");
@@ -14381,7 +14490,7 @@ void Player::SendQuestTimerFailed( uint32 quest_id )
if( quest_id )
{
WorldPacket data( SMSG_QUESTUPDATE_FAILEDTIMER, 4 );
- data << quest_id;
+ data << uint32(quest_id);
GetSession()->SendPacket( &data );
sLog.outDebug("WORLD: Sent SMSG_QUESTUPDATE_FAILEDTIMER");
}
@@ -14522,7 +14631,7 @@ void Player::_LoadDeclinedNames(QueryResult* result)
void Player::_LoadArenaTeamInfo(QueryResult *result)
{
// arenateamid, played_week, played_season, personal_rating
- memset((void*)&m_uint32Values[PLAYER_FIELD_ARENA_TEAM_INFO_1_1], 0, sizeof(uint32)*18);
+ memset((void*)&m_uint32Values[PLAYER_FIELD_ARENA_TEAM_INFO_1_1], 0, sizeof(uint32) * MAX_ARENA_SLOT * ARENA_TEAM_END);
if (!result)
return;
@@ -14533,22 +14642,24 @@ void Player::_LoadArenaTeamInfo(QueryResult *result)
uint32 arenateamid = fields[0].GetUInt32();
uint32 played_week = fields[1].GetUInt32();
uint32 played_season = fields[2].GetUInt32();
- uint32 personal_rating = fields[3].GetUInt32();
+ uint32 wons_season = fields[3].GetUInt32();
+ uint32 personal_rating = fields[4].GetUInt32();
ArenaTeam* aTeam = objmgr.GetArenaTeamById(arenateamid);
if(!aTeam)
{
- sLog.outError("Player::_LoadArenaTeamInfo: couldn't load arenateam %u, week %u, season %u, rating %u", arenateamid, played_week, played_season, personal_rating);
+ sLog.outError("Player::_LoadArenaTeamInfo: couldn't load arenateam %u", arenateamid);
continue;
}
uint8 arenaSlot = aTeam->GetSlot();
- m_uint32Values[PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + arenaSlot * 6] = arenateamid; // TeamID
- m_uint32Values[PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + arenaSlot * 6 + 1] = ((aTeam->GetCaptain() == GetGUID()) ? (uint32)0 : (uint32)1); // Captain 0, member 1
- m_uint32Values[PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + arenaSlot * 6 + 2] = played_week; // Played Week
- m_uint32Values[PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + arenaSlot * 6 + 3] = played_season; // Played Season
- m_uint32Values[PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + arenaSlot * 6 + 4] = 0; // Unk
- m_uint32Values[PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + arenaSlot * 6 + 5] = personal_rating; // Personal Rating
+ m_uint32Values[PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + (arenaSlot * ARENA_TEAM_END) + ARENA_TEAM_ID] = arenateamid; // TeamID
+ m_uint32Values[PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + (arenaSlot * ARENA_TEAM_END) + ARENA_TEAM_TYPE] = aTeam->GetType(); // team type
+ m_uint32Values[PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + (arenaSlot * ARENA_TEAM_END) + ARENA_TEAM_MEMBER] = ((aTeam->GetCaptain() == GetGUID()) ? (uint32)0 : (uint32)1); // Captain 0, member 1
+ m_uint32Values[PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + (arenaSlot * ARENA_TEAM_END) + ARENA_TEAM_GAMES_WEEK] = played_week; // Played Week
+ m_uint32Values[PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + (arenaSlot * ARENA_TEAM_END) + ARENA_TEAM_GAMES_SEASON] = played_season; // Played Season
+ m_uint32Values[PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + (arenaSlot * ARENA_TEAM_END) + ARENA_TEAM_WINS_SEASON] = wons_season; // wins season
+ m_uint32Values[PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + (arenaSlot * ARENA_TEAM_END) + ARENA_TEAM_PERSONAL_RATING] = personal_rating; // Personal Rating
}while (result->NextRow());
delete result;
@@ -14661,37 +14772,6 @@ float Player::GetFloatValueFromArray(Tokens const& data, uint16 index)
uint32 Player::GetUInt32ValueFromDB(uint16 index, uint64 guid)
{
- // todo: cleanup in this, move to a separate function.
- if( index == PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + 0 * 6 + 5
- || index == PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + 1 * 6 + 5
- || index == PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + 2 * 6 + 5
- || index == PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + (0 * 6)
- || index == PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + (1 * 6)
- || index == PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + (2 * 6)
- || index == UNIT_FIELD_LEVEL)
- {
- CachePlayerInfoMap::iterator _iter = objmgr.m_mPlayerInfoMap.find(GUID_LOPART(guid));
- if(_iter != objmgr.m_mPlayerInfoMap.end())
- {
- switch(index)
- {
- case (PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + 0 * 6 + 5):
- return _iter->second->unArenaInfoSlot0;
- case (PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + 1 * 6 + 5):
- return _iter->second->unArenaInfoSlot1;
- case (PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + 2 * 6 + 5):
- return _iter->second->unArenaInfoSlot2;
- case (PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + (0 * 6)):
- return _iter->second->unArenaInfoId0;
- case (PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + (1 * 6)):
- return _iter->second->unArenaInfoId1;
- case (PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + (2 * 6)):
- return _iter->second->unArenaInfoId2;
- case (UNIT_FIELD_LEVEL):
- return _iter->second->unLevel;
- }
- }
- }
Tokens data;
if(!LoadValuesArrayFromDB(data,guid))
return 0;
@@ -14811,7 +14891,11 @@ bool Player::LoadFromDB( uint32 guid, SqlQueryHolder *holder )
Relocate(fields[13].GetFloat(),fields[14].GetFloat(),fields[15].GetFloat(),fields[17].GetFloat());
uint32 mapId = fields[16].GetUInt32();
uint32 instanceId = fields[41].GetFloat();
- SetDifficulty(fields[39].GetUInt32()); // may be changed in _LoadGroup
+
+ uint32 difficulty = fields[39].GetUInt32();
+ if(difficulty >= MAX_DUNGEON_DIFFICULTY)
+ difficulty = DUNGEON_DIFFICULTY_NORMAL;
+ SetDungeonDifficulty(Difficulty(difficulty)); // may be changed in _LoadGroup
std::string taxi_nodes = fields[38].GetCppString();
#define RelocateToHomebind(){ mapId = m_homebindMapId; instanceId = 0; Relocate(m_homebindX, m_homebindY, m_homebindZ); }
@@ -14839,7 +14923,7 @@ bool Player::LoadFromDB( uint32 guid, SqlQueryHolder *holder )
// arena team not exist or not member, cleanup fields
for (int j = 0; j < 6; ++j)
- SetUInt32Value(PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + arena_slot * 6 + j, 0);
+ SetUInt32Value(PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + (arena_slot * ARENA_TEAM_END) + j, 0);
}
_LoadBoundInstances(holder->GetResult(PLAYER_LOGIN_QUERY_LOADBOUNDINSTANCES));
@@ -14989,7 +15073,7 @@ bool Player::LoadFromDB( uint32 guid, SqlQueryHolder *holder )
// fix crash (because of if(Map *map = _FindMap(instanceId)) in MapInstanced::CreateInstance)
if(instanceId)
- if(InstanceSave * save = GetInstanceSave(mapId))
+ if(InstanceSave * save = GetInstanceSave(mapId, mapEntry->IsRaid()))
if(save->GetInstanceId() != instanceId)
instanceId = 0;
@@ -15816,7 +15900,7 @@ void Player::_LoadQuestStatus(QueryResult *result)
((questStatusData.m_status == QUEST_STATUS_INCOMPLETE ||
questStatusData.m_status == QUEST_STATUS_COMPLETE ||
questStatusData.m_status == QUEST_STATUS_FAILED) &&
- (!questStatusData.m_rewarded || pQuest->IsRepeatable())))
+ (!questStatusData.m_rewarded || pQuest->IsDaily())))
{
SetQuestSlot(slot, quest_id, quest_time);
@@ -15935,15 +16019,18 @@ void Player::_LoadGroup(QueryResult *result)
uint8 subgroup = group->GetMemberGroup(GetGUID());
SetGroup(group, subgroup);
if (getLevel() >= LEVELREQUIREMENT_HEROIC)
+ {
// the group leader may change the instance difficulty while the player is offline
- SetDifficulty(group->GetDifficulty());
+ SetDungeonDifficulty(group->GetDungeonDifficulty());
+ SetRaidDifficulty(group->GetRaidDifficulty());
+ }
}
}
}
void Player::_LoadBoundInstances(QueryResult *result)
{
- for (uint8 i = 0; i < TOTAL_DIFFICULTIES; ++i)
+ for (uint8 i = 0; i < MAX_DIFFICULTY; ++i)
m_boundInstances[i].clear();
Group *group = GetGroup();
@@ -15958,6 +16045,7 @@ void Player::_LoadBoundInstances(QueryResult *result)
uint32 mapId = fields[2].GetUInt32();
uint32 instanceId = fields[0].GetUInt32();
uint8 difficulty = fields[3].GetUInt8();
+
time_t resetTime = (time_t)fields[4].GetUInt64();
// the resettime for normal instances is only saved when the InstanceSave is unloaded
// so the value read from the DB may be wrong here but only if the InstanceSave is loaded
@@ -15971,6 +16059,22 @@ void Player::_LoadBoundInstances(QueryResult *result)
continue;
}
+ if(difficulty >= MAX_DIFFICULTY)
+ {
+ sLog.outError("_LoadBoundInstances: player %s(%d) has bind to not existed difficulty %d instance for map %u", GetName(), GetGUIDLow(), difficulty, mapId);
+ CharacterDatabase.PExecute("DELETE FROM character_instance WHERE guid = '%d' AND instance = '%d'", GetGUIDLow(), instanceId);
+ continue;
+ }
+
+ MapDifficulty const* mapDiff = GetMapDifficultyData(mapId,Difficulty(difficulty));
+ if(!mapDiff)
+ {
+ sLog.outError("_LoadBoundInstances: player %s(%d) has bind to not existed difficulty %d instance for map %u", GetName(), GetGUIDLow(), difficulty, mapId);
+ CharacterDatabase.PExecute("DELETE FROM character_instance WHERE guid = '%d' AND instance = '%d'", GetGUIDLow(), instanceId);
+ continue;
+ }
+
+
if (!perm && group)
{
sLog.outError("_LoadBoundInstances: player %s(%d) is in group %d but has a non-permanent character bind to map %d,%d,%d", GetName(), GetGUIDLow(), GUID_LOPART(group->GetLeaderGUID()), mapId, instanceId, difficulty);
@@ -15979,18 +16083,19 @@ void Player::_LoadBoundInstances(QueryResult *result)
}
// since non permanent binds are always solo bind, they can always be reset
- if (InstanceSave *save = sInstanceSaveManager.AddInstanceSave(mapId, instanceId, difficulty, resetTime, !perm, true))
+ if (InstanceSave *save = sInstanceSaveManager.AddInstanceSave(mapId, instanceId, Difficulty(difficulty), resetTime, !perm, true))
BindToInstance(save, perm, true);
} while (result->NextRow());
delete result;
}
}
-InstancePlayerBind* Player::GetBoundInstance(uint32 mapid, uint8 difficulty)
+InstancePlayerBind* Player::GetBoundInstance(uint32 mapid, Difficulty difficulty)
{
// some instances only have one difficulty
- const MapEntry* entry = sMapStore.LookupEntry(mapid);
- if (!entry || !entry->SupportsHeroicMode()) difficulty = DIFFICULTY_NORMAL;
+ MapDifficulty const* mapDiff = GetMapDifficultyData(mapid,difficulty);
+ if(!mapDiff)
+ return NULL;
BoundInstancesMap::iterator itr = m_boundInstances[difficulty].find(mapid);
if (itr != m_boundInstances[difficulty].end())
@@ -15999,25 +16104,25 @@ InstancePlayerBind* Player::GetBoundInstance(uint32 mapid, uint8 difficulty)
return NULL;
}
-InstanceSave * Player::GetInstanceSave(uint32 mapid)
+InstanceSave * Player::GetInstanceSave(uint32 mapid, bool raid)
{
- InstancePlayerBind *pBind = GetBoundInstance(mapid, GetDifficulty());
+ InstancePlayerBind *pBind = GetBoundInstance(mapid, GetDifficulty(raid));
InstanceSave *pSave = pBind ? pBind->save : NULL;
if (!pBind || !pBind->perm)
if(Group *group = GetGroup())
- if(InstanceGroupBind *groupBind = group->GetBoundInstance(mapid, GetDifficulty()))
+ if(InstanceGroupBind *groupBind = group->GetBoundInstance(this))
pSave = groupBind->save;
return pSave;
}
-void Player::UnbindInstance(uint32 mapid, uint8 difficulty, bool unload)
+void Player::UnbindInstance(uint32 mapid, Difficulty difficulty, bool unload)
{
BoundInstancesMap::iterator itr = m_boundInstances[difficulty].find(mapid);
UnbindInstance(itr, difficulty, unload);
}
-void Player::UnbindInstance(BoundInstancesMap::iterator &itr, uint8 difficulty, bool unload)
+void Player::UnbindInstance(BoundInstancesMap::iterator &itr, Difficulty difficulty, bool unload)
{
if (itr != m_boundInstances[difficulty].end())
{
@@ -16074,7 +16179,7 @@ void Player::SendRaidInfo()
time_t now = time(NULL);
- for (uint8 i = 0; i < TOTAL_DIFFICULTIES; ++i)
+ for (uint8 i = 0; i < MAX_DIFFICULTY; ++i)
{
for (BoundInstancesMap::iterator itr = m_boundInstances[i].begin(); itr != m_boundInstances[i].end(); ++itr)
{
@@ -16084,8 +16189,9 @@ void Player::SendRaidInfo()
data << uint32(save->GetMapId()); // map id
data << uint32(save->GetDifficulty()); // difficulty
data << uint64(save->GetInstanceId()); // instance id
+ data << uint8(1); // expired = 0
+ data << uint8(0); // extended = 1
data << uint32(save->GetResetTime() - now); // reset time
- data << uint32(0); // is extended
++counter;
}
}
@@ -16102,7 +16208,7 @@ void Player::SendSavedInstances()
bool hasBeenSaved = false;
WorldPacket data;
- for (uint8 i = 0; i < TOTAL_DIFFICULTIES; ++i)
+ for (uint8 i = 0; i < MAX_DIFFICULTY; ++i)
{
for (BoundInstancesMap::iterator itr = m_boundInstances[i].begin(); itr != m_boundInstances[i].end(); ++itr)
{
@@ -16122,7 +16228,7 @@ void Player::SendSavedInstances()
if (!hasBeenSaved)
return;
- for (uint8 i = 0; i < TOTAL_DIFFICULTIES; ++i)
+ for (uint8 i = 0; i < MAX_DIFFICULTY; ++i)
{
for (BoundInstancesMap::iterator itr = m_boundInstances[i].begin(); itr != m_boundInstances[i].end(); ++itr)
{
@@ -16155,7 +16261,7 @@ void Player::ConvertInstancesToGroup(Player *player, Group *group, uint64 player
if (player)
{
- for (uint8 i = 0; i < TOTAL_DIFFICULTIES; ++i)
+ for (uint8 i = 0; i < MAX_DIFFICULTY; ++i)
{
for (BoundInstancesMap::iterator itr = player->m_boundInstances[i].begin(); itr != player->m_boundInstances[i].end();)
{
@@ -16165,7 +16271,8 @@ void Player::ConvertInstancesToGroup(Player *player, Group *group, uint64 player
// permanent binds are not removed
if (!itr->second.perm)
{
- player->UnbindInstance(itr, i, true); // increments itr
+ // increments itr in call
+ player->UnbindInstance(itr, Difficulty(i), true);
has_solo = true;
}
else
@@ -16193,7 +16300,7 @@ bool Player::Satisfy(AccessRequirement const *ar, uint32 target_map, bool report
{
if (ar->levelMin && getLevel() < ar->levelMin)
LevelMin = ar->levelMin;
- if (ar->heroicLevelMin && GetDifficulty() == DIFFICULTY_HEROIC && getLevel() < ar->heroicLevelMin)
+ if(ar->heroicLevelMin && GetDungeonDifficulty() == DUNGEON_DIFFICULTY_HEROIC && getLevel() < ar->heroicLevelMin)
LevelMin = ar->heroicLevelMin;
if (ar->levelMax && getLevel() > ar->levelMax)
LevelMax = ar->levelMax;
@@ -16209,9 +16316,17 @@ bool Player::Satisfy(AccessRequirement const *ar, uint32 target_map, bool report
else if(ar->item2 && !HasItemCount(ar->item2, 1))
missingItem = ar->item2;
+ MapEntry const* mapEntry = sMapStore.LookupEntry(target_map);
+ if(!mapEntry)
+ return false;
+
+ bool isNormalTargetMap = mapEntry->IsRaid()
+ ? (GetRaidDifficulty() == RAID_DIFFICULTY_10MAN_NORMAL)
+ : (GetDungeonDifficulty() == DUNGEON_DIFFICULTY_NORMAL);
+
uint32 missingKey = 0;
uint32 missingHeroicQuest = 0;
- if (GetDifficulty() == DIFFICULTY_HEROIC)
+ if(!isNormalTargetMap)
{
if (ar->heroicKey)
{
@@ -16237,7 +16352,7 @@ bool Player::Satisfy(AccessRequirement const *ar, uint32 target_map, bool report
if (missingItem)
GetSession()->SendAreaTriggerMessage(GetSession()->GetTrinityString(LANG_LEVEL_MINREQUIRED_AND_ITEM), LevelMin, objmgr.GetItemPrototype(missingItem)->Name1);
else if (missingKey)
- SendTransferAborted(target_map, TRANSFER_ABORT_DIFFICULTY);
+ SendTransferAborted(target_map, TRANSFER_ABORT_DIFFICULTY, isNormalTargetMap ? DUNGEON_DIFFICULTY_NORMAL : DUNGEON_DIFFICULTY_HEROIC);
else if (missingHeroicQuest)
GetSession()->SendAreaTriggerMessage(ar->heroicQuestFailedText.c_str());
else if (missingQuest)
@@ -16352,7 +16467,7 @@ void Player::SaveToDB()
{
ss << GetMapId() << ", "
<< (uint32)GetInstanceId() << ", "
- << (uint32)GetDifficulty() << ", "
+ << (uint32)GetDungeonDifficulty() << ", "
<< finiteAlways(GetPositionX()) << ", "
<< finiteAlways(GetPositionY()) << ", "
<< finiteAlways(GetPositionZ()) << ", "
@@ -16362,7 +16477,7 @@ void Player::SaveToDB()
{
ss << GetTeleportDest().GetMapId() << ", "
<< (uint32)0 << ", "
- << (uint32)GetDifficulty() << ", "
+ << (uint32)GetDungeonDifficulty() << ", "
<< finiteAlways(GetTeleportDest().GetPositionX()) << ", "
<< finiteAlways(GetTeleportDest().GetPositionY()) << ", "
<< finiteAlways(GetTeleportDest().GetPositionZ()) << ", "
@@ -16950,7 +17065,17 @@ void Player::SendDungeonDifficulty(bool IsInGroup)
{
uint8 val = 0x00000001;
WorldPacket data(MSG_SET_DUNGEON_DIFFICULTY, 12);
- data << (uint32)GetDifficulty();
+ data << (uint32)GetDungeonDifficulty();
+ data << uint32(val);
+ data << uint32(IsInGroup);
+ GetSession()->SendPacket(&data);
+}
+
+void Player::SendRaidDifficulty(bool IsInGroup)
+{
+ uint8 val = 0x00000001;
+ WorldPacket data(MSG_SET_RAID_DIFFICULTY, 12);
+ data << uint32(GetRaidDifficulty());
data << uint32(val);
data << uint32(IsInGroup);
GetSession()->SendPacket(&data);
@@ -16964,18 +17089,18 @@ void Player::SendResetFailedNotify(uint32 mapid)
}
/// Reset all solo instances and optionally send a message on success for each
-void Player::ResetInstances(uint8 method)
+void Player::ResetInstances(uint8 method, bool isRaid)
{
// method can be INSTANCE_RESET_ALL, INSTANCE_RESET_CHANGE_DIFFICULTY, INSTANCE_RESET_GROUP_JOIN
// we assume that when the difficulty changes, all instances that can be reset will be
- uint8 dif = GetDifficulty();
+ Difficulty diff = GetDifficulty(isRaid);
- for (BoundInstancesMap::iterator itr = m_boundInstances[dif].begin(); itr != m_boundInstances[dif].end();)
+ for (BoundInstancesMap::iterator itr = m_boundInstances[diff].begin(); itr != m_boundInstances[diff].end(); )
{
InstanceSave *p = itr->second.save;
const MapEntry *entry = sMapStore.LookupEntry(itr->first);
- if(!entry || !p->CanReset())
+ if(!entry || entry->IsRaid() != isRaid || !p->CanReset())
{
++itr;
continue;
@@ -16984,7 +17109,7 @@ void Player::ResetInstances(uint8 method)
if(method == INSTANCE_RESET_ALL)
{
// the "reset all instances" method can only reset normal maps
- if(dif == DIFFICULTY_HEROIC || entry->map_type == MAP_RAID)
+ if(entry->map_type == MAP_RAID || diff == DUNGEON_DIFFICULTY_HEROIC)
{
++itr;
continue;
@@ -17005,7 +17130,7 @@ void Player::ResetInstances(uint8 method)
SendResetInstanceSuccess(p->GetMapId());
p->DeleteFromDB();
- m_boundInstances[dif].erase(itr++);
+ m_boundInstances[diff].erase(itr++);
// the following should remove the instance save from the manager and delete it as well
p->RemovePlayer(this);
@@ -17085,7 +17210,12 @@ Pet* Player::GetPet() const
if(!IS_PET_GUID(pet_guid))
return NULL;
- if(Pet* pet = ObjectAccessor::GetPet(pet_guid))
+ Pet* pet = ObjectAccessor::GetPet(pet_guid);
+
+ if (!pet)
+ return NULL;
+
+ if(IsInWorld() && pet)
return pet;
//there may be a guardian in slot
@@ -17395,6 +17525,10 @@ void Player::VehicleSpellInitialize()
if(!veh)
return;
+ // GetPosition_ is not a member of 'Vehicle', SetPosition is a member of 'Player': SetPosition(GetVehicle()->GetPositionX(), GetVehicle()->GetPositionY(), GetVehicle()->GetPositionZ(), GetVehicle()->GetOrientation());
+
+ // GetPosition_ is not a member of 'Vehicle', SetPosition is a member of 'Player': SetPosition(GetVehicle()->GetPositionX(), GetVehicle()->GetPositionY(), GetVehicle()->GetPositionZ(), GetVehicle()->GetOrientation());
+
WorldPacket data(SMSG_PET_SPELLS, 8+2+4+4+4*10+1+1);
data << uint64(veh->GetGUID());
data << uint16(0);
@@ -18329,17 +18463,32 @@ bool Player::BuyItemFromVendor(uint64 vendorguid, uint32 item, uint8 count, uint
}
ModifyMoney( -(int32)price );
+ uint32 arenaPoints = 0;
+ uint32 honorPoints = 0;
+ uint32 extendedCost[5] = {0,0,0,0,0};
+ uint32 extendedCostCount[5] = {0,0,0,0,0};
+
if (crItem->ExtendedCost) // case for new honor system
{
ItemExtendedCostEntry const* iece = sItemExtendedCostStore.LookupEntry(crItem->ExtendedCost);
if (iece->reqhonorpoints)
- ModifyHonorPoints( - int32(iece->reqhonorpoints * count));
+ {
+ honorPoints = iece->reqhonorpoints * count;
+ ModifyHonorPoints( - int32(honorPoints) );
+ }
if (iece->reqarenapoints)
- ModifyArenaPoints( - int32(iece->reqarenapoints * count));
+ {
+ arenaPoints = iece->reqarenapoints * count;
+ ModifyArenaPoints( - int32(arenaPoints) );
+ }
for (uint8 i = 0; i < 5; ++i)
{
if (iece->reqitem[i])
+ {
DestroyItemCount(iece->reqitem[i], (iece->reqitemcount[i] * count), true);
+ extendedCost[i] = iece->reqitem[i];
+ extendedCostCount[i] = iece->reqitemcount[i];
+ }
}
}
@@ -18348,13 +18497,22 @@ bool Player::BuyItemFromVendor(uint64 vendorguid, uint32 item, uint8 count, uint
uint32 new_count = pCreature->UpdateVendorItemCurrentCount(crItem,pProto->BuyCount * count);
WorldPacket data(SMSG_BUY_ITEM, (8+4+4+4));
- data << pCreature->GetGUID();
- data << (uint32)(vendor_slot+1); // numbered from 1 at client
- data << (uint32)(crItem->maxcount > 0 ? new_count : 0xFFFFFFFF);
- data << (uint32)count;
+ data << uint64(pCreature->GetGUID());
+ data << uint32(vendor_slot+1); // numbered from 1 at client
+ data << uint32(crItem->maxcount > 0 ? new_count : 0xFFFFFFFF);
+ data << uint32(count);
GetSession()->SendPacket(&data);
-
SendNewItem(it, pProto->BuyCount*count, true, false, false);
+
+ // Item Refund system, only works for non stackable items with extendedcost
+ if(count == 1 && crItem->ExtendedCost )
+ {
+ it->SetPaidArenaPoints(arenaPoints);
+ it->SetPaidHonorPoints(honorPoints);
+ it->SetRefundExpiryTime( time(NULL)+(HOUR*2) );
+ for (uint8 i = 0; i < 5; ++i)
+ it->SetPaidExtendedCost(i, extendedCost[i], extendedCostCount[i]);
+ }
}
}
else if (IsEquipmentPos(bag, slot))
@@ -18393,10 +18551,10 @@ bool Player::BuyItemFromVendor(uint64 vendorguid, uint32 item, uint8 count, uint
uint32 new_count = pCreature->UpdateVendorItemCurrentCount(crItem,pProto->BuyCount * count);
WorldPacket data(SMSG_BUY_ITEM, (8+4+4+4));
- data << pCreature->GetGUID();
- data << (uint32)(vendor_slot+1); // numbered from 1 at client
- data << (uint32)(crItem->maxcount > 0 ? new_count : 0xFFFFFFFF);
- data << (uint32)count;
+ data << uint64(pCreature->GetGUID());
+ data << uint32(vendor_slot + 1); // numbered from 1 at client
+ data << uint32(crItem->maxcount > 0 ? new_count : 0xFFFFFFFF);
+ data << uint32(count);
GetSession()->SendPacket(&data);
SendNewItem(it, pProto->BuyCount*count, true, false, false);
@@ -18423,9 +18581,9 @@ uint32 Player::GetMaxPersonalArenaRatingRequirement()
{
if(ArenaTeam * at = objmgr.GetArenaTeamById(GetArenaTeamId(i)))
{
- uint32 p_rating = GetUInt32Value(PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + (i * 6) + 5);
+ uint32 p_rating = GetUInt32Value(PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + (i * ARENA_TEAM_END) + ARENA_TEAM_PERSONAL_RATING);
uint32 t_rating = at->GetRating();
- p_rating = p_rating<t_rating? p_rating : t_rating;
+ p_rating = p_rating < t_rating ? p_rating : t_rating;
if(max_personal_rating < p_rating)
max_personal_rating = p_rating;
}
@@ -18465,7 +18623,7 @@ void Player::UpdateHomebindTime(uint32 time)
m_HomebindTimer = 60000;
// send message to player
WorldPacket data(SMSG_RAID_GROUP_ONLY, 4+4);
- data << m_HomebindTimer;
+ data << uint32(m_HomebindTimer);
data << uint32(1);
GetSession()->SendPacket(&data);
sLog.outDebug("PLAYER: Player '%s' (GUID: %u) will be teleported to homebind in 60 seconds", GetName(),GetGUIDLow());
@@ -18634,8 +18792,8 @@ void Player::SendCooldownEvent(SpellEntry const *spellInfo, uint32 itemId, Spell
// Send activate cooldown timer (possible 0) at client side
WorldPacket data(SMSG_COOLDOWN_EVENT, (4+8));
- data << spellInfo->Id;
- data << GetGUID();
+ data << uint32(spellInfo->Id);
+ data << uint64(GetGUID());
SendDirectMessage(&data);
}
@@ -19077,14 +19235,16 @@ bool Player::IsVisibleInGridForPlayer( Player const * pl ) const
// It seems in battleground everyone sees everyone, except the enemy-faction ghosts
if (InBattleGround())
{
- if (!(isAlive() || m_deathTimer > 0) && !IsFriendlyTo(pl))
+ if (!(isAlive() || m_deathTimer > 0) && !IsFriendlyTo(pl) )
return false;
return true;
}
// Live player see live player or dead player with not realized corpse
- if (pl->isAlive() || pl->m_deathTimer > 0)
+ if(pl->isAlive() || pl->m_deathTimer > 0)
+ {
return isAlive() || m_deathTimer > 0;
+ }
// Ghost see other friendly ghosts, that's for sure
if(!(isAlive() || m_deathTimer > 0) && IsFriendlyTo(pl))
@@ -19275,7 +19435,7 @@ void Player::SendComboPoints()
void Player::AddComboPoints(Unit* target, int8 count, Spell * spell)
{
- if (!count)
+ if(!count)
return;
int8 * comboPoints = spell ? &spell->m_comboPointGain : &m_comboPoints;
@@ -19283,7 +19443,7 @@ void Player::AddComboPoints(Unit* target, int8 count, Spell * spell)
// without combo points lost (duration checked in aura)
RemoveAurasByType(SPELL_AURA_RETAIN_COMBO_POINTS);
- if (target->GetGUID() == m_comboTarget)
+ if (target->GetGUID() == m_comboTarget)
*comboPoints += count;
else
{
@@ -19355,23 +19515,26 @@ void Player::SetGroup(Group *group, int8 subgroup)
void Player::SendInitialPacketsBeforeAddToMap()
{
- WorldPacket data(SMSG_SET_REST_START_OBSOLETE, 4);
- data << uint32(0); // unknown, may be rest state time or experience
- GetSession()->SendPacket(&data);
-
GetSocial()->SendSocialList();
+ // guild bank list wtf?
+
// Homebind
- data.Initialize(SMSG_BINDPOINTUPDATE, 5*4);
+ WorldPacket data(SMSG_BINDPOINTUPDATE, 5*4);
data << m_homebindX << m_homebindY << m_homebindZ;
data << (uint32) m_homebindMapId;
data << (uint32) m_homebindZoneId;
GetSession()->SendPacket(&data);
// SMSG_SET_PROFICIENCY
+ // SMSG_SET_PCT_SPELL_MODIFIER
+ // SMSG_SET_FLAT_SPELL_MODIFIER
// SMSG_UPDATE_AURA_DURATION
SendTalentsInfoData(false);
+
+ // SMSG_INSTANCE_DIFFICULTY
+
SendInitialSpells();
data.Initialize(SMSG_SEND_UNLEARN_SPELLS, 4);
@@ -19389,6 +19552,14 @@ void Player::SendInitialPacketsBeforeAddToMap()
data << (float)0.01666667f; // game speed
data << uint32(0); // added in 3.1.2
GetSession()->SendPacket( &data );
+
+ GetReputationMgr().SendForceReactions(); // SMSG_SET_FORCED_REACTIONS
+
+ // SMSG_TALENTS_INFO x 2 for pet (unspent points and talents in separate packets...)
+ // SMSG_PET_GUIDS
+ // SMSG_UPDATE_WORLD_STATE
+ // SMSG_POWER_UPDATE
+
}
void Player::SendInitialPacketsAfterAddToMap()
@@ -19468,7 +19639,7 @@ void Player::SendTransferAborted(uint32 mapid, uint8 reason, uint8 arg)
GetSession()->SendPacket(&data);
}
-void Player::SendInstanceResetWarning( uint32 mapid, uint32 difficulty, uint32 time )
+void Player::SendInstanceResetWarning( uint32 mapid, Difficulty difficulty, uint32 time )
{
// type of warning, based on the time remaining until reset
uint32 type;
@@ -19800,12 +19971,8 @@ bool Player::GetBGAccessByLevel(BattleGroundTypeId bgTypeId) const
BGQueueIdBasedOnLevel Player::GetBattleGroundQueueIdFromLevel(BattleGroundTypeId bgTypeId) const
{
- //returned to hardcoded version of this function, because there is no way to code it dynamic
- uint8 level = getLevel();
- if (bgTypeId == BATTLEGROUND_AV)
- level--;
-
- uint32 queue_id = (level / 10) - 1; // for ranges 0 - 19, 20 - 29, 30 - 39, 40 - 49, 50 - 59, 60 - 69, 70 -79, 80
+ // for ranges 0 - 19, 20 - 29, 30 - 39, 40 - 49, 50 - 59, 60 - 69, 70 - 79, 80
+ uint32 queue_id = ( getLevel() / 10) - 1;
if (queue_id >= MAX_BATTLEGROUND_QUEUES)
{
sLog.outError("BattleGround: too high queue_id %u this shouldn't happen", queue_id);
@@ -20740,7 +20907,8 @@ bool Player::CanCaptureTowerPoint()
);
}
-uint32 Player::GetBarberShopCost(uint8 newhairstyle, uint8 newhaircolor, uint8 newfacialhair)
+uint32 Player::GetBarberShopCost(uint8 newhairstyle, uint8 newhaircolor, uint8 newfacialhair, BarberShopStyleEntry const* newSkin )
+
{
uint8 level = getLevel();
@@ -20750,8 +20918,9 @@ uint32 Player::GetBarberShopCost(uint8 newhairstyle, uint8 newhaircolor, uint8 n
uint8 hairstyle = GetByteValue(PLAYER_BYTES, 2);
uint8 haircolor = GetByteValue(PLAYER_BYTES, 3);
uint8 facialhair = GetByteValue(PLAYER_BYTES_2, 0);
+ uint8 skincolor = GetByteValue(PLAYER_BYTES, 0);
- if((hairstyle == newhairstyle) && (haircolor == newhaircolor) && (facialhair == newfacialhair))
+ if((hairstyle == newhairstyle) && (haircolor == newhaircolor) && (facialhair == newfacialhair) && (!newSkin || (newSkin->hair_id == skincolor)))
return 0;
GtBarberShopCostBaseEntry const *bsc = sGtBarberShopCostBaseStore.LookupEntry(level - 1);
@@ -20770,6 +20939,9 @@ uint32 Player::GetBarberShopCost(uint8 newhairstyle, uint8 newhaircolor, uint8 n
if(facialhair != newfacialhair)
cost += bsc->cost * 0.75f; // +3/4 of price
+ if(newSkin && skincolor != newSkin->hair_id)
+ cost += bsc->cost * 0.75f; // +5/6 of price
+
return uint32(cost);
}
@@ -21259,7 +21431,7 @@ void Player::HandleFall(MovementInfo const& movementInfo)
DEBUG_LOG("FALLDAMAGE z=%f sz=%f pZ=%f FallTime=%d mZ=%f damage=%d SF=%d" , movementInfo.z, height, GetPositionZ(), movementInfo.fallTime, height, damage, safe_fall);
}
}
- RemoveAura(44795); // No fly zone - Parachute
+ RemoveAura(61243); // No fly zone - Parachute
}
void Player::UpdateAchievementCriteria( AchievementCriteriaTypes type, uint32 miscvalue1/*=0*/, uint32 miscvalue2/*=0*/, Unit *unit/*=NULL*/, uint32 time/*=0*/ )
@@ -22196,3 +22368,10 @@ std::string Player::GetGuildName()
{
return objmgr.GetGuildById(GetGuildId())->GetName();
}
+
+void Player::SendDuelCountdown(uint32 counter)
+{
+ WorldPacket data(SMSG_DUEL_COUNTDOWN, 4);
+ data << uint32(counter); // seconds
+ GetSession()->SendPacket(&data);
+}
diff --git a/src/game/Player.h b/src/game/Player.h
index 4b3cf3245f7..9038c8926b9 100644
--- a/src/game/Player.h
+++ b/src/game/Player.h
@@ -38,6 +38,7 @@
#include "AchievementMgr.h"
#include "ReputationMgr.h"
#include "BattleGround.h"
+#include "DBCEnums.h"
#include<string>
#include<vector>
@@ -178,7 +179,7 @@ struct ActionButton
}
};
-#define MAX_ACTION_BUTTONS 132 //checked in 2.3.0
+#define MAX_ACTION_BUTTONS 144 //checked in 3.2.0
typedef std::map<uint8,ActionButton> ActionButtonList;
@@ -339,10 +340,10 @@ enum LfgType
enum LfgRoles
{
- LEADER = 1,
- TANK = 2,
- HEALER = 4,
- DAMAGE = 8
+ LEADER = 0x01,
+ TANK = 0x02,
+ HEALER = 0x04,
+ DAMAGE = 0x08
};
struct LookingForGroupSlot
@@ -438,7 +439,9 @@ enum PlayerFlags
PLAYER_FLAGS_UNK22 = 0x00200000,
PLAYER_FLAGS_UNK23 = 0x00400000,
PLAYER_ALLOW_ONLY_ABILITY = 0x00800000, // used by bladestorm and killing spree
- PLAYER_FLAGS_UNK25 = 0x01000000 // disabled all melee ability on tab include autoattack
+ PLAYER_FLAGS_UNK25 = 0x01000000, // disabled all melee ability on tab include autoattack
+
+ PLAYER_FLAGS_NO_XP_GAIN = 0x02000000
};
// used for PLAYER__FIELD_KNOWN_TITLES field (uint64), (1<<bit_index) without (-1)
@@ -734,6 +737,9 @@ enum TransferAbortReason
TRANSFER_ABORT_NEED_GROUP = 0x0B, // 3.1
TRANSFER_ABORT_NOT_FOUND2 = 0x0C, // 3.1
TRANSFER_ABORT_NOT_FOUND3 = 0x0D, // 3.1
+ TRANSFER_ABORT_NOT_FOUND4 = 0x0E, // 3.2
+ TRANSFER_ABORT_REALM_ONLY = 0x0F, // All players on party must be from the same realm.
+ TRANSFER_ABORT_MAP_NOT_ALLOWED = 0x10, // Map can't be entered at this time.
};
enum InstanceResetWarningType
@@ -745,6 +751,19 @@ enum InstanceResetWarningType
RAID_INSTANCE_EXPIRED = 5
};
+// PLAYER_FIELD_ARENA_TEAM_INFO_1_1 offsets
+enum ArenaTeamInfoType
+{
+ ARENA_TEAM_ID = 0,
+ ARENA_TEAM_TYPE = 1, // new in 3.2 - team type?
+ ARENA_TEAM_MEMBER = 2, // 0 - captain, 1 - member
+ ARENA_TEAM_GAMES_WEEK = 3,
+ ARENA_TEAM_GAMES_SEASON = 4,
+ ARENA_TEAM_WINS_SEASON = 5,
+ ARENA_TEAM_PERSONAL_RATING = 6,
+ ARENA_TEAM_END = 7
+};
+
class InstanceSave;
enum RestType
@@ -827,8 +846,8 @@ enum PlayerDelayedOperations
DELAYED_SAVE_PLAYER = 0x01,
DELAYED_RESURRECT_PLAYER = 0x02,
DELAYED_SPELL_CAST_DESERTER = 0x04,
- DELAYED_BG_MOUNT_RESTORE = 0x08, ///< Flag to restore mount state after teleport from BG
- DELAYED_BG_TAXI_RESTORE = 0x10, ///< Flag to restore taxi state after teleport from BG
+ DELAYED_BG_MOUNT_RESTORE = 0x08, ///< Flag to restore mount state after teleport from BG
+ DELAYED_BG_TAXI_RESTORE = 0x10, ///< Flag to restore taxi state after teleport from BG
DELAYED_END
};
@@ -988,12 +1007,11 @@ class MANGOS_DLL_SPEC Player : public Unit
bool IsInWater() const { return m_isInWater; }
bool IsUnderWater() const;
- bool IsFalling() { return GetPositionZ() < m_lastFallZ; }
void SendInitialPacketsBeforeAddToMap();
void SendInitialPacketsAfterAddToMap();
void SendTransferAborted(uint32 mapid, uint8 reason, uint8 arg = 0);
- void SendInstanceResetWarning(uint32 mapid, uint32 difficulty, uint32 time);
+ void SendInstanceResetWarning(uint32 mapid, Difficulty difficulty, uint32 time);
Creature* GetNPCIfCanInteractWith(uint64 guid, uint32 npcflagmask);
bool CanInteractWithNPCs(bool alive = true) const;
@@ -1001,13 +1019,13 @@ class MANGOS_DLL_SPEC Player : public Unit
bool ToggleAFK();
bool ToggleDND();
- bool isAFK() const { return HasFlag(PLAYER_FLAGS,PLAYER_FLAGS_AFK); };
- bool isDND() const { return HasFlag(PLAYER_FLAGS,PLAYER_FLAGS_DND); };
+ bool isAFK() const { return HasFlag(PLAYER_FLAGS,PLAYER_FLAGS_AFK); }
+ bool isDND() const { return HasFlag(PLAYER_FLAGS,PLAYER_FLAGS_DND); }
uint8 chatTag() const;
std::string afkMsg;
std::string dndMsg;
- uint32 GetBarberShopCost(uint8 newhairstyle, uint8 newhaircolor, uint8 newfacialhair);
+ uint32 GetBarberShopCost(uint8 newhairstyle, uint8 newhaircolor, uint8 newfacialhair, BarberShopStyleEntry const* newSkin=NULL);
PlayerSocial *GetSocial() { return m_social; }
@@ -1039,8 +1057,8 @@ class MANGOS_DLL_SPEC Player : public Unit
time_t m_logintime;
time_t m_Last_tick;
uint32 m_Played_time[MAX_PLAYED_TIME_INDEX];
- uint32 GetTotalPlayedTime() { return m_Played_time[PLAYED_TIME_TOTAL]; };
- uint32 GetLevelPlayedTime() { return m_Played_time[PLAYED_TIME_LEVEL]; };
+ uint32 GetTotalPlayedTime() { return m_Played_time[PLAYED_TIME_TOTAL]; }
+ uint32 GetLevelPlayedTime() { return m_Played_time[PLAYED_TIME_LEVEL]; }
void setDeathState(DeathState s); // overwrite Unit::setDeathState
@@ -1051,21 +1069,21 @@ class MANGOS_DLL_SPEC Player : public Unit
inn_pos_y = y;
inn_pos_z = z;
time_inn_enter = time;
- };
+ }
- float GetRestBonus() const { return m_rest_bonus; };
+ float GetRestBonus() const { return m_rest_bonus; }
void SetRestBonus(float rest_bonus_new);
- RestType GetRestType() const { return rest_type; };
- void SetRestType(RestType n_r_type) { rest_type = n_r_type; };
+ RestType GetRestType() const { return rest_type; }
+ void SetRestType(RestType n_r_type) { rest_type = n_r_type; }
- uint32 GetInnPosMapId() const { return inn_pos_mapid; };
- float GetInnPosX() const { return inn_pos_x; };
- float GetInnPosY() const { return inn_pos_y; };
- float GetInnPosZ() const { return inn_pos_z; };
+ uint32 GetInnPosMapId() const { return inn_pos_mapid; }
+ float GetInnPosX() const { return inn_pos_x; }
+ float GetInnPosY() const { return inn_pos_y; }
+ float GetInnPosZ() const { return inn_pos_z; }
- int GetTimeInnEnter() const { return time_inn_enter; };
- void UpdateInnerTime (int time) { time_inn_enter = time; };
+ int GetTimeInnEnter() const { return time_inn_enter; }
+ void UpdateInnerTime (int time) { time_inn_enter = time; }
Pet* GetPet() const;
Pet* SummonPet(uint32 entry, float x, float y, float z, float ang, PetType petType, uint32 despwtime);
@@ -1324,12 +1342,12 @@ class MANGOS_DLL_SPEC Player : public Unit
void SendQuestUpdateAddItem( Quest const* pQuest, uint32 item_idx, uint32 count );
void SendQuestUpdateAddCreatureOrGo( Quest const* pQuest, uint64 guid, uint32 creatureOrGO_idx, uint32 old_count, uint32 add_count );
- uint64 GetDivider() { return m_divider; };
- void SetDivider( uint64 guid ) { m_divider = guid; };
+ uint64 GetDivider() { return m_divider; }
+ void SetDivider( uint64 guid ) { m_divider = guid; }
- uint32 GetInGameTime() { return m_ingametime; };
+ uint32 GetInGameTime() { return m_ingametime; }
- void SetInGameTime( uint32 time ) { m_ingametime = time; };
+ void SetInGameTime( uint32 time ) { m_ingametime = time; }
void AddTimedQuest( uint32 quest_id ) { m_timedquests.insert(quest_id); }
void RemoveTimedQuest( uint32 quest_id ) { m_timedquests.erase(quest_id); }
@@ -1421,15 +1439,14 @@ class MANGOS_DLL_SPEC Player : public Unit
void AddNewMailDeliverTime(time_t deliver_time);
bool IsMailsLoaded() const { return m_mailsLoaded; }
- //void SetMail(Mail *m);
void RemoveMail(uint32 id);
void AddMail(Mail* mail) { m_mail.push_front(mail);}// for call from WorldSession::SendMailTo
- uint32 GetMailSize() { return m_mail.size();};
+ uint32 GetMailSize() { return m_mail.size();}
Mail* GetMail(uint32 id);
- PlayerMails::iterator GetMailBegin() { return m_mail.begin();};
- PlayerMails::iterator GetMailEnd() { return m_mail.end();};
+ PlayerMails::iterator GetMailBegin() { return m_mail.begin();}
+ PlayerMails::iterator GetMailEnd() { return m_mail.end();}
/*********************************************************/
/*** MAILED ITEMS SYSTEM ***/
@@ -1575,7 +1592,7 @@ class MANGOS_DLL_SPEC Player : public Unit
m_resurrectZ = Z;
m_resurrectHealth = health;
m_resurrectMana = mana;
- };
+ }
void clearResurrectRequestData() { setResurrectRequestData(0,0,0.0f,0.0f,0.0f,0,0); }
bool isRessurectRequestedBy(uint64 guid) const { return m_resurrectGUID == guid; }
bool isRessurectRequested() const { return m_resurrectGUID != 0; }
@@ -1626,6 +1643,7 @@ class MANGOS_DLL_SPEC Player : public Unit
void UpdateDuelFlag(time_t currTime);
void CheckDuelDistance(time_t currTime);
void DuelComplete(DuelCompleteType type);
+ void SendDuelCountdown(uint32 counter);
bool IsGroupVisibleFor(Player* p) const;
bool IsInSameGroupWith(Player const* p) const;
@@ -1646,19 +1664,22 @@ class MANGOS_DLL_SPEC Player : public Unit
static void RemovePetitionsAndSigns(uint64 guid, uint32 type);
// Arena Team
- void SetInArenaTeam(uint32 ArenaTeamId, uint8 slot)
+ void SetInArenaTeam(uint32 ArenaTeamId, uint8 slot, uint8 type)
{
- SetUInt32Value(PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + (slot * 6), ArenaTeamId);
+ SetUInt32Value(PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + (slot * ARENA_TEAM_END) + ARENA_TEAM_ID, ArenaTeamId);
+ SetUInt32Value(PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + (slot * ARENA_TEAM_END) + ARENA_TEAM_TYPE, type);
}
- uint32 GetArenaTeamId(uint8 slot) { return GetUInt32Value(PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + (slot * 6)); }
+ uint32 GetArenaTeamId(uint8 slot) { return GetUInt32Value(PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + (slot * ARENA_TEAM_END)); }
static uint32 GetArenaTeamIdFromDB(uint64 guid, uint8 slot);
void SetArenaTeamIdInvited(uint32 ArenaTeamId) { m_ArenaTeamIdInvited = ArenaTeamId; }
uint32 GetArenaTeamIdInvited() { return m_ArenaTeamIdInvited; }
static void LeaveAllArenaTeams(uint64 guid);
- void SetDifficulty(uint32 dungeon_difficulty) { m_dungeonDifficulty = dungeon_difficulty; }
- uint8 GetDifficulty() { return m_dungeonDifficulty; }
- bool IsHeroic() { return m_dungeonDifficulty == DIFFICULTY_HEROIC; }
+ Difficulty GetDifficulty(bool isRaid) const { return isRaid ? m_raidDifficulty : m_dungeonDifficulty; }
+ Difficulty GetDungeonDifficulty() const { return m_dungeonDifficulty; }
+ Difficulty GetRaidDifficulty() const { return m_raidDifficulty; }
+ void SetDungeonDifficulty(Difficulty dungeon_difficulty) { m_dungeonDifficulty = dungeon_difficulty; }
+ void SetRaidDifficulty(Difficulty raid_difficulty) { m_raidDifficulty = raid_difficulty; }
bool UpdateSkill(uint32 skill_id, uint32 step);
bool UpdateSkillPro(uint16 SkillId, int32 Chance, uint32 step);
@@ -1701,9 +1722,11 @@ class MANGOS_DLL_SPEC Player : public Unit
float GetRatingCoefficient(CombatRating cr) const;
float GetRatingBonusValue(CombatRating cr) const;
uint32 GetMeleeCritDamageReduction(uint32 damage) const;
+ uint32 GetMeleeDamageReduction(uint32 damage) const;
uint32 GetRangedCritDamageReduction(uint32 damage) const;
+ uint32 GetRangedDamageReduction(uint32 damage) const;
uint32 GetSpellCritDamageReduction(uint32 damage) const;
- uint32 GetDotDamageReduction(uint32 damage) const;
+ uint32 GetSpellDamageReduction(uint32 damage) const;
uint32 GetBaseSpellPowerBonus() { return m_baseSpellPower; }
float GetExpertiseDodgeOrParryReduction(WeaponAttackType attType) const;
@@ -1721,6 +1744,7 @@ class MANGOS_DLL_SPEC Player : public Unit
void UpdateArmorPenetration(int32 amount);
void UpdateExpertise(WeaponAttackType attType);
void ApplyManaRegenBonus(int32 amount, bool apply);
+ void ApplyHealthRegenBonus(int32 amount, bool apply);
void UpdateManaRegen();
const uint64& GetLootGUID() const { return m_lootGuid; }
@@ -1746,7 +1770,8 @@ class MANGOS_DLL_SPEC Player : public Unit
void SendExplorationExperience(uint32 Area, uint32 Experience);
void SendDungeonDifficulty(bool IsInGroup);
- void ResetInstances(uint8 method);
+ void SendRaidDifficulty(bool IsInGroup);
+ void ResetInstances(uint8 method, bool isRaid);
void SendResetInstanceSuccess(uint32 MapId);
void SendResetInstanceFailed(uint32 reason, uint32 MapId);
void SendResetFailedNotify(uint32 mapid);
@@ -2049,8 +2074,8 @@ class MANGOS_DLL_SPEC Player : public Unit
bool isRested() const { return GetRestTime() >= 10*IN_MILISECONDS; }
uint32 GetXPRestBonus(uint32 xp);
- uint32 GetRestTime() const { return m_restTime;};
- void SetRestTime(uint32 v) { m_restTime = v;};
+ uint32 GetRestTime() const { return m_restTime;}
+ void SetRestTime(uint32 v) { m_restTime = v;}
/*********************************************************/
/*** ENVIROMENTAL SYSTEM ***/
@@ -2163,12 +2188,12 @@ class MANGOS_DLL_SPEC Player : public Unit
uint32 m_HomebindTimer;
bool m_InstanceValid;
// permanent binds and solo binds by difficulty
- BoundInstancesMap m_boundInstances[TOTAL_DIFFICULTIES];
- InstancePlayerBind* GetBoundInstance(uint32 mapid, uint8 difficulty);
- BoundInstancesMap& GetBoundInstances(uint8 difficulty) { return m_boundInstances[difficulty]; }
- InstanceSave * GetInstanceSave(uint32 mapid);
- void UnbindInstance(uint32 mapid, uint8 difficulty, bool unload = false);
- void UnbindInstance(BoundInstancesMap::iterator &itr, uint8 difficulty, bool unload = false);
+ BoundInstancesMap m_boundInstances[MAX_DIFFICULTY];
+ InstancePlayerBind* GetBoundInstance(uint32 mapid, Difficulty difficulty);
+ BoundInstancesMap& GetBoundInstances(Difficulty difficulty) { return m_boundInstances[difficulty]; }
+ InstanceSave * GetInstanceSave(uint32 mapid, bool raid);
+ void UnbindInstance(uint32 mapid, Difficulty difficulty, bool unload = false);
+ void UnbindInstance(BoundInstancesMap::iterator &itr, Difficulty difficulty, bool unload = false);
InstancePlayerBind* BindToInstance(InstanceSave *save, bool permanent, bool load = false);
void SendRaidInfo();
void SendSavedInstances();
@@ -2239,6 +2264,11 @@ class MANGOS_DLL_SPEC Player : public Unit
//bool isActiveObject() const { return true; }
bool canSeeSpellClickOn(Creature const* creature) const;
+ uint32 GetActionButtonSpell(uint8 button) const
+ {
+ ActionButtonList::const_iterator ab = m_actionButtons.find(button);
+ return ab != m_actionButtons.end() && ab->second.uState != ACTIONBUTTON_DELETED && ab->second.GetType() == ACTION_BUTTON_SPELL ? ab->second.GetAction() : 0;
+ }
uint32 GetChampioningFaction() const { return m_ChampioningFaction; }
void SetChampioningFaction(uint32 faction) { m_ChampioningFaction = faction; }
@@ -2342,7 +2372,8 @@ Spell * m_spellModTakingSpell;
uint32 m_nextSave;
time_t m_speakTime;
uint32 m_speakCount;
- uint32 m_dungeonDifficulty;
+ Difficulty m_dungeonDifficulty;
+ Difficulty m_raidDifficulty;
uint32 m_atLoginFlags;
@@ -2382,6 +2413,7 @@ Spell * m_spellModTakingSpell;
uint16 m_baseSpellPower;
uint16 m_baseFeralAP;
uint16 m_baseManaRegen;
+ uint16 m_baseHealthRegen;
SpellModList m_spellMods[MAX_SPELLMOD];
//uint32 m_pad;
@@ -2407,8 +2439,6 @@ Spell * m_spellModTakingSpell;
uint16 tradeItems[TRADE_SLOT_COUNT];
uint32 tradeGold;
- time_t m_nextThinkTime;
-
bool m_DailyQuestChanged;
time_t m_lastDailyQuestTime;
@@ -2442,7 +2472,6 @@ Spell * m_spellModTakingSpell;
float m_rest_bonus;
RestType rest_type;
////////////////////Rest System/////////////////////
-
uint32 m_resetTalentsCost;
time_t m_resetTalentsTime;
uint32 m_usedTalentCount;
diff --git a/src/game/PoolHandler.cpp b/src/game/PoolHandler.cpp
index ff7d0146b3d..da2f432fa40 100644
--- a/src/game/PoolHandler.cpp
+++ b/src/game/PoolHandler.cpp
@@ -28,13 +28,6 @@ INSTANTIATE_SINGLETON_1(PoolHandler);
////////////////////////////////////////////////////////////
// Methods of template class PoolGroup
-template <class T>
-PoolGroup<T>::PoolGroup()
-{
- m_SpawnedPoolAmount = 0;
- m_LastDespawnedNode = 0;
-}
-
// Method to add a gameobject/creature guid to the proper list depending on pool type and chance value
template <class T>
void PoolGroup<T>::AddEntry(PoolObject& poolitem, uint32 maxentries)
@@ -73,26 +66,39 @@ bool PoolGroup<T>::IsSpawnedObject(uint32 guid)
return false;
}
-// Method that return a guid of a rolled creature or gameobject
-// Note: Copy from loot system because it's very similar and only few things change
template <class T>
-uint32 PoolGroup<T>::RollOne(void)
+void PoolGroup<T>::RollOne(int32& index, PoolObjectList** store, uint32 triggerFrom)
{
- if (!ExplicitlyChanced.empty()) // First explicitly chanced entries are checked
+ if (!ExplicitlyChanced.empty())
{
- float roll = rand_chance();
+ float roll = (float)rand_chance();
for (uint32 i=0; i<ExplicitlyChanced.size(); ++i)
{
roll -= ExplicitlyChanced[i].chance;
- if (roll < 0)
- return ExplicitlyChanced[i].guid;
+ // Triggering object is marked as spawned at this time and can be also rolled (respawn case)
+ // so this need explicit check for this case
+ if (roll < 0 && (!ExplicitlyChanced[i].spawned || ExplicitlyChanced[i].guid == triggerFrom))
+ {
+ index = i;
+ *store = &ExplicitlyChanced;
+ return;
+ }
}
}
if (!EqualChanced.empty())
- return EqualChanced[irand(0, EqualChanced.size()-1)].guid;
+ {
+ index = irand(0, EqualChanced.size()-1);
+ // Triggering object is marked as spawned at this time and can be also rolled (respawn case)
+ // so this need explicit check for this case
+ if (!EqualChanced[index].spawned || EqualChanced[index].guid == triggerFrom)
+ {
+ *store = &EqualChanced;
+ return;
+ }
+ }
- return 0; // None found
+ index = -1;
}
// Main method to despawn a creature or gameobject in a pool
@@ -107,10 +113,7 @@ void PoolGroup<T>::DespawnObject(uint32 guid)
{
if (!guid || EqualChanced[i].guid == guid)
{
- if (guid)
- m_LastDespawnedNode = EqualChanced[i].guid;
- else
- Despawn1Object(EqualChanced[i].guid);
+ Despawn1Object(EqualChanced[i].guid);
EqualChanced[i].spawned = false;
if (m_SpawnedPoolAmount > 0)
@@ -118,6 +121,21 @@ void PoolGroup<T>::DespawnObject(uint32 guid)
}
}
}
+
+ for (size_t i = 0; i < ExplicitlyChanced.size(); ++i)
+ {
+ if (ExplicitlyChanced[i].spawned)
+ {
+ if (!guid || ExplicitlyChanced[i].guid == guid)
+ {
+ Despawn1Object(ExplicitlyChanced[i].guid);
+ ExplicitlyChanced[i].spawned = false;
+
+ if (m_SpawnedPoolAmount > 0)
+ --m_SpawnedPoolAmount;
+ }
+ }
+ }
}
// Method that is actualy doing the removal job on one creature
@@ -175,53 +193,48 @@ void PoolGroup<Pool>::RemoveOneRelation(uint16 child_pool_id)
}
}
-// Method that Spawn 1+ creatures or gameobject
-// if cache is false (initialization or event start), X creatures are spawned with X <= limit (< if limit higher that the number of creatures in pool)
-// if cache is true, this means only one has to be spawned (or respawned if the rolled one is same as cached one)
template <class T>
-void PoolGroup<T>::SpawnObject(uint32 limit, bool cache)
+void PoolGroup<T>::SpawnObject(uint32 limit, uint32 triggerFrom)
{
- if (limit == 1) // This is the only case where explicit chance is used
- {
- uint32 roll = RollOne();
- if (cache && m_LastDespawnedNode != roll)
- Despawn1Object(m_LastDespawnedNode);
+ uint32 lastDespawned = 0;
+ int count = limit - m_SpawnedPoolAmount;
- m_LastDespawnedNode = 0;
- Spawn1Object(roll);
- }
- else if (limit < EqualChanced.size() && m_SpawnedPoolAmount < limit)
+ // If triggered from some object respawn this object is still marked as spawned
+ // and also counted into m_SpawnedPoolAmount so we need increase count to be
+ // spawned by 1
+ if (triggerFrom)
+ ++count;
+
+ // This will try to spawn the rest of pool, not guaranteed
+ for (int i = 0; i < count; ++i)
{
- std::vector<uint32> IndexList;
- for (size_t i=0; i<EqualChanced.size(); ++i)
- if (!EqualChanced[i].spawned)
- IndexList.push_back(i);
+ int index;
+ PoolObjectList* store;
- while (m_SpawnedPoolAmount < limit && IndexList.size() > 0)
- {
- uint32 roll = urand(1, IndexList.size()) - 1;
- uint32 index = IndexList[roll];
- if (!cache || (cache && EqualChanced[index].guid != m_LastDespawnedNode))
- {
- if (cache)
- Despawn1Object(m_LastDespawnedNode);
- EqualChanced[index].spawned = Spawn1Object(EqualChanced[index].guid);
- }
- else
- EqualChanced[index].spawned = ReSpawn1Object(EqualChanced[index].guid);
+ RollOne(index, &store, triggerFrom);
+ if (index == -1)
+ continue;
+ if ((*store)[index].guid == lastDespawned)
+ continue;
- if (EqualChanced[index].spawned)
- ++m_SpawnedPoolAmount; // limited group use the Spawned variable to store the number of actualy spawned creatures
+ if ((*store)[index].guid == triggerFrom)
+ {
+ (*store)[index].spawned = ReSpawn1Object(triggerFrom);
+ triggerFrom = 0;
+ continue;
+ }
+ else
+ (*store)[index].spawned = Spawn1Object((*store)[index].guid);
- std::vector<uint32>::iterator itr = IndexList.begin()+roll;
- IndexList.erase(itr);
+ if (triggerFrom)
+ {
+ // One spawn one despawn no count increase
+ DespawnObject(triggerFrom);
+ lastDespawned = triggerFrom;
+ triggerFrom = 0;
}
- m_LastDespawnedNode = 0;
- }
- else // Not enough objects in pool, so spawn all
- {
- for (size_t i=0; i<EqualChanced.size(); ++i)
- EqualChanced[i].spawned = Spawn1Object(EqualChanced[i].guid);
+ else
+ ++m_SpawnedPoolAmount;
}
}
@@ -241,7 +254,10 @@ bool PoolGroup<Creature>::Spawn1Object(uint32 guid)
Creature* pCreature = new Creature;
//sLog.outDebug("Spawning creature %u",guid);
if (!pCreature->LoadFromDB(guid, map))
+ {
delete pCreature;
+ return false;
+ }
else
map->Add(pCreature);
}
@@ -266,7 +282,10 @@ bool PoolGroup<GameObject>::Spawn1Object(uint32 guid)
GameObject* pGameobject = new GameObject;
//sLog.outDebug("Spawning gameobject %u", guid);
if (!pGameobject->LoadFromDB(guid, map))
+ {
delete pGameobject;
+ return false;
+ }
else
{
if (pGameobject->isSpawnedByDefault())
@@ -282,7 +301,9 @@ bool PoolGroup<GameObject>::Spawn1Object(uint32 guid)
template <>
bool PoolGroup<Pool>::Spawn1Object(uint32 child_pool_id)
{
- poolhandler.SpawnPool(child_pool_id);
+ poolhandler.SpawnPool(child_pool_id, 0, 0);
+ poolhandler.SpawnPool(child_pool_id, 0, TYPEID_GAMEOBJECT);
+ poolhandler.SpawnPool(child_pool_id, 0, TYPEID_UNIT);
return true;
}
@@ -290,8 +311,7 @@ bool PoolGroup<Pool>::Spawn1Object(uint32 child_pool_id)
template <>
bool PoolGroup<Creature>::ReSpawn1Object(uint32 guid)
{
- CreatureData const* data = objmgr.GetCreatureData(guid);
- if (data)
+ if (CreatureData const* data = objmgr.GetCreatureData(guid))
{
if (Creature* pCreature = ObjectAccessor::Instance().GetObjectInWorld(MAKE_NEW_GUID(guid, data->id, HIGHGUID_UNIT), (Creature*)NULL))
pCreature->GetMap()->Add(pCreature);
@@ -304,8 +324,7 @@ bool PoolGroup<Creature>::ReSpawn1Object(uint32 guid)
template <>
bool PoolGroup<GameObject>::ReSpawn1Object(uint32 guid)
{
- GameObjectData const* data = objmgr.GetGOData(guid);
- if (data)
+ if (GameObjectData const* data = objmgr.GetGOData(guid))
{
if (GameObject* pGameobject = ObjectAccessor::Instance().GetObjectInWorld(MAKE_NEW_GUID(guid, data->id, HIGHGUID_GAMEOBJECT), (GameObject*)NULL))
pGameobject->GetMap()->Add(pGameobject);
@@ -613,7 +632,9 @@ void PoolHandler::Initialize()
sLog.outErrorDb("Pool Id (%u) has all creatures or gameobjects with explicit chance sum <>100 and no equal chance defined. The pool system cannot pick one to spawn.", pool_entry);
continue;
}
- SpawnPool(pool_entry);
+ SpawnPool(pool_entry, 0, 0);
+ SpawnPool(pool_entry, 0, TYPEID_GAMEOBJECT);
+ SpawnPool(pool_entry, 0, TYPEID_UNIT);
count++;
} while (result->NextRow());
delete result;
@@ -625,25 +646,35 @@ void PoolHandler::Initialize()
// Call to spawn a pool, if cache if true the method will spawn only if cached entry is different
// If it's same, the gameobject/creature is respawned only (added back to map)
-void PoolHandler::SpawnPool(uint16 pool_id, bool cache)
+void PoolHandler::SpawnPool(uint16 pool_id, uint32 guid, uint32 type)
{
- if (!mPoolPoolGroups[pool_id].isEmpty())
- mPoolPoolGroups[pool_id].SpawnObject(mPoolTemplate[pool_id].MaxLimit, cache);
- if (!mPoolGameobjectGroups[pool_id].isEmpty())
- mPoolGameobjectGroups[pool_id].SpawnObject(mPoolTemplate[pool_id].MaxLimit, cache);
- if (!mPoolCreatureGroups[pool_id].isEmpty())
- mPoolCreatureGroups[pool_id].SpawnObject(mPoolTemplate[pool_id].MaxLimit, cache);
+ switch (type)
+ {
+ case TYPEID_UNIT:
+ if (!mPoolCreatureGroups[pool_id].isEmpty())
+ mPoolCreatureGroups[pool_id].SpawnObject(mPoolTemplate[pool_id].MaxLimit, guid);
+ break;
+ case TYPEID_GAMEOBJECT:
+ if (!mPoolGameobjectGroups[pool_id].isEmpty())
+ mPoolGameobjectGroups[pool_id].SpawnObject(mPoolTemplate[pool_id].MaxLimit, guid);
+ break;
+ default:
+ if (!mPoolPoolGroups[pool_id].isEmpty())
+ mPoolPoolGroups[pool_id].SpawnObject(mPoolTemplate[pool_id].MaxLimit, guid);
+ }
}
// Call to despawn a pool, all gameobjects/creatures in this pool are removed
void PoolHandler::DespawnPool(uint16 pool_id)
{
- if (!mPoolPoolGroups[pool_id].isEmpty())
- mPoolPoolGroups[pool_id].DespawnObject();
- if (!mPoolGameobjectGroups[pool_id].isEmpty())
- mPoolGameobjectGroups[pool_id].DespawnObject();
if (!mPoolCreatureGroups[pool_id].isEmpty())
mPoolCreatureGroups[pool_id].DespawnObject();
+
+ if (!mPoolGameobjectGroups[pool_id].isEmpty())
+ mPoolGameobjectGroups[pool_id].DespawnObject();
+
+ if (!mPoolPoolGroups[pool_id].isEmpty())
+ mPoolPoolGroups[pool_id].DespawnObject();
}
// Call to update the pool when a gameobject/creature part of pool [pool_id] is ready to respawn
@@ -651,19 +682,10 @@ void PoolHandler::DespawnPool(uint16 pool_id)
// Then the spawn pool call will use this cache to decide
void PoolHandler::UpdatePool(uint16 pool_id, uint32 guid, uint32 type)
{
- uint16 motherpoolid = IsPartOfAPool(pool_id, 0);
-
- if (motherpoolid)
- mPoolPoolGroups[motherpoolid].DespawnObject(pool_id);
- else if (type == TYPEID_GAMEOBJECT && !mPoolGameobjectGroups[pool_id].isEmpty())
- mPoolGameobjectGroups[pool_id].DespawnObject(guid);
- else if (type != TYPEID_GAMEOBJECT && !mPoolCreatureGroups[pool_id].isEmpty())
- mPoolCreatureGroups[pool_id].DespawnObject(guid);
-
- if (motherpoolid)
- SpawnPool(motherpoolid, true);
+ if (uint16 motherpoolid = IsPartOfAPool(pool_id, 0))
+ SpawnPool(motherpoolid, 0, 0);
else
- SpawnPool(pool_id, true);
+ SpawnPool(pool_id, guid, type);
}
// Method that tell if the gameobject/creature is part of a pool and return the pool id if yes
diff --git a/src/game/PoolHandler.h b/src/game/PoolHandler.h
index 652d8e2cf3b..a3f6755bfde 100644
--- a/src/game/PoolHandler.h
+++ b/src/game/PoolHandler.h
@@ -40,25 +40,24 @@ struct PoolObject
template <class T>
class PoolGroup
{
+ typedef std::vector<PoolObject> PoolObjectList;
public:
- PoolGroup();
+ PoolGroup() : m_SpawnedPoolAmount(0) {}
~PoolGroup() {};
bool isEmpty() { return ExplicitlyChanced.empty() && EqualChanced.empty(); }
void AddEntry(PoolObject& poolitem, uint32 maxentries);
bool CheckPool(void);
- uint32 RollOne(void);
+ void RollOne(int32& index, PoolObjectList** store, uint32 triggerFrom);
bool IsSpawnedObject(uint32 guid);
void DespawnObject(uint32 guid=0);
void Despawn1Object(uint32 guid);
- void SpawnObject(uint32 limit, bool cache=false);
+ void SpawnObject(uint32 limit, uint32 triggerFrom);
bool Spawn1Object(uint32 guid);
bool ReSpawn1Object(uint32 guid);
void RemoveOneRelation(uint16 child_pool_id);
private:
- typedef std::vector<PoolObject> PoolObjectList;
PoolObjectList ExplicitlyChanced;
PoolObjectList EqualChanced;
- uint32 m_LastDespawnedNode; // Store the guid of the removed creature/gameobject during a pool update
uint32 m_SpawnedPoolAmount; // Used to know the number of spawned objects
};
@@ -75,7 +74,7 @@ class PoolHandler
uint16 IsPartOfAPool(uint32 guid, uint32 type);
bool IsSpawnedObject(uint16 pool_id, uint32 guid, uint32 type);
bool CheckPool(uint16 pool_id);
- void SpawnPool(uint16 pool_id, bool cache=false);
+ void SpawnPool(uint16 pool_id, uint32 guid, uint32 type);
void DespawnPool(uint16 pool_id);
void UpdatePool(uint16 pool_id, uint32 guid, uint32 type);
void Initialize();
diff --git a/src/game/QueryHandler.cpp b/src/game/QueryHandler.cpp
index f3ceb16dc6b..e428b66cee4 100644
--- a/src/game/QueryHandler.cpp
+++ b/src/game/QueryHandler.cpp
@@ -38,7 +38,6 @@ void WorldSession::SendNameQueryOpcode(Player *p)
{
if(!p)
return;
-
// guess size
WorldPacket data( SMSG_NAME_QUERY_RESPONSE, (8+1+1+1+1+1+10) );
data.append(p->GetPackGUID()); // player guid
@@ -102,7 +101,6 @@ void WorldSession::SendNameQueryOpcodeFromDBCallBack(QueryResult *result, uint32
pGender = fields[3].GetUInt8();
pClass = fields[4].GetUInt8();
}
-
// guess size
WorldPacket data( SMSG_NAME_QUERY_RESPONSE, (8+1+1+1+1+1+1+10) );
data.appendPackGUID(MAKE_NEW_GUID(guid, 0, HIGHGUID_PLAYER));
@@ -154,7 +152,8 @@ void WorldSession::HandleCreatureQueryOpcode( WorldPacket & recv_data )
{
uint32 entry;
recv_data >> entry;
- recv_data.read_skip<uint64>(); // guid
+ uint64 guid;
+ recv_data >> guid;
CreatureInfo const *ci = objmgr.GetCreatureTemplate(entry);
if (ci)
@@ -205,9 +204,6 @@ void WorldSession::HandleCreatureQueryOpcode( WorldPacket & recv_data )
}
else
{
- uint64 guid;
- recv_data >> guid;
-
sLog.outDebug("WORLD: CMSG_CREATURE_QUERY - NO CREATURE INFO! (GUID: %u, ENTRY: %u)",
GUID_LOPART(guid), entry);
WorldPacket data( SMSG_CREATURE_QUERY_RESPONSE, 4 );
@@ -222,7 +218,8 @@ void WorldSession::HandleGameObjectQueryOpcode( WorldPacket & recv_data )
{
uint32 entryID;
recv_data >> entryID;
- recv_data.read_skip<uint64>(); // guid
+ uint64 guid;
+ recv_data >> guid;
const GameObjectInfo *info = objmgr.GetGameObjectInfo(entryID);
if(info)
@@ -260,16 +257,12 @@ void WorldSession::HandleGameObjectQueryOpcode( WorldPacket & recv_data )
data.append(info->raw.data, 24);
data << float(info->size); // go size
for (uint32 i = 0; i < 6; ++i)
- data << uint32(info->questItems[i]); // itemId[6], quest drop
+ data << uint32(info->questItems[i]); // itemId[6], quest drop
SendPacket( &data );
sLog.outDebug( "WORLD: Sent SMSG_GAMEOBJECT_QUERY_RESPONSE" );
}
else
{
-
- uint64 guid;
- recv_data >> guid;
-
sLog.outDebug( "WORLD: CMSG_GAMEOBJECT_QUERY - Missing gameobject info for (GUID: %u, ENTRY: %u)",
GUID_LOPART(guid), entryID );
WorldPacket data ( SMSG_GAMEOBJECT_QUERY_RESPONSE, 4 );
@@ -418,10 +411,12 @@ void WorldSession::HandleNpcTextQueryOpcode( WorldPacket & recv_data )
void WorldSession::HandlePageTextQueryOpcode( WorldPacket & recv_data )
{
- uint32 pageID;
+ sLog.outDetail("WORLD: Received CMSG_PAGE_TEXT_QUERY");
+ recv_data.hexlike();
+ uint32 pageID;
recv_data >> pageID;
- sLog.outDetail("WORLD: Received CMSG_PAGE_TEXT_QUERY for pageID '%u'", pageID);
+ recv_data.read_skip<uint64>(); // guid
while (pageID)
{
@@ -461,3 +456,17 @@ void WorldSession::HandlePageTextQueryOpcode( WorldPacket & recv_data )
}
}
+void WorldSession::HandleCorpseMapPositionQuery( WorldPacket & recv_data )
+{
+ sLog.outDebug( "WORLD: Recv CMSG_CORPSE_MAP_POSITION_QUERY" );
+
+ uint32 unk;
+ recv_data >> unk;
+
+ WorldPacket data(CMSG_CORPSE_MAP_POSITION_QUERY_RESPONSE, 4+4+4+4);
+ data << float(0);
+ data << float(0);
+ data << float(0);
+ data << float(0);
+ SendPacket(&data);
+}
diff --git a/src/game/QuestDef.cpp b/src/game/QuestDef.cpp
index 1c429178fda..dcbedf62eec 100644
--- a/src/game/QuestDef.cpp
+++ b/src/game/QuestDef.cpp
@@ -63,74 +63,74 @@ Quest::Quest(Field * questRecord)
for (int i = 0; i < QUEST_OBJECTIVES_COUNT; ++i)
ObjectiveText[i] = questRecord[35+i].GetCppString();
- for (int i = 0; i < QUEST_OBJECTIVES_COUNT; ++i)
+ for (int i = 0; i < QUEST_ITEM_OBJECTIVES_COUNT; ++i)
ReqItemId[i] = questRecord[39+i].GetUInt32();
- for (int i = 0; i < QUEST_OBJECTIVES_COUNT; ++i)
- ReqItemCount[i] = questRecord[43+i].GetUInt32();
+ for (int i = 0; i < QUEST_ITEM_OBJECTIVES_COUNT; ++i)
+ ReqItemCount[i] = questRecord[45+i].GetUInt32();
for (int i = 0; i < QUEST_SOURCE_ITEM_IDS_COUNT; ++i)
- ReqSourceId[i] = questRecord[47+i].GetUInt32();
+ ReqSourceId[i] = questRecord[51+i].GetUInt32();
for (int i = 0; i < QUEST_SOURCE_ITEM_IDS_COUNT; ++i)
- ReqSourceCount[i] = questRecord[51+i].GetUInt32();
+ ReqSourceCount[i] = questRecord[55+i].GetUInt32();
for (int i = 0; i < QUEST_OBJECTIVES_COUNT; ++i)
- ReqCreatureOrGOId[i] = questRecord[55+i].GetInt32();
+ ReqCreatureOrGOId[i] = questRecord[59+i].GetInt32();
for (int i = 0; i < QUEST_OBJECTIVES_COUNT; ++i)
- ReqCreatureOrGOCount[i] = questRecord[59+i].GetUInt32();
+ ReqCreatureOrGOCount[i] = questRecord[63+i].GetUInt32();
for (int i = 0; i < QUEST_OBJECTIVES_COUNT; ++i)
- ReqSpell[i] = questRecord[63+i].GetUInt32();
+ ReqSpell[i] = questRecord[67+i].GetUInt32();
for (int i = 0; i < QUEST_REWARD_CHOICES_COUNT; ++i)
- RewChoiceItemId[i] = questRecord[67+i].GetUInt32();
+ RewChoiceItemId[i] = questRecord[71+i].GetUInt32();
for (int i = 0; i < QUEST_REWARD_CHOICES_COUNT; ++i)
- RewChoiceItemCount[i] = questRecord[73+i].GetUInt32();
+ RewChoiceItemCount[i] = questRecord[77+i].GetUInt32();
for (int i = 0; i < QUEST_REWARDS_COUNT; ++i)
- RewItemId[i] = questRecord[79+i].GetUInt32();
+ RewItemId[i] = questRecord[83+i].GetUInt32();
for (int i = 0; i < QUEST_REWARDS_COUNT; ++i)
- RewItemCount[i] = questRecord[83+i].GetUInt32();
+ RewItemCount[i] = questRecord[87+i].GetUInt32();
for (int i = 0; i < QUEST_REPUTATIONS_COUNT; ++i)
- RewRepFaction[i] = questRecord[87+i].GetUInt32();
+ RewRepFaction[i] = questRecord[91+i].GetUInt32();
for (int i = 0; i < QUEST_REPUTATIONS_COUNT; ++i)
- RewRepValue[i] = questRecord[92+i].GetInt32();
-
- RewHonorableKills = questRecord[97].GetUInt32();
- RewOrReqMoney = questRecord[98].GetInt32();
- RewMoneyMaxLevel = questRecord[99].GetUInt32();
- RewSpell = questRecord[100].GetUInt32();
- RewSpellCast = questRecord[101].GetUInt32();
- RewMailTemplateId = questRecord[102].GetUInt32();
- RewMailDelaySecs = questRecord[103].GetUInt32();
- PointMapId = questRecord[104].GetUInt32();
- PointX = questRecord[105].GetFloat();
- PointY = questRecord[106].GetFloat();
- PointOpt = questRecord[107].GetUInt32();
+ RewRepValue[i] = questRecord[96+i].GetInt32();
+
+ RewHonorableKills = questRecord[101].GetUInt32();
+ RewOrReqMoney = questRecord[102].GetInt32();
+ RewMoneyMaxLevel = questRecord[103].GetUInt32();
+ RewSpell = questRecord[104].GetUInt32();
+ RewSpellCast = questRecord[105].GetUInt32();
+ RewMailTemplateId = questRecord[106].GetUInt32();
+ RewMailDelaySecs = questRecord[107].GetUInt32();
+ PointMapId = questRecord[108].GetUInt32();
+ PointX = questRecord[109].GetFloat();
+ PointY = questRecord[110].GetFloat();
+ PointOpt = questRecord[111].GetUInt32();
for (int i = 0; i < QUEST_EMOTE_COUNT; ++i)
- DetailsEmote[i] = questRecord[108+i].GetUInt32();
+ DetailsEmote[i] = questRecord[112+i].GetUInt32();
for (int i = 0; i < QUEST_EMOTE_COUNT; ++i)
- DetailsEmoteDelay[i] = questRecord[112+i].GetUInt32();
+ DetailsEmoteDelay[i] = questRecord[116+i].GetUInt32();
- IncompleteEmote = questRecord[116].GetUInt32();
- CompleteEmote = questRecord[117].GetUInt32();
+ IncompleteEmote = questRecord[120].GetUInt32();
+ CompleteEmote = questRecord[121].GetUInt32();
for (int i = 0; i < QUEST_EMOTE_COUNT; ++i)
- OfferRewardEmote[i] = questRecord[118+i].GetInt32();
+ OfferRewardEmote[i] = questRecord[122+i].GetInt32();
for (int i = 0; i < QUEST_EMOTE_COUNT; ++i)
- OfferRewardEmoteDelay[i] = questRecord[122+i].GetInt32();
+ OfferRewardEmoteDelay[i] = questRecord[126+i].GetInt32();
- QuestStartScript = questRecord[126].GetUInt32();
- QuestCompleteScript = questRecord[127].GetUInt32();
+ QuestStartScript = questRecord[130].GetUInt32();
+ QuestCompleteScript = questRecord[131].GetUInt32();
QuestFlags |= SpecialFlags << 16;
@@ -139,10 +139,14 @@ Quest::Quest(Field * questRecord)
m_rewitemscount = 0;
m_rewchoiceitemscount = 0;
- for (int i=0; i < QUEST_OBJECTIVES_COUNT; ++i)
+ for (int i=0; i < QUEST_ITEM_OBJECTIVES_COUNT; ++i)
{
if ( ReqItemId[i] )
++m_reqitemscount;
+ }
+
+ for (int i=0; i < QUEST_OBJECTIVES_COUNT; ++i)
+ {
if ( ReqCreatureOrGOId[i] )
++m_reqCreatureOrGOcount;
}
@@ -208,4 +212,3 @@ int32 Quest::GetRewOrReqMoney() const
return int32(RewOrReqMoney * sWorld.getRate(RATE_DROP_MONEY));
}
-
diff --git a/src/game/QuestDef.h b/src/game/QuestDef.h
index 264acff95b8..f9eab231b68 100644
--- a/src/game/QuestDef.h
+++ b/src/game/QuestDef.h
@@ -34,6 +34,7 @@ class ObjectMgr;
#define MAX_QUEST_LOG_SIZE 25
#define QUEST_OBJECTIVES_COUNT 4
+#define QUEST_ITEM_OBJECTIVES_COUNT 6
#define QUEST_SOURCE_ITEM_IDS_COUNT 4
#define QUEST_REWARD_CHOICES_COUNT 6
#define QUEST_REWARDS_COUNT 4
@@ -231,8 +232,8 @@ class Quest
// multiple values
std::string ObjectiveText[QUEST_OBJECTIVES_COUNT];
- uint32 ReqItemId[QUEST_OBJECTIVES_COUNT];
- uint32 ReqItemCount[QUEST_OBJECTIVES_COUNT];
+ uint32 ReqItemId[QUEST_ITEM_OBJECTIVES_COUNT];
+ uint32 ReqItemCount[QUEST_ITEM_OBJECTIVES_COUNT];
uint32 ReqSourceId[QUEST_SOURCE_ITEM_IDS_COUNT];
uint32 ReqSourceCount[QUEST_SOURCE_ITEM_IDS_COUNT];
int32 ReqCreatureOrGOId[QUEST_OBJECTIVES_COUNT]; // >0 Creature <0 Gameobject
@@ -332,7 +333,7 @@ struct QuestStatusData
: m_status(QUEST_STATUS_NONE),m_rewarded(false),
m_explored(false), m_timer(0), uState(QUEST_NEW)
{
- memset(m_itemcount, 0, QUEST_OBJECTIVES_COUNT * sizeof(uint32));
+ memset(m_itemcount, 0, QUEST_ITEM_OBJECTIVES_COUNT * sizeof(uint32));
memset(m_creatureOrGOcount, 0, QUEST_OBJECTIVES_COUNT * sizeof(uint32));
}
@@ -342,8 +343,7 @@ struct QuestStatusData
uint32 m_timer;
QuestUpdateState uState;
- uint32 m_itemcount[ QUEST_OBJECTIVES_COUNT ];
+ uint32 m_itemcount[ QUEST_ITEM_OBJECTIVES_COUNT ];
uint32 m_creatureOrGOcount[ QUEST_OBJECTIVES_COUNT ];
};
#endif
-
diff --git a/src/game/QuestHandler.cpp b/src/game/QuestHandler.cpp
index b60e901417d..cc8d3e4a87c 100644
--- a/src/game/QuestHandler.cpp
+++ b/src/game/QuestHandler.cpp
@@ -173,7 +173,7 @@ void WorldSession::HandleQuestgiverAcceptQuestOpcode( WorldPacket & recv_data )
// destroy not required for quest finish quest starting item
bool destroyItem = true;
- for (int i = 0; i < QUEST_OBJECTIVES_COUNT; ++i)
+ for (int i = 0; i < QUEST_ITEM_OBJECTIVES_COUNT; ++i)
{
if ((qInfo->ReqItemId[i] == ((Item*)pObject)->GetEntry()) && (((Item*)pObject)->GetProto()->MaxCount > 0))
{
@@ -638,4 +638,3 @@ void WorldSession::HandleQuestgiverStatusMultipleQuery(WorldPacket& /*recvPacket
data.put<uint32>(0, count); // write real count
SendPacket(&data);
}
-
diff --git a/src/game/SharedDefines.h b/src/game/SharedDefines.h
index eaeb583d0e9..c6cf5debe77 100644
--- a/src/game/SharedDefines.h
+++ b/src/game/SharedDefines.h
@@ -47,7 +47,7 @@ enum Races
RACE_TROLL = 8,
//RACE_GOBLIN = 9,
RACE_BLOODELF = 10,
- RACE_DRAENEI = 11,
+ RACE_DRAENEI = 11
//RACE_FEL_ORC = 12,
//RACE_NAGA = 13,
//RACE_BROKEN = 14,
@@ -82,7 +82,7 @@ enum Classes
CLASS_MAGE = 8,
CLASS_WARLOCK = 9,
//CLASS_UNK = 10,
- CLASS_DRUID = 11,
+ CLASS_DRUID = 11
};
// max+1 for player class
@@ -98,7 +98,7 @@ enum Classes
#define CLASSMASK_WAND_USERS ((1<<(CLASS_PRIEST-1))|(1<<(CLASS_MAGE-1))|(1<<(CLASS_WARLOCK-1)))
-#define PLAYER_MAX_BATTLEGROUND_QUEUES 3
+#define PLAYER_MAX_BATTLEGROUND_QUEUES 2
enum ReputationRank
{
@@ -661,7 +661,7 @@ enum SpellEffects
SPELL_EFFECT_SELF_RESURRECT = 94,
SPELL_EFFECT_SKINNING = 95,
SPELL_EFFECT_CHARGE = 96,
- SPELL_EFFECT_97 = 97,
+ SPELL_EFFECT_CAST_BUTTON = 97,
SPELL_EFFECT_KNOCK_BACK = 98,
SPELL_EFFECT_DISENCHANT = 99,
SPELL_EFFECT_INEBRIATE = 100,
@@ -732,192 +732,193 @@ enum SpellEffects
enum SpellCastResult
{
- SPELL_FAILED_AFFECTING_COMBAT = 0x00,
- SPELL_FAILED_ALREADY_AT_FULL_HEALTH = 0x01,
- SPELL_FAILED_ALREADY_AT_FULL_MANA = 0x02,
- SPELL_FAILED_ALREADY_AT_FULL_POWER = 0x03,
- SPELL_FAILED_ALREADY_BEING_TAMED = 0x04,
- SPELL_FAILED_ALREADY_HAVE_CHARM = 0x05,
- SPELL_FAILED_ALREADY_HAVE_SUMMON = 0x06,
- SPELL_FAILED_ALREADY_OPEN = 0x07,
- SPELL_FAILED_AURA_BOUNCED = 0x08,
- SPELL_FAILED_AUTOTRACK_INTERRUPTED = 0x09,
- SPELL_FAILED_BAD_IMPLICIT_TARGETS = 0x0A,
- SPELL_FAILED_BAD_TARGETS = 0x0B,
- SPELL_FAILED_CANT_BE_CHARMED = 0x0C,
- SPELL_FAILED_CANT_BE_DISENCHANTED = 0x0D,
- SPELL_FAILED_CANT_BE_DISENCHANTED_SKILL = 0x0E,
- SPELL_FAILED_CANT_BE_MILLED = 0x0F,
- SPELL_FAILED_CANT_BE_PROSPECTED = 0x10,
- SPELL_FAILED_CANT_CAST_ON_TAPPED = 0x11,
- SPELL_FAILED_CANT_DUEL_WHILE_INVISIBLE = 0x12,
- SPELL_FAILED_CANT_DUEL_WHILE_STEALTHED = 0x13,
- SPELL_FAILED_CANT_STEALTH = 0x14,
- SPELL_FAILED_CASTER_AURASTATE = 0x15,
- SPELL_FAILED_CASTER_DEAD = 0x16,
- SPELL_FAILED_CHARMED = 0x17,
- SPELL_FAILED_CHEST_IN_USE = 0x18,
- SPELL_FAILED_CONFUSED = 0x19,
- SPELL_FAILED_DONT_REPORT = 0x1A,
- SPELL_FAILED_EQUIPPED_ITEM = 0x1B,
- SPELL_FAILED_EQUIPPED_ITEM_CLASS = 0x1C,
- SPELL_FAILED_EQUIPPED_ITEM_CLASS_MAINHAND = 0x1D,
- SPELL_FAILED_EQUIPPED_ITEM_CLASS_OFFHAND = 0x1E,
- SPELL_FAILED_ERROR = 0x1F,
- SPELL_FAILED_FIZZLE = 0x20,
- SPELL_FAILED_FLEEING = 0x21,
- SPELL_FAILED_FOOD_LOWLEVEL = 0x22,
- SPELL_FAILED_HIGHLEVEL = 0x23,
- SPELL_FAILED_HUNGER_SATIATED = 0x24,
- SPELL_FAILED_IMMUNE = 0x25,
- SPELL_FAILED_INCORRECT_AREA = 0x26,
- SPELL_FAILED_INTERRUPTED = 0x27,
- SPELL_FAILED_INTERRUPTED_COMBAT = 0x28,
- SPELL_FAILED_ITEM_ALREADY_ENCHANTED = 0x29,
- SPELL_FAILED_ITEM_GONE = 0x2A,
- SPELL_FAILED_ITEM_NOT_FOUND = 0x2B,
- SPELL_FAILED_ITEM_NOT_READY = 0x2C,
- SPELL_FAILED_LEVEL_REQUIREMENT = 0x2D,
- SPELL_FAILED_LINE_OF_SIGHT = 0x2E,
- SPELL_FAILED_LOWLEVEL = 0x2F,
- SPELL_FAILED_LOW_CASTLEVEL = 0x30,
- SPELL_FAILED_MAINHAND_EMPTY = 0x31,
- SPELL_FAILED_MOVING = 0x32,
- SPELL_FAILED_NEED_AMMO = 0x33,
- SPELL_FAILED_NEED_AMMO_POUCH = 0x34,
- SPELL_FAILED_NEED_EXOTIC_AMMO = 0x35,
- SPELL_FAILED_NEED_MORE_ITEMS = 0x36,
- SPELL_FAILED_NOPATH = 0x37,
- SPELL_FAILED_NOT_BEHIND = 0x38,
- SPELL_FAILED_NOT_FISHABLE = 0x39,
- SPELL_FAILED_NOT_FLYING = 0x3A,
- SPELL_FAILED_NOT_HERE = 0x3B,
- SPELL_FAILED_NOT_INFRONT = 0x3C,
- SPELL_FAILED_NOT_IN_CONTROL = 0x3D,
- SPELL_FAILED_NOT_KNOWN = 0x3E,
- SPELL_FAILED_NOT_MOUNTED = 0x3F,
- SPELL_FAILED_NOT_ON_TAXI = 0x40,
- SPELL_FAILED_NOT_ON_TRANSPORT = 0x41,
- SPELL_FAILED_NOT_READY = 0x42,
- SPELL_FAILED_NOT_SHAPESHIFT = 0x43,
- SPELL_FAILED_NOT_STANDING = 0x44,
- SPELL_FAILED_NOT_TRADEABLE = 0x45,
- SPELL_FAILED_NOT_TRADING = 0x46,
- SPELL_FAILED_NOT_UNSHEATHED = 0x47,
- SPELL_FAILED_NOT_WHILE_GHOST = 0x48,
- SPELL_FAILED_NOT_WHILE_LOOTING = 0x49,
- SPELL_FAILED_NO_AMMO = 0x4A,
- SPELL_FAILED_NO_CHARGES_REMAIN = 0x4B,
- SPELL_FAILED_NO_CHAMPION = 0x4C,
- SPELL_FAILED_NO_COMBO_POINTS = 0x4D,
- SPELL_FAILED_NO_DUELING = 0x4E,
- SPELL_FAILED_NO_ENDURANCE = 0x4F,
- SPELL_FAILED_NO_FISH = 0x50,
- SPELL_FAILED_NO_ITEMS_WHILE_SHAPESHIFTED = 0x51,
- SPELL_FAILED_NO_MOUNTS_ALLOWED = 0x52,
- SPELL_FAILED_NO_PET = 0x53,
- SPELL_FAILED_NO_POWER = 0x54,
- SPELL_FAILED_NOTHING_TO_DISPEL = 0x55,
- SPELL_FAILED_NOTHING_TO_STEAL = 0x56,
- SPELL_FAILED_ONLY_ABOVEWATER = 0x57,
- SPELL_FAILED_ONLY_DAYTIME = 0x58,
- SPELL_FAILED_ONLY_INDOORS = 0x59,
- SPELL_FAILED_ONLY_MOUNTED = 0x5A,
- SPELL_FAILED_ONLY_NIGHTTIME = 0x5B,
- SPELL_FAILED_ONLY_OUTDOORS = 0x5C,
- SPELL_FAILED_ONLY_SHAPESHIFT = 0x5D,
- SPELL_FAILED_ONLY_STEALTHED = 0x5E,
- SPELL_FAILED_ONLY_UNDERWATER = 0x5F,
- SPELL_FAILED_OUT_OF_RANGE = 0x60,
- SPELL_FAILED_PACIFIED = 0x61,
- SPELL_FAILED_POSSESSED = 0x62,
- SPELL_FAILED_REAGENTS = 0x63,
- SPELL_FAILED_REQUIRES_AREA = 0x64,
- SPELL_FAILED_REQUIRES_SPELL_FOCUS = 0x65,
- SPELL_FAILED_ROOTED = 0x66,
- SPELL_FAILED_SILENCED = 0x67,
- SPELL_FAILED_SPELL_IN_PROGRESS = 0x68,
- SPELL_FAILED_SPELL_LEARNED = 0x69,
- SPELL_FAILED_SPELL_UNAVAILABLE = 0x6A,
- SPELL_FAILED_STUNNED = 0x6B,
- SPELL_FAILED_TARGETS_DEAD = 0x6C,
- SPELL_FAILED_TARGET_AFFECTING_COMBAT = 0x6D,
- SPELL_FAILED_TARGET_AURASTATE = 0x6E,
- SPELL_FAILED_TARGET_DUELING = 0x6F,
- SPELL_FAILED_TARGET_ENEMY = 0x70,
- SPELL_FAILED_TARGET_ENRAGED = 0x71,
- SPELL_FAILED_TARGET_FRIENDLY = 0x72,
- SPELL_FAILED_TARGET_IN_COMBAT = 0x73,
- SPELL_FAILED_TARGET_IS_PLAYER = 0x74,
- SPELL_FAILED_TARGET_IS_PLAYER_CONTROLLED = 0x75,
- SPELL_FAILED_TARGET_NOT_DEAD = 0x76,
- SPELL_FAILED_TARGET_NOT_IN_PARTY = 0x77,
- SPELL_FAILED_TARGET_NOT_LOOTED = 0x78,
- SPELL_FAILED_TARGET_NOT_PLAYER = 0x79,
- SPELL_FAILED_TARGET_NO_POCKETS = 0x7A,
- SPELL_FAILED_TARGET_NO_WEAPONS = 0x7B,
- SPELL_FAILED_TARGET_NO_RANGED_WEAPONS = 0x7C,
- SPELL_FAILED_TARGET_UNSKINNABLE = 0x7D,
- SPELL_FAILED_THIRST_SATIATED = 0x7E,
- SPELL_FAILED_TOO_CLOSE = 0x7F,
- SPELL_FAILED_TOO_MANY_OF_ITEM = 0x80,
- SPELL_FAILED_TOTEM_CATEGORY = 0x81,
- SPELL_FAILED_TOTEMS = 0x82,
- SPELL_FAILED_TRY_AGAIN = 0x83,
- SPELL_FAILED_UNIT_NOT_BEHIND = 0x84,
- SPELL_FAILED_UNIT_NOT_INFRONT = 0x85,
- SPELL_FAILED_WRONG_PET_FOOD = 0x86,
- SPELL_FAILED_NOT_WHILE_FATIGUED = 0x87,
- SPELL_FAILED_TARGET_NOT_IN_INSTANCE = 0x88,
- SPELL_FAILED_NOT_WHILE_TRADING = 0x89,
- SPELL_FAILED_TARGET_NOT_IN_RAID = 0x8A,
- SPELL_FAILED_TARGET_FREEFORALL = 0x8B,
- SPELL_FAILED_NO_EDIBLE_CORPSES = 0x8C,
- SPELL_FAILED_ONLY_BATTLEGROUNDS = 0x8D,
- SPELL_FAILED_TARGET_NOT_GHOST = 0x8E,
- SPELL_FAILED_TRANSFORM_UNUSABLE = 0x8F,
- SPELL_FAILED_WRONG_WEATHER = 0x90,
- SPELL_FAILED_DAMAGE_IMMUNE = 0x91,
- SPELL_FAILED_PREVENTED_BY_MECHANIC = 0x92,
- SPELL_FAILED_PLAY_TIME = 0x93,
- SPELL_FAILED_REPUTATION = 0x94,
- SPELL_FAILED_MIN_SKILL = 0x95,
- SPELL_FAILED_NOT_IN_ARENA = 0x96,
- SPELL_FAILED_NOT_ON_SHAPESHIFT = 0x97,
- SPELL_FAILED_NOT_ON_STEALTHED = 0x98,
- SPELL_FAILED_NOT_ON_DAMAGE_IMMUNE = 0x99,
- SPELL_FAILED_NOT_ON_MOUNTED = 0x9A,
- SPELL_FAILED_TOO_SHALLOW = 0x9B,
- SPELL_FAILED_TARGET_NOT_IN_SANCTUARY = 0x9C,
- SPELL_FAILED_TARGET_IS_TRIVIAL = 0x9D,
- SPELL_FAILED_BM_OR_INVISGOD = 0x9E,
- SPELL_FAILED_EXPERT_RIDING_REQUIREMENT = 0x9F,
- SPELL_FAILED_ARTISAN_RIDING_REQUIREMENT = 0xA0,
- SPELL_FAILED_NOT_IDLE = 0xA1,
- SPELL_FAILED_NOT_INACTIVE = 0xA2,
- SPELL_FAILED_PARTIAL_PLAYTIME = 0xA3,
- SPELL_FAILED_NO_PLAYTIME = 0xA4,
- SPELL_FAILED_NOT_IN_BATTLEGROUND = 0xA5,
- SPELL_FAILED_NOT_IN_RAID_INSTANCE = 0xA6,
- SPELL_FAILED_ONLY_IN_ARENA = 0xA7,
- SPELL_FAILED_TARGET_LOCKED_TO_RAID_INSTANCE = 0xA8,
- SPELL_FAILED_ON_USE_ENCHANT = 0xA9,
- SPELL_FAILED_NOT_ON_GROUND = 0xAA,
- SPELL_FAILED_CUSTOM_ERROR = 0xAB,
- SPELL_FAILED_CANT_DO_THAT_RIGHT_NOW = 0xAC,
- SPELL_FAILED_TOO_MANY_SOCKETS = 0xAD,
- SPELL_FAILED_INVALID_GLYPH = 0xAE,
- SPELL_FAILED_UNIQUE_GLYPH = 0xAF,
- SPELL_FAILED_GLYPH_SOCKET_LOCKED = 0xB0,
- SPELL_FAILED_NO_VALID_TARGETS = 0xB1,
- SPELL_FAILED_ITEM_AT_MAX_CHARGES = 0xB2,
- SPELL_FAILED_NOT_IN_BARBERSHOP = 0xB3,
- SPELL_FAILED_FISHING_TOO_LOW = 0xB4,
- SPELL_FAILED_ITEM_ENCHANT_TRADE_WINDOW = 0xB5,
- SPELL_FAILED_SUMMON_PENDING = 0xB6,
- SPELL_FAILED_MAX_SOCKETS = 0xB7,
- SPELL_FAILED_PET_CAN_RENAME = 0xB8,
- SPELL_FAILED_UNKNOWN = 0xB9,
+ SPELL_FAILED_SUCCESS = 0x00,
+ SPELL_FAILED_AFFECTING_COMBAT = 0x01,
+ SPELL_FAILED_ALREADY_AT_FULL_HEALTH = 0x02,
+ SPELL_FAILED_ALREADY_AT_FULL_MANA = 0x03,
+ SPELL_FAILED_ALREADY_AT_FULL_POWER = 0x04,
+ SPELL_FAILED_ALREADY_BEING_TAMED = 0x05,
+ SPELL_FAILED_ALREADY_HAVE_CHARM = 0x06,
+ SPELL_FAILED_ALREADY_HAVE_SUMMON = 0x07,
+ SPELL_FAILED_ALREADY_OPEN = 0x08,
+ SPELL_FAILED_AURA_BOUNCED = 0x09,
+ SPELL_FAILED_AUTOTRACK_INTERRUPTED = 0x0A,
+ SPELL_FAILED_BAD_IMPLICIT_TARGETS = 0x0B,
+ SPELL_FAILED_BAD_TARGETS = 0x0C,
+ SPELL_FAILED_CANT_BE_CHARMED = 0x0D,
+ SPELL_FAILED_CANT_BE_DISENCHANTED = 0x0E,
+ SPELL_FAILED_CANT_BE_DISENCHANTED_SKILL = 0x0F,
+ SPELL_FAILED_CANT_BE_MILLED = 0x10,
+ SPELL_FAILED_CANT_BE_PROSPECTED = 0x11,
+ SPELL_FAILED_CANT_CAST_ON_TAPPED = 0x12,
+ SPELL_FAILED_CANT_DUEL_WHILE_INVISIBLE = 0x13,
+ SPELL_FAILED_CANT_DUEL_WHILE_STEALTHED = 0x14,
+ SPELL_FAILED_CANT_STEALTH = 0x15,
+ SPELL_FAILED_CASTER_AURASTATE = 0x16,
+ SPELL_FAILED_CASTER_DEAD = 0x17,
+ SPELL_FAILED_CHARMED = 0x18,
+ SPELL_FAILED_CHEST_IN_USE = 0x19,
+ SPELL_FAILED_CONFUSED = 0x1A,
+ SPELL_FAILED_DONT_REPORT = 0x1B,
+ SPELL_FAILED_EQUIPPED_ITEM = 0x1C,
+ SPELL_FAILED_EQUIPPED_ITEM_CLASS = 0x1D,
+ SPELL_FAILED_EQUIPPED_ITEM_CLASS_MAINHAND = 0x1E,
+ SPELL_FAILED_EQUIPPED_ITEM_CLASS_OFFHAND = 0x1F,
+ SPELL_FAILED_ERROR = 0x20,
+ SPELL_FAILED_FIZZLE = 0x21,
+ SPELL_FAILED_FLEEING = 0x22,
+ SPELL_FAILED_FOOD_LOWLEVEL = 0x23,
+ SPELL_FAILED_HIGHLEVEL = 0x24,
+ SPELL_FAILED_HUNGER_SATIATED = 0x25,
+ SPELL_FAILED_IMMUNE = 0x26,
+ SPELL_FAILED_INCORRECT_AREA = 0x27,
+ SPELL_FAILED_INTERRUPTED = 0x28,
+ SPELL_FAILED_INTERRUPTED_COMBAT = 0x29,
+ SPELL_FAILED_ITEM_ALREADY_ENCHANTED = 0x2A,
+ SPELL_FAILED_ITEM_GONE = 0x2B,
+ SPELL_FAILED_ITEM_NOT_FOUND = 0x2C,
+ SPELL_FAILED_ITEM_NOT_READY = 0x2D,
+ SPELL_FAILED_LEVEL_REQUIREMENT = 0x2E,
+ SPELL_FAILED_LINE_OF_SIGHT = 0x2F,
+ SPELL_FAILED_LOWLEVEL = 0x30,
+ SPELL_FAILED_LOW_CASTLEVEL = 0x31,
+ SPELL_FAILED_MAINHAND_EMPTY = 0x32,
+ SPELL_FAILED_MOVING = 0x33,
+ SPELL_FAILED_NEED_AMMO = 0x34,
+ SPELL_FAILED_NEED_AMMO_POUCH = 0x35,
+ SPELL_FAILED_NEED_EXOTIC_AMMO = 0x36,
+ SPELL_FAILED_NEED_MORE_ITEMS = 0x37,
+ SPELL_FAILED_NOPATH = 0x38,
+ SPELL_FAILED_NOT_BEHIND = 0x39,
+ SPELL_FAILED_NOT_FISHABLE = 0x3A,
+ SPELL_FAILED_NOT_FLYING = 0x3B,
+ SPELL_FAILED_NOT_HERE = 0x3C,
+ SPELL_FAILED_NOT_INFRONT = 0x3D,
+ SPELL_FAILED_NOT_IN_CONTROL = 0x3E,
+ SPELL_FAILED_NOT_KNOWN = 0x3F,
+ SPELL_FAILED_NOT_MOUNTED = 0x40,
+ SPELL_FAILED_NOT_ON_TAXI = 0x41,
+ SPELL_FAILED_NOT_ON_TRANSPORT = 0x42,
+ SPELL_FAILED_NOT_READY = 0x43,
+ SPELL_FAILED_NOT_SHAPESHIFT = 0x44,
+ SPELL_FAILED_NOT_STANDING = 0x45,
+ SPELL_FAILED_NOT_TRADEABLE = 0x46,
+ SPELL_FAILED_NOT_TRADING = 0x47,
+ SPELL_FAILED_NOT_UNSHEATHED = 0x48,
+ SPELL_FAILED_NOT_WHILE_GHOST = 0x49,
+ SPELL_FAILED_NOT_WHILE_LOOTING = 0x4A,
+ SPELL_FAILED_NO_AMMO = 0x4B,
+ SPELL_FAILED_NO_CHARGES_REMAIN = 0x4C,
+ SPELL_FAILED_NO_CHAMPION = 0x4D,
+ SPELL_FAILED_NO_COMBO_POINTS = 0x4E,
+ SPELL_FAILED_NO_DUELING = 0x4F,
+ SPELL_FAILED_NO_ENDURANCE = 0x50,
+ SPELL_FAILED_NO_FISH = 0x51,
+ SPELL_FAILED_NO_ITEMS_WHILE_SHAPESHIFTED = 0x52,
+ SPELL_FAILED_NO_MOUNTS_ALLOWED = 0x53,
+ SPELL_FAILED_NO_PET = 0x54,
+ SPELL_FAILED_NO_POWER = 0x55,
+ SPELL_FAILED_NOTHING_TO_DISPEL = 0x56,
+ SPELL_FAILED_NOTHING_TO_STEAL = 0x57,
+ SPELL_FAILED_ONLY_ABOVEWATER = 0x58,
+ SPELL_FAILED_ONLY_DAYTIME = 0x59,
+ SPELL_FAILED_ONLY_INDOORS = 0x5A,
+ SPELL_FAILED_ONLY_MOUNTED = 0x5B,
+ SPELL_FAILED_ONLY_NIGHTTIME = 0x5C,
+ SPELL_FAILED_ONLY_OUTDOORS = 0x5D,
+ SPELL_FAILED_ONLY_SHAPESHIFT = 0x5E,
+ SPELL_FAILED_ONLY_STEALTHED = 0x5F,
+ SPELL_FAILED_ONLY_UNDERWATER = 0x60,
+ SPELL_FAILED_OUT_OF_RANGE = 0x61,
+ SPELL_FAILED_PACIFIED = 0x62,
+ SPELL_FAILED_POSSESSED = 0x63,
+ SPELL_FAILED_REAGENTS = 0x64,
+ SPELL_FAILED_REQUIRES_AREA = 0x65,
+ SPELL_FAILED_REQUIRES_SPELL_FOCUS = 0x66,
+ SPELL_FAILED_ROOTED = 0x67,
+ SPELL_FAILED_SILENCED = 0x68,
+ SPELL_FAILED_SPELL_IN_PROGRESS = 0x69,
+ SPELL_FAILED_SPELL_LEARNED = 0x6A,
+ SPELL_FAILED_SPELL_UNAVAILABLE = 0x6B,
+ SPELL_FAILED_STUNNED = 0x6C,
+ SPELL_FAILED_TARGETS_DEAD = 0x6D,
+ SPELL_FAILED_TARGET_AFFECTING_COMBAT = 0x6E,
+ SPELL_FAILED_TARGET_AURASTATE = 0x6F,
+ SPELL_FAILED_TARGET_DUELING = 0x70,
+ SPELL_FAILED_TARGET_ENEMY = 0x71,
+ SPELL_FAILED_TARGET_ENRAGED = 0x72,
+ SPELL_FAILED_TARGET_FRIENDLY = 0x73,
+ SPELL_FAILED_TARGET_IN_COMBAT = 0x74,
+ SPELL_FAILED_TARGET_IS_PLAYER = 0x75,
+ SPELL_FAILED_TARGET_IS_PLAYER_CONTROLLED = 0x76,
+ SPELL_FAILED_TARGET_NOT_DEAD = 0x77,
+ SPELL_FAILED_TARGET_NOT_IN_PARTY = 0x78,
+ SPELL_FAILED_TARGET_NOT_LOOTED = 0x79,
+ SPELL_FAILED_TARGET_NOT_PLAYER = 0x7A,
+ SPELL_FAILED_TARGET_NO_POCKETS = 0x7B,
+ SPELL_FAILED_TARGET_NO_WEAPONS = 0x7C,
+ SPELL_FAILED_TARGET_NO_RANGED_WEAPONS = 0x7D,
+ SPELL_FAILED_TARGET_UNSKINNABLE = 0x7E,
+ SPELL_FAILED_THIRST_SATIATED = 0x7F,
+ SPELL_FAILED_TOO_CLOSE = 0x80,
+ SPELL_FAILED_TOO_MANY_OF_ITEM = 0x81,
+ SPELL_FAILED_TOTEM_CATEGORY = 0x82,
+ SPELL_FAILED_TOTEMS = 0x83,
+ SPELL_FAILED_TRY_AGAIN = 0x84,
+ SPELL_FAILED_UNIT_NOT_BEHIND = 0x85,
+ SPELL_FAILED_UNIT_NOT_INFRONT = 0x86,
+ SPELL_FAILED_WRONG_PET_FOOD = 0x87,
+ SPELL_FAILED_NOT_WHILE_FATIGUED = 0x88,
+ SPELL_FAILED_TARGET_NOT_IN_INSTANCE = 0x89,
+ SPELL_FAILED_NOT_WHILE_TRADING = 0x8A,
+ SPELL_FAILED_TARGET_NOT_IN_RAID = 0x8B,
+ SPELL_FAILED_TARGET_FREEFORALL = 0x8C,
+ SPELL_FAILED_NO_EDIBLE_CORPSES = 0x8D,
+ SPELL_FAILED_ONLY_BATTLEGROUNDS = 0x8E,
+ SPELL_FAILED_TARGET_NOT_GHOST = 0x8F,
+ SPELL_FAILED_TRANSFORM_UNUSABLE = 0x90,
+ SPELL_FAILED_WRONG_WEATHER = 0x91,
+ SPELL_FAILED_DAMAGE_IMMUNE = 0x92,
+ SPELL_FAILED_PREVENTED_BY_MECHANIC = 0x93,
+ SPELL_FAILED_PLAY_TIME = 0x94,
+ SPELL_FAILED_REPUTATION = 0x95,
+ SPELL_FAILED_MIN_SKILL = 0x96,
+ SPELL_FAILED_NOT_IN_ARENA = 0x97,
+ SPELL_FAILED_NOT_ON_SHAPESHIFT = 0x98,
+ SPELL_FAILED_NOT_ON_STEALTHED = 0x99,
+ SPELL_FAILED_NOT_ON_DAMAGE_IMMUNE = 0x9A,
+ SPELL_FAILED_NOT_ON_MOUNTED = 0x9B,
+ SPELL_FAILED_TOO_SHALLOW = 0x9C,
+ SPELL_FAILED_TARGET_NOT_IN_SANCTUARY = 0x9D,
+ SPELL_FAILED_TARGET_IS_TRIVIAL = 0x9E,
+ SPELL_FAILED_BM_OR_INVISGOD = 0x9F,
+ SPELL_FAILED_EXPERT_RIDING_REQUIREMENT = 0xA0,
+ SPELL_FAILED_ARTISAN_RIDING_REQUIREMENT = 0xA1,
+ SPELL_FAILED_NOT_IDLE = 0xA2,
+ SPELL_FAILED_NOT_INACTIVE = 0xA3,
+ SPELL_FAILED_PARTIAL_PLAYTIME = 0xA4,
+ SPELL_FAILED_NO_PLAYTIME = 0xA5,
+ SPELL_FAILED_NOT_IN_BATTLEGROUND = 0xA6,
+ SPELL_FAILED_NOT_IN_RAID_INSTANCE = 0xA7,
+ SPELL_FAILED_ONLY_IN_ARENA = 0xA8,
+ SPELL_FAILED_TARGET_LOCKED_TO_RAID_INSTANCE = 0xA9,
+ SPELL_FAILED_ON_USE_ENCHANT = 0xAA,
+ SPELL_FAILED_NOT_ON_GROUND = 0xAB,
+ SPELL_FAILED_CUSTOM_ERROR = 0xAC,
+ SPELL_FAILED_CANT_DO_THAT_RIGHT_NOW = 0xAD,
+ SPELL_FAILED_TOO_MANY_SOCKETS = 0xAE,
+ SPELL_FAILED_INVALID_GLYPH = 0xAF,
+ SPELL_FAILED_UNIQUE_GLYPH = 0xB0,
+ SPELL_FAILED_GLYPH_SOCKET_LOCKED = 0xB1,
+ SPELL_FAILED_NO_VALID_TARGETS = 0xB2,
+ SPELL_FAILED_ITEM_AT_MAX_CHARGES = 0xB3,
+ SPELL_FAILED_NOT_IN_BARBERSHOP = 0xB4,
+ SPELL_FAILED_FISHING_TOO_LOW = 0xB5,
+ SPELL_FAILED_ITEM_ENCHANT_TRADE_WINDOW = 0xB6,
+ SPELL_FAILED_SUMMON_PENDING = 0xB7,
+ SPELL_FAILED_MAX_SOCKETS = 0xB8,
+ SPELL_FAILED_PET_CAN_RENAME = 0xB9,
+ SPELL_FAILED_UNKNOWN = 0xBA,
SPELL_CAST_OK = 0xFF // custom value, don't must be send to client
};
@@ -2363,8 +2364,8 @@ enum ChatMsg
CHAT_MSG_OFFICER = 0x05,
CHAT_MSG_YELL = 0x06,
CHAT_MSG_WHISPER = 0x07,
- CHAT_MSG_WHISPER_INFORM = 0x08,
- CHAT_MSG_REPLY = 0x09,
+ CHAT_MSG_WHISPER_INFORM = 0x08, // WHISPER_FOREIGN?
+ CHAT_MSG_REPLY = 0x09, // WHISPER_INFORM?
CHAT_MSG_EMOTE = 0x0A,
CHAT_MSG_TEXT_EMOTE = 0x0B,
CHAT_MSG_MONSTER_SAY = 0x0C,
@@ -2437,10 +2438,10 @@ enum PetDiet
#define CHAIN_SPELL_JUMP_RADIUS 10
// Max values for Guild & Guild Bank
-#define GUILD_BANK_MAX_TABS 6
+#define GUILD_BANK_MAX_TABS 6 // send by client for money log also
#define GUILD_BANK_MAX_SLOTS 98
#define GUILD_BANK_MAX_LOGS 25
-#define GUILD_BANK_MONEY_LOGS_TAB 100
+#define GUILD_BANK_MONEY_LOGS_TAB 100 // used for money log in DB
#define GUILD_EVENTLOG_MAX_RECORDS 100
#define GUILD_RANKS_MIN_COUNT 5
#define GUILD_RANKS_MAX_COUNT 10
@@ -2487,14 +2488,7 @@ enum DiminishingGroup
DIMINISHING_TAUNT,
DIMINISHING_LIMITONLY // Don't Diminish, but limit duration to 10s
};
-
-enum DungeonDifficulties
-{
- DIFFICULTY_NORMAL = 0,
- DIFFICULTY_HEROIC = 1,
- TOTAL_DIFFICULTIES
-};
-
+
enum SummonCategory
{
SUMMON_CATEGORY_WILD = 0,
@@ -2596,42 +2590,51 @@ enum ResponseCodes
CHAR_CREATE_EXPANSION_CLASS = 0x3A,
CHAR_CREATE_LEVEL_REQUIREMENT = 0x3B,
CHAR_CREATE_UNIQUE_CLASS_LIMIT = 0x3C,
-
- CHAR_DELETE_IN_PROGRESS = 0x3D,
- CHAR_DELETE_SUCCESS = 0x3E,
- CHAR_DELETE_FAILED = 0x3F,
- CHAR_DELETE_FAILED_LOCKED_FOR_TRANSFER = 0x40,
- CHAR_DELETE_FAILED_GUILD_LEADER = 0x41,
- CHAR_DELETE_FAILED_ARENA_CAPTAIN = 0x42,
-
- CHAR_LOGIN_IN_PROGRESS = 0x43,
- CHAR_LOGIN_SUCCESS = 0x44,
- CHAR_LOGIN_NO_WORLD = 0x45,
- CHAR_LOGIN_DUPLICATE_CHARACTER = 0x46,
- CHAR_LOGIN_NO_INSTANCES = 0x47,
- CHAR_LOGIN_FAILED = 0x48,
- CHAR_LOGIN_DISABLED = 0x49,
- CHAR_LOGIN_NO_CHARACTER = 0x4A,
- CHAR_LOGIN_LOCKED_FOR_TRANSFER = 0x4B,
- CHAR_LOGIN_LOCKED_BY_BILLING = 0x4C,
-
- CHAR_NAME_SUCCESS = 0x4D,
- CHAR_NAME_FAILURE = 0x4E,
- CHAR_NAME_NO_NAME = 0x4F,
- CHAR_NAME_TOO_SHORT = 0x50,
- CHAR_NAME_TOO_LONG = 0x51,
- CHAR_NAME_INVALID_CHARACTER = 0x52,
- CHAR_NAME_MIXED_LANGUAGES = 0x53,
- CHAR_NAME_PROFANE = 0x54,
- CHAR_NAME_RESERVED = 0x55,
- CHAR_NAME_INVALID_APOSTROPHE = 0x56,
- CHAR_NAME_MULTIPLE_APOSTROPHES = 0x57,
- CHAR_NAME_THREE_CONSECUTIVE = 0x58,
- CHAR_NAME_INVALID_SPACE = 0x59,
- CHAR_NAME_CONSECUTIVE_SPACES = 0x5A,
- CHAR_NAME_RUSSIAN_CONSECUTIVE_SILENT_CHARACTERS = 0x5B,
- CHAR_NAME_RUSSIAN_SILENT_CHARACTER_AT_BEGINNING_OR_END = 0x5C,
- CHAR_NAME_DECLENSION_DOESNT_MATCH_BASE_NAME = 0x5D
+ CHAR_CREATE_CHARACTER_IN_GUILD = 0x3D,
+ CHAR_CREATE_RESTRICTED_RACECLASS = 0x3E,
+ CHAR_CREATE_CHARACTER_CHOOSE_RACE = 0x3F,
+ CHAR_CREATE_CHARACTER_ARENA_LEADER = 0x40,
+ CHAR_CREATE_CHARACTER_DELETE_MAIL = 0x41,
+ CHAR_CREATE_CHARACTER_SWAP_FACTION = 0x42,
+ CHAR_CREATE_CHARACTER_RACE_ONLY = 0x43,
+
+ CHAR_CREATE_CHARACTER_GOLD_LIMIT = 0x44,
+
+ CHAR_DELETE_IN_PROGRESS = 0x45,
+ CHAR_DELETE_SUCCESS = 0x46,
+ CHAR_DELETE_FAILED = 0x47,
+ CHAR_DELETE_FAILED_LOCKED_FOR_TRANSFER = 0x48,
+ CHAR_DELETE_FAILED_GUILD_LEADER = 0x49,
+ CHAR_DELETE_FAILED_ARENA_CAPTAIN = 0x4A,
+
+ CHAR_LOGIN_IN_PROGRESS = 0x4B,
+ CHAR_LOGIN_SUCCESS = 0x4C,
+ CHAR_LOGIN_NO_WORLD = 0x4D,
+ CHAR_LOGIN_DUPLICATE_CHARACTER = 0x4E,
+ CHAR_LOGIN_NO_INSTANCES = 0x4F,
+ CHAR_LOGIN_FAILED = 0x50,
+ CHAR_LOGIN_DISABLED = 0x51,
+ CHAR_LOGIN_NO_CHARACTER = 0x52,
+ CHAR_LOGIN_LOCKED_FOR_TRANSFER = 0x53,
+ CHAR_LOGIN_LOCKED_BY_BILLING = 0x54,
+
+ CHAR_NAME_SUCCESS = 0x55,
+ CHAR_NAME_FAILURE = 0x56,
+ CHAR_NAME_NO_NAME = 0x57,
+ CHAR_NAME_TOO_SHORT = 0x58,
+ CHAR_NAME_TOO_LONG = 0x59,
+ CHAR_NAME_INVALID_CHARACTER = 0x5A,
+ CHAR_NAME_MIXED_LANGUAGES = 0x5B,
+ CHAR_NAME_PROFANE = 0x5C,
+ CHAR_NAME_RESERVED = 0x5D,
+ CHAR_NAME_INVALID_APOSTROPHE = 0x5E,
+ CHAR_NAME_MULTIPLE_APOSTROPHES = 0x5F,
+ CHAR_NAME_THREE_CONSECUTIVE = 0x60,
+ CHAR_NAME_INVALID_SPACE = 0x61,
+ CHAR_NAME_CONSECUTIVE_SPACES = 0x62,
+ CHAR_NAME_RUSSIAN_CONSECUTIVE_SILENT_CHARACTERS = 0x63,
+ CHAR_NAME_RUSSIAN_SILENT_CHARACTER_AT_BEGINNING_OR_END = 0x64,
+ CHAR_NAME_DECLENSION_DOESNT_MATCH_BASE_NAME = 0x65
};
/// Ban function modes
@@ -2664,9 +2667,12 @@ enum BattleGroundTypeId
BATTLEGROUND_RL = 8,
BATTLEGROUND_SA = 9,
BATTLEGROUND_DS = 10,
- BATTLEGROUND_RV = 11
+ BATTLEGROUND_RV = 11,
+ BATTLEGROUND_IC = 30,
+ BATTLEGROUND_ABG = 32
};
-#define MAX_BATTLEGROUND_TYPE_ID 12
+
+#define MAX_BATTLEGROUND_TYPE_ID 33
enum MailResponseType
{
@@ -2719,4 +2725,3 @@ enum SpellFamilyNames
};
#endif
-
diff --git a/src/game/Spell.cpp b/src/game/Spell.cpp
index 20c4bd379d9..d5918134ec8 100644
--- a/src/game/Spell.cpp
+++ b/src/game/Spell.cpp
@@ -255,7 +255,10 @@ bool SpellCastTargets::read ( WorldPacket * data, Unit *caster )
if( m_targetMask & TARGET_FLAG_SOURCE_LOCATION )
{
- if(data->rpos() + 4 + 4 + 4 > data->size())
+ if(data->rpos() + 1 + 4 + 4 + 4 > data->size())
+ return false;
+
+ if(!data->readPackGUID(m_unitTargetGUID))
return false;
*data >> m_srcPos.m_positionX >> m_srcPos.m_positionY >> m_srcPos.m_positionZ;
@@ -341,7 +344,14 @@ void SpellCastTargets::write ( WorldPacket * data )
}
if( m_targetMask & TARGET_FLAG_SOURCE_LOCATION )
+ {
+ if(m_unitTarget)
+ data->append(m_unitTarget->GetPackGUID());
+ else
+ *data << uint8(0);
+
*data << m_srcPos.m_positionX << m_srcPos.m_positionY << m_srcPos.m_positionZ;
+ }
if( m_targetMask & TARGET_FLAG_DEST_LOCATION )
{
@@ -1022,7 +1032,7 @@ void Spell::AddItemTarget(Item* pitem, uint32 effIndex)
void Spell::DoAllEffectOnTarget(TargetInfo *target)
{
- if (!target || target->processed) // Check target
+ if (!target || target == (TargetInfo*)0x10 || target->processed)
return;
target->processed = true; // Target checked in apply effects procedure
@@ -2901,7 +2911,7 @@ void Spell::cast(bool skipCheck)
continue;
SpellEntry const *auraSpellInfo = (*i)->GetSpellProto();
uint32 auraSpellIdx = (*i)->GetEffIndex();
- if (SpellEntry const *spellInfo = sSpellStore.LookupEntry(auraSpellInfo->EffectTriggerSpell[auraSpellIdx]))
+ if(SpellEntry const *spellInfo = sSpellStore.LookupEntry(auraSpellInfo->EffectTriggerSpell[auraSpellIdx]))
{
// Calculate chance at that moment (can be depend for example from combo points)
int32 chance = m_caster->CalculateSpellDamage(auraSpellInfo, auraSpellIdx, (*i)->GetBasePoints(), NULL);
@@ -2909,7 +2919,7 @@ void Spell::cast(bool skipCheck)
}
}
- if (m_customAttr & SPELL_ATTR_CU_DIRECT_DAMAGE)
+ if(m_customAttr & SPELL_ATTR_CU_DIRECT_DAMAGE)
CalculateDamageDoneForAllTargets();
// CAST SPELL
@@ -2917,11 +2927,11 @@ void Spell::cast(bool skipCheck)
//SendCastResult(castResult);
SendSpellGo(); // we must send smsg_spell_go packet before m_castItem delete in TakeCastItem()...
- if (m_customAttr & SPELL_ATTR_CU_CHARGE)
+ if(m_customAttr & SPELL_ATTR_CU_CHARGE)
{
for (uint32 i = 0; i < 3; ++i)
{
- switch (m_spellInfo->Effect[i])
+ switch(m_spellInfo->Effect[i])
{
case SPELL_EFFECT_CHARGE:
case SPELL_EFFECT_JUMP:
@@ -2994,10 +3004,18 @@ void Spell::handle_immediate()
_handle_immediate_phase();
for (std::list<TargetInfo>::iterator ihit= m_UniqueTargetInfo.begin(); ihit != m_UniqueTargetInfo.end(); ++ihit)
+ {
DoAllEffectOnTarget(&(*ihit));
+ if(m_UniqueTargetInfo.end()==ihit)
+ break;
+ }
for (std::list<GOTargetInfo>::iterator ihit= m_UniqueGOTargetInfo.begin(); ihit != m_UniqueGOTargetInfo.end(); ++ihit)
+ {
DoAllEffectOnTarget(&(*ihit));
+ if(m_UniqueGOTargetInfo.end()==ihit)
+ break;
+ }
// spell is finished, perform some last features of the spell here
_handle_finish_phase();
@@ -3189,7 +3207,7 @@ void Spell::SendSpellCooldown()
}
// have infinity cooldown but set at aura apply // do not set cooldown for triggered spells (needed by reincarnation)
- if(m_spellInfo->Attributes & SPELL_ATTR_DISABLED_WHILE_ACTIVE || m_IsTriggeredSpell)
+ if(m_spellInfo->Attributes & (SPELL_ATTR_DISABLED_WHILE_ACTIVE | SPELL_ATTR_PASSIVE ) || m_IsTriggeredSpell)
return;
_player->AddSpellAndCategoryCooldowns(m_spellInfo,m_CastItem ? m_CastItem->GetEntry() : 0, this);
@@ -3492,6 +3510,12 @@ void Spell::SendSpellStart()
if ( castFlags & CAST_FLAG_AMMO )
WriteAmmoToPacket(&data);
+ if ( castFlags & CAST_FLAG_UNKNOWN21 )
+ {
+ data << uint32(0);
+ data << uint32(0);
+ }
+
m_caster->SendMessageToSet(&data, true);
}
@@ -4287,9 +4311,10 @@ void Spell::HandleThreatSpells(uint32 spellId)
DEBUG_LOG("Spell %u, rank %u, added an additional %i threat", spellId, spellmgr.GetSpellRank(spellId), threat);
}
-void Spell::HandleEffects(Unit *pUnitTarget, Item *pItemTarget, GameObject *pGOTarget, uint32 i)
+void Spell::HandleEffects(Unit *pUnitTarget,Item *pItemTarget,GameObject *pGOTarget,uint32 i)
{
- if (!Script->OnSpellCast(pUnitTarget, pItemTarget, pGOTarget, i, m_spellInfo))
+
+ if (!Script->OnSpellCast(pUnitTarget,pItemTarget,pGOTarget,i,m_spellInfo))
return;
//effect has been handled, skip it
@@ -4302,12 +4327,12 @@ void Spell::HandleEffects(Unit *pUnitTarget, Item *pItemTarget, GameObject *pGOT
uint8 eff = m_spellInfo->Effect[i];
- sLog.outDebug("Spell: %u Effect : %u", m_spellInfo->Id, eff);
+ sLog.outDebug( "Spell: %u Effect : %u", m_spellInfo->Id, eff);
//we do not need DamageMultiplier here.
damage = CalculateDamage(i, NULL);
- if (eff < TOTAL_SPELL_EFFECTS)
+ if(eff < TOTAL_SPELL_EFFECTS)
{
//sLog.outDebug( "WORLD: Spell FX %d < TOTAL_SPELL_EFFECTS ", eff);
(this->*SpellEffects[eff])(i);
@@ -4316,7 +4341,7 @@ void Spell::HandleEffects(Unit *pUnitTarget, Item *pItemTarget, GameObject *pGOT
void Spell::TriggerSpell()
{
- for (TriggerSpells::iterator si = m_TriggerSpells.begin(); si!=m_TriggerSpells.end(); ++si)
+ for (TriggerSpells::iterator si=m_TriggerSpells.begin(); si!=m_TriggerSpells.end(); ++si)
{
Spell* spell = new Spell(m_caster, (*si), true, m_originalCasterGUID, m_selfContainer, true);
spell->prepare(&m_targets); // use original spell original targets
@@ -4326,7 +4351,7 @@ void Spell::TriggerSpell()
SpellCastResult Spell::CheckCast(bool strict)
{
// check cooldowns to prevent cheating
- if(m_caster->GetTypeId() == TYPEID_PLAYER)
+ if(m_caster->GetTypeId() == TYPEID_PLAYER && !(m_spellInfo->Attributes & SPELL_ATTR_PASSIVE))
{
//can cast triggered (by aura only?) spells while have this flag
if (!m_IsTriggeredSpell && ((Player*)m_caster)->HasFlag(PLAYER_FLAGS, PLAYER_ALLOW_ONLY_ABILITY))
@@ -4518,16 +4543,19 @@ SpellCastResult Spell::CheckCast(bool strict)
}
*/
- if(IsPositiveSpell(m_spellInfo->Id))
- if(target->IsImmunedToSpell(m_spellInfo))
- return SPELL_FAILED_TARGET_AURASTATE;
+ if(target)
+ if(IsPositiveSpell(m_spellInfo->Id))
+ if(target->IsImmunedToSpell(m_spellInfo))
+ return SPELL_FAILED_TARGET_AURASTATE;
//Must be behind the target.
if( m_spellInfo->AttributesEx2 == 0x100000 && (m_spellInfo->AttributesEx & 0x200) == 0x200 && target->HasInArc(M_PI, m_caster)
//Exclusion for Pounce: Facing Limitation was removed in 2.0.1, but it still uses the same, old Ex-Flags
&& (!(m_spellInfo->SpellFamilyName == SPELLFAMILY_DRUID && m_spellInfo->SpellFamilyFlags.IsEqual(0x20000,0,0)))
//Mutilate no longer requires you be behind the target as of patch 3.0.3
- && (!(m_spellInfo->SpellFamilyName == SPELLFAMILY_ROGUE && m_spellInfo->SpellFamilyFlags[1] & 0x200000)))
+ && (!(m_spellInfo->SpellFamilyName == SPELLFAMILY_ROGUE && m_spellInfo->SpellFamilyFlags[1] & 0x200000))
+ //Exclusion for Throw: Facing limitation was added in 3.2.x, but that shouldn't be
+ && (!(m_spellInfo->SpellFamilyName == SPELLFAMILY_ROGUE && m_spellInfo->SpellFamilyFlags[0] & 0x00000001)))
{
SendInterrupted(2);
return SPELL_FAILED_NOT_BEHIND;
@@ -5094,15 +5122,6 @@ SpellCastResult Spell::CheckCast(bool strict)
break;
}
- case 44795: // Parachute
- {
- float x, y, z;
- m_caster->GetPosition(x, y, z);
- float ground_Z = m_caster->GetMap()->GetVmapHeight(x, y, z, true);
- if (fabs(ground_Z - z) < 0.1f)
- return SPELL_FAILED_DONT_REPORT;
- break;
- }
default:
break;
}
@@ -5192,8 +5211,8 @@ SpellCastResult Spell::CheckCast(bool strict)
// allow always ghost flight spells
if (m_originalCaster && m_originalCaster->GetTypeId() == TYPEID_PLAYER && m_originalCaster->isAlive())
{
- // 4197 = Wintergrasp || 4395 = Dalaran && 4564 = Krasus Landing
- if (m_originalCaster->GetZoneId() == 4197 || m_originalCaster->GetZoneId() == 4395 && m_originalCaster->GetAreaId() != 4564)
+ //if (!((Player*)m_originalCaster)->IsKnowHowFlyIn(m_originalCaster->GetMapId(),m_originalCaster->GetZoneId()))
+ if (m_originalCaster->GetZoneId() == 4197 || m_originalCaster->GetZoneId() == 4395)
return m_IsTriggeredSpell ? SPELL_FAILED_DONT_REPORT : SPELL_FAILED_NOT_HERE;
}
break;
@@ -6056,9 +6075,7 @@ bool Spell::CheckTargetCreatureType(Unit* target) const
uint32 spellCreatureTargetMask = m_spellInfo->TargetCreatureType;
// Curse of Doom & Exorcism: not find another way to fix spell target check :/
- if (m_spellInfo->SpellFamilyName==SPELLFAMILY_WARLOCK && m_spellInfo->Category == 1179 ||
- // TODO: will be removed in 3.2.x
- m_spellInfo->SpellFamilyName==SPELLFAMILY_PALADIN && m_spellInfo->Category == 19)
+ if (m_spellInfo->SpellFamilyName==SPELLFAMILY_WARLOCK && m_spellInfo->Category == 1179)
{
// not allow cast at player
if(target->GetTypeId() == TYPEID_PLAYER)
@@ -6375,7 +6392,7 @@ bool Spell::IsValidSingleTargetSpell(Unit const* target) const
}
for (uint8 i = 0; i < 3; ++i)
{
- if (!IsValidSingleTargetEffect(target, Targets(m_spellInfo->EffectImplicitTargetA[i])))
+ if(!IsValidSingleTargetEffect(target, Targets(m_spellInfo->EffectImplicitTargetA[i])))
return false;
// Need to check B?
//if(!IsValidSingleTargetEffect(m_spellInfo->EffectImplicitTargetB[i], target)
@@ -6394,8 +6411,8 @@ void Spell::CalculateDamageDoneForAllTargets()
// Get multiplier
multiplier[i] = m_spellInfo->DmgMultiplier[i];
// Apply multiplier mods
- if (m_originalCaster)
- if (Player *modOwner = m_originalCaster->GetSpellModOwner())
+ if(m_originalCaster)
+ if(Player* modOwner = m_originalCaster->GetSpellModOwner())
modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_EFFECT_PAST_FIRST, multiplier[i], this);
}
}
@@ -6408,7 +6425,7 @@ void Spell::CalculateDamageDoneForAllTargets()
usesAmmo=false;
}
- 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)
{
TargetInfo &target = *ihit;
@@ -6422,8 +6439,8 @@ void Spell::CalculateDamageDoneForAllTargets()
if (usesAmmo)
{
- bool ammoTaken = false;
- for (uint8 i = 0; i < 3; ++i)
+ bool ammoTaken=false;
+ for (uint8 i=0; i<3; i++)
{
if (!(mask & 1<<i))
continue;
@@ -6434,7 +6451,7 @@ void Spell::CalculateDamageDoneForAllTargets()
case SPELL_EFFECT_WEAPON_DAMAGE_NOSCHOOL:
case SPELL_EFFECT_NORMALIZED_WEAPON_DMG:
case SPELL_EFFECT_WEAPON_PERCENT_DAMAGE:
- ammoTaken = true;
+ ammoTaken=true;
TakeAmmo();
}
if (ammoTaken)
@@ -6442,14 +6459,14 @@ void Spell::CalculateDamageDoneForAllTargets()
}
}
- if (target.missCondition == SPELL_MISS_NONE) // In case spell hit target, do all effect on that target
+ if (target.missCondition==SPELL_MISS_NONE) // In case spell hit target, do all effect on that target
{
target.damage += CalculateDamageDone(unit, mask, multiplier);
target.crit = m_caster->isSpellCrit(unit, m_spellInfo, m_spellSchoolMask, m_attackType);
}
else if (target.missCondition == SPELL_MISS_REFLECT) // In case spell reflect from target, do all effect on caster (if hit)
{
- if (target.reflectResult == SPELL_MISS_NONE) // If reflected spell hit caster -> do all effect on him
+ if (target.reflectResult == SPELL_MISS_NONE) // If reflected spell hit caster -> do all effect on him
{
target.damage += CalculateDamageDone(m_caster, mask, multiplier);
target.crit = m_caster->isSpellCrit(m_caster, m_spellInfo, m_spellSchoolMask, m_attackType);
@@ -6485,11 +6502,11 @@ int32 Spell::CalculateDamageDone(Unit *unit, const uint32 effectMask, float *mul
break;
}
- if (m_damage > 0)
+ if(m_damage > 0)
{
- if (IsAreaEffectTarget[m_spellInfo->EffectImplicitTargetA[i]] || IsAreaEffectTarget[m_spellInfo->EffectImplicitTargetB[i]])
+ if(IsAreaEffectTarget[m_spellInfo->EffectImplicitTargetA[i]] || IsAreaEffectTarget[m_spellInfo->EffectImplicitTargetB[i]])
{
- if (int32 reducedPct = unit->GetMaxNegativeAuraModifier(SPELL_AURA_MOD_AOE_DAMAGE_AVOIDANCE))
+ if(int32 reducedPct = unit->GetMaxNegativeAuraModifier(SPELL_AURA_MOD_AOE_DAMAGE_AVOIDANCE))
m_damage = m_damage * (100 + reducedPct) / 100;
}
}
@@ -6519,13 +6536,13 @@ SpellCastResult Spell::CanOpenLock(uint32 effIndex, uint32 lockId, SkillType& sk
bool reqKey = false; // some locks not have reqs
- for (uint8 j = 0; j < 8; ++j)
+ for (int j = 0; j < 8; ++j)
{
- switch (lockInfo->Type[j])
+ switch(lockInfo->Type[j])
{
// check key item (many fit cases can be)
case LOCK_KEY_ITEM:
- if (lockInfo->Index[j] && m_CastItem && m_CastItem->GetEntry()==lockInfo->Index[j])
+ if(lockInfo->Index[j] && m_CastItem && m_CastItem->GetEntry()==lockInfo->Index[j])
return SPELL_CAST_OK;
reqKey = true;
break;
@@ -6535,12 +6552,12 @@ SpellCastResult Spell::CanOpenLock(uint32 effIndex, uint32 lockId, SkillType& sk
reqKey = true;
// wrong locktype, skip
- if (uint32(m_spellInfo->EffectMiscValue[effIndex]) != lockInfo->Index[j])
+ if(uint32(m_spellInfo->EffectMiscValue[effIndex]) != lockInfo->Index[j])
continue;
skillId = SkillByLockType(LockType(lockInfo->Index[j]));
- if (skillId != SKILL_NONE)
+ if ( skillId != SKILL_NONE )
{
// skill bonus provided by casting spell (mostly item spells)
// add the damage modifier from the spell casted (cheat lock / skeleton key etc.) (use m_currentBasePoints, CalculateDamage returns wrong value)
@@ -6562,7 +6579,7 @@ SpellCastResult Spell::CanOpenLock(uint32 effIndex, uint32 lockId, SkillType& sk
}
}
- if (reqKey)
+ if(reqKey)
return SPELL_FAILED_BAD_TARGETS;
return SPELL_CAST_OK;
diff --git a/src/game/Spell.h b/src/game/Spell.h
index 85d8c46771e..dc640438032 100644
--- a/src/game/Spell.h
+++ b/src/game/Spell.h
@@ -77,7 +77,8 @@ enum SpellCastFlags
CAST_FLAG_UNKNOWN10 = 0x00040000,
CAST_FLAG_UNKNOWN5 = 0x00080000, // wotlk
CAST_FLAG_UNKNOWN20 = 0x00100000,
- CAST_FLAG_UNKNOWN7 = 0x00200000 // wotlk, rune cooldown list
+ CAST_FLAG_UNKNOWN7 = 0x00200000, // wotlk, rune cooldown list
+ CAST_FLAG_UNKNOWN21 = 0x04000000
};
enum SpellRangeFlag
@@ -362,6 +363,7 @@ class Spell
void EffectPlayMusic(uint32 i);
void EffectSpecCount(uint32 i);
void EffectActivateSpec(uint32 i);
+ void EffectCastButtons(uint32 i);
typedef std::set<Aura *> UsedSpellMods;
@@ -732,11 +734,11 @@ namespace Trinity
i_data->push_back(target);
break;
case PUSH_IN_FRONT:
- if(i_source->isInFrontInMap(target, i_radius, M_PI/3))
+ if(i_source->isInFront(target, i_radius, M_PI/3))
i_data->push_back(target);
break;
case PUSH_IN_BACK:
- if(i_source->isInBackInMap(target, i_radius, M_PI/3))
+ if(i_source->isInBack(target, i_radius, M_PI/3))
i_data->push_back(target);
break;
case PUSH_IN_LINE:
@@ -780,4 +782,3 @@ class SpellEvent : public BasicEvent
Spell* m_Spell;
};
#endif
-
diff --git a/src/game/SpellAuraDefines.h b/src/game/SpellAuraDefines.h
index fb840620397..633a81bf362 100644
--- a/src/game/SpellAuraDefines.h
+++ b/src/game/SpellAuraDefines.h
@@ -318,7 +318,7 @@ enum AuraType
SPELL_AURA_MOD_ABILITY_IGNORE_TARGET_RESIST = 270, // Possibly need swap vs 195 aura used only in 1 spell Chaos Bolt Passive
SPELL_AURA_MOD_DAMAGE_FROM_CASTER = 271,
SPELL_AURA_272 = 272,
- SPELL_AURA_273 = 273,
+ SPELL_AURA_X_RAY = 273,
SPELL_AURA_ABILITY_CONSUME_NO_AMMO = 274,
SPELL_AURA_MOD_IGNORE_SHAPESHIFT = 275,
SPELL_AURA_276 = 276, // Only "Test Mod Damage % Mechanic" spell, possible mod damage done
@@ -332,15 +332,27 @@ enum AuraType
SPELL_AURA_LINKED = 284,
SPELL_AURA_MOD_ATTACK_POWER_OF_ARMOR = 285,
SPELL_AURA_ABILITY_PERIODIC_CRIT = 286,
- SPELL_AURA_DEFLECT_SPELLS,
- SPELL_AURA_IGNORE_HIT_DIRECTION,
- SPELL_AURA_289,
- SPELL_AURA_MOD_CRIT_PCT,
- SPELL_AURA_MOD_XP_QUEST_PCT,
- SPELL_AURA_292,
- SPELL_AURA_293,
- SPELL_AURA_PREVENT_REGENERATE_POWER,
- TOTAL_AURAS = 295
+ SPELL_AURA_DEFLECT_SPELLS = 287,
+ SPELL_AURA_IGNORE_HIT_DIRECTION = 288,
+ SPELL_AURA_289 = 289,
+ SPELL_AURA_MOD_CRIT_PCT = 290,
+ SPELL_AURA_MOD_XP_QUEST_PCT = 291,
+ SPELL_AURA_292 = 292,
+ SPELL_AURA_293 = 293,
+ SPELL_AURA_PREVENT_REGENERATE_POWER = 294,
+ SPELL_AURA_295 = 295,
+ SPELL_AURA_296 = 296,
+ SPELL_AURA_297 = 297,
+ SPELL_AURA_298 = 298,
+ SPELL_AURA_299 = 299,
+ SPELL_AURA_300 = 300,
+ SPELL_AURA_301 = 301,
+ SPELL_AURA_302 = 302,
+ SPELL_AURA_303 = 303,
+ SPELL_AURA_304 = 304,
+ SPELL_AURA_MOD_MINIMUM_SPEED = 305,
+ SPELL_AURA_306 = 306,
+ TOTAL_AURAS = 307
};
enum AreaAuraType
@@ -353,4 +365,3 @@ enum AreaAuraType
AREA_AURA_OWNER
};
#endif
-
diff --git a/src/game/SpellAuras.cpp b/src/game/SpellAuras.cpp
index f4df205e7e2..7f54d5ad294 100644
--- a/src/game/SpellAuras.cpp
+++ b/src/game/SpellAuras.cpp
@@ -122,7 +122,7 @@ pAuraHandler AuraHandler[TOTAL_AURAS]=
&Aura::HandleFeignDeath, // 66 SPELL_AURA_FEIGN_DEATH
&Aura::HandleAuraModDisarm, // 67 SPELL_AURA_MOD_DISARM
&Aura::HandleAuraModStalked, // 68 SPELL_AURA_MOD_STALKED
- &Aura::HandleNoImmediateEffect, // 69 SPELL_AURA_SCHOOL_ABSORB implemented in Unit::CalcAbsorbResist
+ &Aura::HandleSchoolAbsorb, // 69 SPELL_AURA_SCHOOL_ABSORB implemented in Unit::CalcAbsorbResist
&Aura::HandleUnused, // 70 SPELL_AURA_EXTRA_ATTACKS Useless, used by only one spell that has only visual effect
&Aura::HandleModSpellCritChanceShool, // 71 SPELL_AURA_MOD_SPELL_CRIT_CHANCE_SCHOOL
&Aura::HandleModPowerCostPCT, // 72 SPELL_AURA_MOD_POWER_COST_SCHOOL_PCT
@@ -258,7 +258,7 @@ pAuraHandler AuraHandler[TOTAL_AURAS]=
&Aura::HandleNoImmediateEffect, //202 SPELL_AURA_CANNOT_BE_DODGED implemented in Unit::RollPhysicalOutcomeAgainst
&Aura::HandleNoImmediateEffect, //203 SPELL_AURA_MOD_ATTACKER_MELEE_CRIT_DAMAGE implemented in Unit::CalculateMeleeDamage and Unit::CalculateSpellDamage
&Aura::HandleNoImmediateEffect, //204 SPELL_AURA_MOD_ATTACKER_RANGED_CRIT_DAMAGE implemented in Unit::CalculateMeleeDamage and Unit::CalculateSpellDamage
- &Aura::HandleNULL, //205 SPELL_AURA_MOD_SCHOOL_CRIT_DMG_TAKEN
+ &Aura::HandleNoImmediateEffect, //205 SPELL_AURA_MOD_SCHOOL_CRIT_DMG_TAKEN
&Aura::HandleAuraModIncreaseFlightSpeed, //206 SPELL_AURA_MOD_INCREASE_VEHICLE_FLIGHT_SPEED
&Aura::HandleAuraModIncreaseFlightSpeed, //207 SPELL_AURA_MOD_INCREASE_MOUNTED_FLIGHT_SPEED
&Aura::HandleAuraModIncreaseFlightSpeed, //208 SPELL_AURA_MOD_INCREASE_FLIGHT_SPEED
@@ -326,7 +326,7 @@ pAuraHandler AuraHandler[TOTAL_AURAS]=
&Aura::HandleNoImmediateEffect, //270 SPELL_AURA_MOD_ABILITY_IGNORE_TARGET_RESIST implemented in Unit::CalcAbsorbResist and CalcArmorReducedDamage
&Aura::HandleNoImmediateEffect, //271 SPELL_AURA_MOD_DAMAGE_FROM_CASTER implemented in Unit::SpellDamageBonus
&Aura::HandleNULL, //272 unknown
- &Aura::HandleUnused, //273 clientside
+ &Aura::HandleNoImmediateEffect, //273 SPELL_AURA_X_RAY (client side implementation)
&Aura::HandleNoImmediateEffect, //274 SPELL_AURA_CONSUME_NO_AMMO implemented in spell::CalculateDamageDoneForAllTargets
&Aura::HandleNoImmediateEffect, //275 SPELL_AURA_MOD_IGNORE_SHAPESHIFT Use SpellClassMask for spell select
&Aura::HandleNULL, //276 mod damage % mechanic?
@@ -337,17 +337,29 @@ pAuraHandler AuraHandler[TOTAL_AURAS]=
&Aura::HandleNoImmediateEffect, //281 SPELL_AURA_MOD_HONOR_GAIN_PCT implemented in Player::RewardHonor
&Aura::HandleAuraIncreaseBaseHealthPercent, //282 SPELL_AURA_INCREASE_BASE_HEALTH_PERCENT
&Aura::HandleNoImmediateEffect, //283 SPELL_AURA_MOD_HEALING_RECEIVED implemented in Unit::SpellHealingBonus
- &Aura::HandleAuraLinked, //284 SPELL_AURA_LINKED
+ &Aura::HandleAuraLinked, //284 SPELL_AURA_LINKED 51 spells using
&Aura::HandleAuraModAttackPowerOfArmor, //285 SPELL_AURA_MOD_ATTACK_POWER_OF_ARMOR implemented in Player::UpdateAttackPowerAndDamage
&Aura::HandleNoImmediateEffect, //286 SPELL_AURA_ABILITY_PERIODIC_CRIT implemented in AuraEffect::PeriodicTick
&Aura::HandleNoImmediateEffect, //287 SPELL_AURA_DEFLECT_SPELLS implemented in Unit::MagicSpellHitResult and Unit::MeleeSpellHitResult
- &Aura::HandleNoImmediateEffect, //288 SPELL_AURA_IGNORE_HIT_DIRECTION implemented in Unit::MagicSpellHitResult and Unit::MeleeSpellHitResult Unit::RollMeleeOutcomeAgainst
+ &Aura::HandleNoImmediateEffect, //288 SPELL_AURA_IGNORE_HIT_DIRECTION implemented in Unit::MagicSpellHitResult and Unit::MeleeSpellHitResult Unit::RollMeleeOutcomeAgainst
&Aura::HandleNULL, //289 unused
&Aura::HandleAuraModCritPct, //290 SPELL_AURA_MOD_CRIT_PCT
&Aura::HandleNoImmediateEffect, //291 SPELL_AURA_MOD_XP_QUEST_PCT implemented in Player::RewardQuest
&Aura::HandleNULL, //292 call stabled pet
&Aura::HandleNULL, //293 2 test spells
- &Aura::HandleNoImmediateEffect //294 SPELL_AURA_PREVENT_REGENERATE_POWER implemented in Player::Regenerate(Powers power)
+ &Aura::HandleNoImmediateEffect, //294 SPELL_AURA_PREVENT_REGENERATE_POWER implemented in Player::Regenerate(Powers power)
+ &Aura::HandleNULL, //295 unused
+ &Aura::HandleNULL, //296 2 spells
+ &Aura::HandleNULL, //297 1 spell (counter spell school?)
+ &Aura::HandleNULL, //298 unused
+ &Aura::HandleNULL, //299 unused
+ &Aura::HandleNULL, //300 3 spells (share damage?)
+ &Aura::HandleNULL, //301 5 spells
+ &Aura::HandleNULL, //302 unused
+ &Aura::HandleNULL, //303 17 spells
+ &Aura::HandleNULL, //304 2 spells (alcohol effect?)
+ &Aura::HandleAuraModIncreaseSpeed, //305 SPELL_AURA_MOD_MINIMUM_SPEED
+ &Aura::HandleNULL //306 1 spell
};
#undef Aura
@@ -931,6 +943,131 @@ void AuraEffect::CleanupTriggeredSpells()
m_target->RemoveAurasDueToSpell(tSpellId, GetCasterGUID());
}
+void AuraEffect::HandleSchoolAbsorb(bool apply, bool Real, bool changeAmount)
+{
+ if(!Real)
+ return;
+
+ Unit* caster = GetCaster();
+ if(!caster)
+ return;
+
+ if (apply)
+ {
+ // prevent double apply bonuses
+ if (m_target->GetTypeId()!=TYPEID_PLAYER || !((Player*)m_target)->GetSession()->PlayerLoading())
+ {
+ float DoneActualBenefit = 0.0f;
+ switch(m_spellProto->SpellFamilyName)
+ {
+ case SPELLFAMILY_PRIEST:
+ // Power Word: Shield
+ if (m_spellProto->SpellFamilyFlags & UI64LIT(0x0000000000000001))
+ //+80.68% from +spell bonus
+ DoneActualBenefit = caster->SpellBaseHealingBonus(GetSpellSchoolMask(m_spellProto)) * 0.8068f;
+ break;
+ case SPELLFAMILY_MAGE:
+ // Frost Ward, Fire Ward
+ if (m_spellProto->SpellFamilyFlags & UI64LIT(0x0000000000000108))
+ //+10% from +spell bonus
+ DoneActualBenefit = caster->SpellBaseDamageBonus(GetSpellSchoolMask(m_spellProto)) * 0.1f;
+ // Ice Barrier
+ else if (m_spellProto->SpellFamilyFlags & UI64LIT(0x0000000100000000))
+ //+80.67% from +spell bonus
+ DoneActualBenefit = caster->SpellBaseDamageBonus(GetSpellSchoolMask(m_spellProto)) * 0.8067f;
+ break;
+ case SPELLFAMILY_WARLOCK:
+ // Shadow Ward
+ if (m_spellProto->SpellIconID == 207)
+ //+30% from +spell bonus
+ DoneActualBenefit = caster->SpellBaseDamageBonus(GetSpellSchoolMask(m_spellProto)) * 0.30f;
+ break;
+ case SPELLFAMILY_PALADIN:
+ // Sacred Shield
+ // (check not strictly needed, only Sacred Shield has SPELL_AURA_SCHOOL_ABSORB in SPELLFAMILY_PALADIN at this time)
+ if (m_spellProto->SpellFamilyFlags & UI64LIT(0x0008000000000000))
+ {
+ // +75% from spell power
+ DoneActualBenefit = caster->SpellBaseHealingBonus(GetSpellSchoolMask(m_spellProto)) * 0.75f;
+ }
+ break;
+ default:
+ break;
+ }
+
+ DoneActualBenefit *= caster->CalculateLevelPenalty(GetSpellProto());
+
+ m_amount += (int32)DoneActualBenefit;
+ }
+ }
+ else
+ {
+ if (caster &&
+ // Power Word: Shield
+ m_spellProto->SpellFamilyName == SPELLFAMILY_PRIEST && m_spellProto->Mechanic == MECHANIC_SHIELD &&
+ (m_spellProto->SpellFamilyFlags & UI64LIT(0x0000000000000001)) &&
+ // completely absorbed or dispelled
+ ((m_parentAura->GetRemoveMode() == AURA_REMOVE_BY_DEFAULT && m_amount) || m_parentAura->GetRemoveMode() == AURA_REMOVE_BY_EXPIRE))
+ {
+ Unit::AuraEffectList const& vDummyAuras = caster->GetAurasByType(SPELL_AURA_DUMMY);
+ for(Unit::AuraEffectList::const_iterator itr = vDummyAuras.begin(); itr != vDummyAuras.end(); ++itr)
+ {
+ SpellEntry const* vSpell = (*itr)->GetSpellProto();
+
+ // Rapture (main spell)
+ if(vSpell->SpellFamilyName == SPELLFAMILY_PRIEST && vSpell->SpellIconID == 2894 && vSpell->Effect[1])
+ {
+ switch((*itr)->m_effIndex)
+ {
+ case 0:
+ {
+ // energize caster
+ int32 manapct1000 = 5 * ((*itr)->m_amount + spellmgr.GetSpellRank(vSpell->Id));
+ int32 basepoints0 = caster->GetMaxPower(POWER_MANA) * manapct1000 / 1000;
+ caster->CastCustomSpell(caster, 47755, &basepoints0, NULL, NULL, true);
+ break;
+ }
+ case 1:
+ {
+ // energize target
+ if (!roll_chance_i((*itr)->m_amount) || caster->HasAura(63853))
+ break;
+
+ switch(m_target->getPowerType())
+ {
+ case POWER_RUNIC_POWER:
+ m_target->CastSpell(m_target, 63652, true, NULL, NULL, GetCasterGUID());
+ break;
+ case POWER_RAGE:
+ m_target->CastSpell(m_target, 63653, true, NULL, NULL, GetCasterGUID());
+ break;
+ case POWER_MANA:
+ {
+ int32 basepoints0 = m_target->GetMaxPower(POWER_MANA) * 2 / 100;
+ m_target->CastCustomSpell(m_target, 63654, &basepoints0, NULL, NULL, true);
+ break;
+ }
+ case POWER_ENERGY:
+ m_target->CastSpell(m_target, 63655, true, NULL, NULL, GetCasterGUID());
+ break;
+ default:
+ break;
+ }
+
+ //cooldwon aura
+ caster->CastSpell(caster, 63853, true);
+ break;
+ }
+ default:
+ sLog.outError("Changes in R-dummy spell???: effect 3");
+ break;
+ }
+ }
+ }
+ }
+ }
+}
+
void Aura::ApplyAllModifiers(bool apply, bool Real)
{
for (uint8 i = 0; i<MAX_SPELL_EFFECTS; ++i)
@@ -1504,6 +1641,9 @@ void AuraEffect::HandleAuraEffectSpecificMods(bool apply, bool Real, bool change
// Innervate
else if (m_spellProto->Id == 29166 && GetAuraName() == SPELL_AURA_PERIODIC_ENERGIZE)
m_amount = m_target->GetCreatePowers(POWER_MANA) * m_amount / (GetTotalTicks() * 100.0f);
+ // Owlkin Frenzy
+ else if (m_spellProto->Id == 48391)
+ m_amount = m_target->GetCreatePowers(POWER_MANA) * 2 / 100;
// Thorns
else if (m_spellProto->SpellFamilyFlags[0] & 0x100 && GetAuraName() == SPELL_AURA_DAMAGE_SHIELD)
// 3.3% from sp bonus
@@ -1534,7 +1674,13 @@ void AuraEffect::HandleAuraEffectSpecificMods(bool apply, bool Real, bool change
if (m_spellProto->SpellFamilyFlags[1] & 0x80000 && GetAuraName() == SPELL_AURA_SCHOOL_ABSORB)
{
// 0.75 from sp bonus
- DoneActualBenefit = caster->SpellBaseHealingBonus(GetSpellSchoolMask(m_spellProto)) * 0.75f;
+ float koef = 1.0f;
+ if (caster->HasAura(53527))
+ koef = 1.1f;
+ if (caster->HasAura(53530))
+ koef = 1.2f;
+
+ DoneActualBenefit = caster->SpellBaseHealingBonus(GetSpellSchoolMask(m_spellProto)) * 0.75f * koef;
}
break;
case SPELLFAMILY_SHAMAN:
@@ -1579,26 +1725,6 @@ void AuraEffect::HandleAuraEffectSpecificMods(bool apply, bool Real, bool change
DoneActualBenefit *= caster->CalculateLevelPenalty(GetSpellProto());
m_amount += (int32)DoneActualBenefit;
}
-
- // we have exact amount now so apply mods affecting all boni
- switch (m_spellProto->SpellFamilyName)
- {
- case SPELLFAMILY_PRIEST:
- // Glyph of Power Word: Shield
- if (m_spellProto->SpellFamilyFlags[0] & 0x1 && m_spellProto->SpellFamilyFlags[2] & 0x400 &&
- GetAuraName() == SPELL_AURA_SCHOOL_ABSORB)
- {
- if (AuraEffect* glyph = caster->GetAuraEffect(55672,0))
- {
- // instantly heal m_amount% of the absorb-value
- int32 heal = (glyph->GetAmount() * m_amount)/100;
- caster->CastCustomSpell(m_target, 56160, &heal, NULL, NULL, true, 0, this);
- }
- }
- break;
- default:
- break;
- }
}
}
}
@@ -2079,8 +2205,10 @@ void AuraEffect::HandleShapeshiftBoosts(bool apply)
case FORM_SHADOW:
spellId = 49868;
break;
- case FORM_GHOUL:
case FORM_GHOSTWOLF:
+ spellId = 67116;
+ break;
+ case FORM_GHOUL:
case FORM_AMBIENT:
case FORM_STEALTH:
case FORM_CREATURECAT:
@@ -2287,7 +2415,6 @@ void AuraEffect::HandleAddModifier(bool apply, bool Real, bool changeAmount)
mod->value = m_amount;
mod->type = SpellModType(m_auraName); // SpellModType value == spell aura types
mod->spellId = GetId();
-
mod->mask = m_spellProto->EffectSpellClassMask[m_effIndex];
mod->charges = GetParentAura()->GetAuraCharges();
@@ -2922,7 +3049,7 @@ void AuraEffect::HandleAuraDummy(bool apply, bool Real, bool changeAmount)
{
if (m_target->GetMap()->IsDungeon())
{
- uint32 spellId = m_target->GetMap()->IsHeroic() ? 46163 : 44190;
+ uint32 spellId = ((InstanceMap*)m_target->GetMap())->GetDifficulty() == REGULAR_DIFFICULTY ? 44190 : 46163;
m_target->CastSpell(m_target, spellId, true, NULL, this);
}
@@ -2959,6 +3086,30 @@ void AuraEffect::HandleAuraDummy(bool apply, bool Real, bool changeAmount)
return;
}
break;
+ case SPELLFAMILY_PALADIN:
+ switch (GetSpellProto()->SpellIconID)
+ {
+ // Blessing of Sanctuary
+ // Greater Blessing of Sanctuary
+ case 19:
+ case 1804:
+ {
+ if (!caster || !m_target)
+ return;
+
+ if (apply)
+ {
+ // Greater Blessing of Sanctuary does not provide strength bonus
+ int32 bp1 = 0;
+ caster->CastCustomSpell(m_target, 67480, NULL, (GetSpellProto()->SpellIconID == 1804) ? &bp1 : NULL, NULL, true);
+ }
+ else
+ m_target->RemoveAurasDueToSpell(67480);
+
+ return;
+ }
+ }
+ break;
case SPELLFAMILY_PRIEST:
// Vampiric Touch
if (m_spellProto->SpellFamilyFlags[1] & 0x0400 && GetParentAura()->GetRemoveMode() == AURA_REMOVE_BY_ENEMY_SPELL)
@@ -3371,7 +3522,30 @@ void AuraEffect::HandleAuraFeatherFall(bool apply, bool Real, bool /*changeAmoun
WorldPacket data;
if (apply)
+ {
+ Unit* caster = GetCaster();
+ if (!caster)
+ return;
+
+ if (caster->GetGUID() == m_target->GetGUID())
+ {
+ m_target->RemoveAurasByType(SPELL_AURA_MOD_INCREASE_MOUNTED_FLIGHT_SPEED);
+ m_target->RemoveAurasByType(SPELL_AURA_FLY);
+ }
+
+ if (GetId() == 61243) // No fly zone - Parachute
+ {
+ float x, y, z;
+ caster->GetPosition(x, y, z);
+ float ground_Z = caster->GetMap()->GetVmapHeight(x, y, z, true);
+ if (fabs(ground_Z - z) < 0.1f)
+ {
+ m_target->RemoveAura(GetId());
+ return;
+ }
+ }
data.Initialize(SMSG_MOVE_FEATHER_FALL, 8+4);
+ }
else
data.Initialize(SMSG_MOVE_NORMAL_FALL, 8+4);
data.append(m_target->GetPackGUID());
@@ -3417,89 +3591,37 @@ void AuraEffect::HandleAuraModShapeshift(bool apply, bool Real, bool changeAmoun
switch(form)
{
case FORM_CAT:
- if(Player::TeamForRace(m_target->getRace())==ALLIANCE)
- modelid = 892;
- else
- modelid = 8571;
- PowerType = POWER_ENERGY;
- break;
- case FORM_TRAVEL:
- modelid = 632;
- break;
- case FORM_AQUA:
- if(Player::TeamForRace(m_target->getRace())==ALLIANCE)
- modelid = 2428;
- else
- modelid = 2428;
- break;
- case FORM_BEAR:
- if(Player::TeamForRace(m_target->getRace())==ALLIANCE)
- modelid = 2281;
- else
- modelid = 2289;
- PowerType = POWER_RAGE;
- break;
case FORM_GHOUL:
- modelid = 24994;
PowerType = POWER_ENERGY;
break;
+ case FORM_BEAR:
case FORM_DIREBEAR:
- if(Player::TeamForRace(m_target->getRace())==ALLIANCE)
- modelid = 2281;
- else
- modelid = 2289;
+ case FORM_BATTLESTANCE:
+ case FORM_BERSERKERSTANCE:
+ case FORM_DEFENSIVESTANCE:
PowerType = POWER_RAGE;
break;
+ case FORM_TRAVEL:
+ case FORM_AQUA:
case FORM_CREATUREBEAR:
- modelid = 902;
- break;
case FORM_GHOSTWOLF:
- modelid = 4613;
- break;
case FORM_FLIGHT:
- if(Player::TeamForRace(m_target->getRace())==ALLIANCE)
- modelid = 20857;
- else
- modelid = 20872;
- break;
case FORM_MOONKIN:
- if(Player::TeamForRace(m_target->getRace())==ALLIANCE)
- modelid = 15374;
- else
- modelid = 15375;
- break;
case FORM_FLIGHT_EPIC:
- if(Player::TeamForRace(m_target->getRace())==ALLIANCE)
- modelid = 21243;
- else
- modelid = 21244;
- break;
- case FORM_MASTER_ANGLER:
- modelid = 15234;
- break;
case FORM_METAMORPHOSIS:
- modelid = 25277;
- break;
+ case FORM_MASTER_ANGLER:
case FORM_AMBIENT:
case FORM_SHADOW:
case FORM_STEALTH:
case FORM_UNDEAD:
case FORM_SHADOW_DANCE:
- break;
case FORM_TREE:
- modelid = 864;
- break;
- case FORM_BATTLESTANCE:
- case FORM_BERSERKERSTANCE:
- case FORM_DEFENSIVESTANCE:
- PowerType = POWER_RAGE;
- break;
case FORM_SPIRITOFREDEMPTION:
- modelid = 16031;
break;
default:
sLog.outError("Auras: Unknown Shapeshift Type: %u", GetMiscValue());
}
+ modelid = m_target->GetModelForForm(form);
// remove polymorph before changing display id to keep new display id
switch ( form )
@@ -3566,7 +3688,10 @@ void AuraEffect::HandleAuraModShapeshift(bool apply, bool Real, bool changeAmoun
case FORM_BEAR:
case FORM_DIREBEAR:
if (urand(0,99) < FurorChance)
- m_target->CastSpell(m_target, 17057, true);
+ {
+ int32 basePoints = 100; // Not sure if 100 is correct basePoints, maybe it should be 10?
+ m_target->CastCustomSpell(m_target, 17057, &basePoints, NULL, NULL, true, NULL, this);
+ }
default:
{
uint32 newEnergy = std::min(m_target->GetPower(POWER_ENERGY), FurorChance);
@@ -4632,21 +4757,26 @@ void AuraEffect::HandleAuraModStalked(bool apply, bool Real, bool /*changeAmount
void AuraEffect::HandlePeriodicTriggerSpell(bool apply, bool Real, bool /*changeAmount*/)
{
m_isPeriodic = apply;
+ if (!apply)
+ {
+ switch(m_spellProto->Id)
+ {
+ case 66: // Invisibility
+ m_target->CastSpell(m_target, 32612, true, NULL, this);
+
+ return;
+ case 42783: //Wrath of the Astrom...
+ m_target->CastSpell(m_target, m_spellProto->CalculateSimpleValue(GetEffIndex()+1), true);
+ return;
+ default:
+ break;
+ }
+ }
}
void AuraEffect::HandlePeriodicTriggerSpellWithValue(bool apply, bool Real, bool /*changeAmount*/)
{
m_isPeriodic = apply;
-
- SpellEntry const* spell = GetSpellProto();
- switch (spell->Id)
- {
- case 58730: // No fly zone - Wintergrasp (3.1.3 only 3.2.2 Does not call this aura)
- if (apply)
- if (m_target->GetTypeId() == TYPEID_PLAYER)
- ((Player *)m_target)->GetSession()->SendNotification(LANG_ZONE_NOFLYZONE);
- break;
- }
}
void AuraEffect::HandlePeriodicEnergize(bool apply, bool Real, bool changeAmount)
@@ -4668,30 +4798,22 @@ void AuraEffect::HandleAuraPeriodicDummy(bool apply, bool Real, bool changeAmoun
Unit* caster = GetCaster();
SpellEntry const*spell = GetSpellProto();
- switch(spell->SpellFamilyName)
+ switch( spell->SpellFamilyName)
{
case SPELLFAMILY_GENERIC:
{
- switch(spell->Id)
+ if(spell->Id == 62399) // Overload Circuit
{
- case 62399: // Overload Circuit
- if(m_target->GetMap()->IsDungeon() && m_target->GetAuras().count(62399) >= (m_target->GetMap()->IsHeroic() ? 4 : 2))
- {
- m_target->CastSpell(m_target, 62475, true); // System Shutdown
- if(Unit *veh = m_target->GetVehicleBase())
- veh->CastSpell(m_target, 62475, true);
- }
- break;
- case 58600: // No fly zone - Dalaran
- if (apply && m_target->GetTypeId() == TYPEID_PLAYER)
- ((Player *)m_target)->GetSession()->SendNotification(LANG_ZONE_NOFLYZONE);
- break;
- default:
- break;
+ if(m_target->GetMap()->IsDungeon())
+ if(m_target->GetAuras().count(62399) >= (((InstanceMap*)m_target->GetMap())->GetDifficulty() == REGULAR_DIFFICULTY ? 2 : 4))
+ {
+ m_target->CastSpell(m_target, 62475, true); // System Shutdown
+ if(Unit *veh = m_target->GetVehicleBase())
+ veh->CastSpell(m_target, 62475, true);
+ }
}
break;
}
-
case SPELLFAMILY_WARLOCK:
{
switch (spell->Id)
@@ -4704,12 +4826,11 @@ void AuraEffect::HandleAuraPeriodicDummy(bool apply, bool Real, bool changeAmoun
// to prevent remove GO added by new spell
// old one is already removed
if (GetParentAura()->GetRemoveMode()!=AURA_REMOVE_BY_STACK)
- m_target->RemoveGameObject(spell->Id, true);
+ m_target->RemoveGameObject(spell->Id,true);
m_target->RemoveAura(62388);
}
break;
}
- break;
}
case SPELLFAMILY_DEATHKNIGHT:
{
@@ -5934,11 +6055,10 @@ void AuraEffect::PeriodicTick()
bool crit = IsPeriodicTickCrit(pCaster);
if (crit)
pdamage = pCaster->SpellCriticalDamageBonus(m_spellProto, pdamage, m_target);
-
- //As of 2.2 resilience reduces damage from DoT ticks as much as the chance to not be critically hit
- // Reduce dot damage from resilience for players
+
+ // Reduce dot damage from resilience for players.
if (m_target->GetTypeId() == TYPEID_PLAYER)
- pdamage-=((Player*)m_target)->GetDotDamageReduction(pdamage);
+ pdamage-=((Player*)m_target)->GetSpellDamageReduction(pdamage);
pCaster->CalcAbsorbResist(m_target, GetSpellSchoolMask(GetSpellProto()), DOT, pdamage, &absorb, &resist, m_spellProto);
@@ -6006,11 +6126,10 @@ void AuraEffect::PeriodicTick()
cleanDamage.mitigated_damage += pdamage - pdamageReductedArmor;
pdamage = pdamageReductedArmor;
}
-
- //As of 2.2 resilience reduces damage from DoT ticks as much as the chance to not be critically hit
- // Reduce dot damage from resilience for players
+
+ // Reduce dot damage from resilience for players.
if (m_target->GetTypeId() == TYPEID_PLAYER)
- pdamage-=((Player*)m_target)->GetDotDamageReduction(pdamage);
+ pdamage-=((Player*)m_target)->GetSpellDamageReduction(pdamage);
pCaster->CalcAbsorbResist(m_target, GetSpellSchoolMask(GetSpellProto()), DOT, pdamage, &absorb, &resist, m_spellProto);
@@ -6566,24 +6685,6 @@ void AuraEffect::PeriodicDummyTick()
// 7053 Forsaken Skill: Shadow
return;
}
- case 45472: // Parachute
- if (m_target->GetTypeId() == TYPEID_PLAYER)
- {
- Player *plr = (Player*)m_target;
- if (plr->IsFalling())
- {
- plr->RemoveAurasDueToSpell(45472);
- plr->CastSpell(plr, 44795, true);
- }
- }
- break;
- case 58600: // No fly Zone - Dalaran
- if (10 == m_tickNumber)
- {
- m_target->RemoveAurasByType(SPELL_AURA_MOD_INCREASE_MOUNTED_FLIGHT_SPEED);
- m_target->RemoveAurasByType(SPELL_AURA_FLY);
- }
- break;
case 58549: // Tenacity
case 59911: // Tenacity (vehicle)
GetParentAura()->RefreshAura();
diff --git a/src/game/SpellAuras.h b/src/game/SpellAuras.h
index 3730107461a..9fdff04f05f 100644
--- a/src/game/SpellAuras.h
+++ b/src/game/SpellAuras.h
@@ -321,6 +321,7 @@ class TRINITY_DLL_SPEC AuraEffect
void HandleForceMoveForward(bool apply, bool Real, bool changeAmount);
void HandleAuraModResistenceOfStatPercent(bool apply, bool Real, bool changeAmount);
void HandleAuraPowerBurn(bool apply, bool Real, bool changeAmount);
+ void HandleSchoolAbsorb(bool apply, bool Real, bool changeAmount);
void HandlePreventFleeing(bool apply, bool Real, bool changeAmount);
void HandleArenaPreparation(bool apply, bool Real, bool changeAmount);
void HandleAuraConvertRune(bool apply, bool Real, bool changeAmount);
diff --git a/src/game/SpellEffects.cpp b/src/game/SpellEffects.cpp
index 3f90a52c7df..c3a633c5ffc 100644
--- a/src/game/SpellEffects.cpp
+++ b/src/game/SpellEffects.cpp
@@ -161,7 +161,7 @@ pEffect SpellEffects[TOTAL_SPELL_EFFECTS]=
&Spell::EffectSelfResurrect, // 94 SPELL_EFFECT_SELF_RESURRECT
&Spell::EffectSkinning, // 95 SPELL_EFFECT_SKINNING
&Spell::EffectCharge, // 96 SPELL_EFFECT_CHARGE
- &Spell::EffectUnused, // 97 SPELL_EFFECT_97
+ &Spell::EffectCastButtons, // 97 SPELL_EFFECT_CAST_BUTTON (totem bar since 3.2.2a)
&Spell::EffectKnockBack, // 98 SPELL_EFFECT_KNOCK_BACK
&Spell::EffectDisEnchant, // 99 SPELL_EFFECT_DISENCHANT
&Spell::EffectInebriate, //100 SPELL_EFFECT_INEBRIATE
@@ -377,7 +377,7 @@ void Spell::SpellDamageSchoolDmg(uint32 effect_idx)
break;
// Consumption
case 28865:
- damage = (m_caster->GetMap()->IsHeroic() ? 4250 : 2750);
+ damage = (((InstanceMap*)m_caster->GetMap())->GetDifficulty() == REGULAR_DIFFICULTY ? 2750 : 4250);
break;
// percent from health with min
case 25599: // Thundercrash
@@ -420,8 +420,7 @@ void Spell::SpellDamageSchoolDmg(uint32 effect_idx)
damage = unitTarget->GetMaxHealth() / 10;
break;
}
- // Gargoyle Strike
- case 51963:
+ case 51963: // Gargoyle Strike
{
// about +4 base spell dmg per level
damage = (m_caster->getLevel() - 60) * 4 + 60;
@@ -535,7 +534,23 @@ void Spell::SpellDamageSchoolDmg(uint32 effect_idx)
if (unitTarget->GetAura(SPELL_AURA_PERIODIC_DAMAGE, SPELLFAMILY_PRIEST, 0x100000, 0, 0, m_caster->GetGUID()))
damage += damage * aurEff->GetAmount() / 100;
}
-
+ // Improved Mind Blast (Mind Blast in shadow form bonus)
+ else if (m_caster->m_form == FORM_SHADOW && (m_spellInfo->SpellFamilyFlags[0] & 0x00002000))
+ {
+ Unit::AuraEffectList const& ImprMindBlast = m_caster->GetAurasByType(SPELL_AURA_ADD_FLAT_MODIFIER);
+ for(Unit::AuraEffectList::const_iterator i = ImprMindBlast.begin(); i != ImprMindBlast.end(); ++i)
+ {
+ if ((*i)->GetSpellProto()->SpellFamilyName == SPELLFAMILY_PRIEST &&
+ ((*i)->GetSpellProto()->SpellIconID == 95))
+ {
+ int chance = (*i)->GetSpellProto()->CalculateSimpleValue(1);
+ if (roll_chance_i(chance))
+ // Mind Trauma
+ m_caster->CastSpell(unitTarget, 48301, true, 0);
+ break;
+ }
+ }
+ }
break;
}
case SPELLFAMILY_DRUID:
@@ -687,12 +702,12 @@ void Spell::SpellDamageSchoolDmg(uint32 effect_idx)
damage += int32(0.25f*ap + 0.4f*sp);
}
// Judgement of Wisdom, Light, Justice
- else if (m_spellInfo->SpellFamilyFlags[0] & 0x00800000 && m_spellInfo->Id != 31804 && m_spellInfo->Id != 53733)
+ else if(m_spellInfo->Id == 54158)
{
float ap = m_caster->GetTotalAttackPowerValue(BASE_ATTACK);
float sp = m_caster->SpellBaseDamageBonus(GetSpellSchoolMask(m_spellInfo));
damage += int32(0.16f*ap + 0.25f*sp);
- }
+ }
break;
}
case SPELLFAMILY_DEATHKNIGHT:
@@ -850,6 +865,22 @@ void Spell::EffectDummy(uint32 i)
m_caster->CastSpell(unitTarget,spell_id,true,NULL);
return;
}
+ case 67019: // Flask of the North
+ {
+ if (m_caster->GetTypeId() != TYPEID_PLAYER)
+ return;
+
+ uint32 spell_id;
+ switch(urand(1, 3))
+ {
+ case 1: spell_id = 67016; break;
+ case 2: spell_id = 67017; break;
+ default:spell_id = 67018; break;
+ }
+
+ m_caster->CastSpell(m_caster, spell_id, true, NULL);
+ return;
+ }
case 13280: // Gnomish Death Ray
{
if (!unitTarget)
@@ -945,10 +976,6 @@ void Spell::EffectDummy(uint32 i)
creatureTarget->ForcedDespawn();
- WorldPacket data(SMSG_GAMEOBJECT_SPAWN_ANIM_OBSOLETE, 8);
- data << uint64(Crystal_Prison->GetGUID());
- m_caster->SendMessageToSet(&data, true);
-
return;
}
case 23074: // Arcanite Dragonling
@@ -1351,16 +1378,28 @@ void Spell::EffectDummy(uint32 i)
m_caster->CastSpell(m_caster, 54586, true);
return;
}
+ // Great Feast
+ case 57337:
+ {
+ if (!unitTarget)
+ return;
+
+ unitTarget->CastSpell(unitTarget, 58067, true);
+ break;
+ }
+ //Fish Feast
+ case 57397:
+ {
+ if (!unitTarget)
+ return;
+
+ unitTarget->CastSpell(unitTarget, 58648, true);
+ unitTarget->CastSpell(unitTarget, 57398, true);
+ break;
+ }
case 58418: // Portal to Orgrimmar
case 58420: // Portal to Stormwind
return; // implemented in EffectScript[0]
- case 58601:
- if (Player *plr = (Player*)unitTarget)
- {
- plr->RemoveAurasByType(SPELL_AURA_MOD_INCREASE_MOUNTED_FLIGHT_SPEED);
- plr->RemoveAurasByType(SPELL_AURA_FLY);
- }
- break;
case 59640: // Underbelly Elixir
{
if(m_caster->GetTypeId() != TYPEID_PLAYER)
@@ -1426,29 +1465,6 @@ void Spell::EffectDummy(uint32 i)
}
}
- //All IconID Check in there
- switch(m_spellInfo->SpellIconID)
- {
- // Berserking (troll racial traits)
- case 1661:
- {
- uint32 healthPerc = uint32((float(m_caster->GetHealth())/m_caster->GetMaxHealth())*100);
- int32 melee_mod = 10;
- if (healthPerc <= 40)
- melee_mod = 30;
- if (healthPerc < 100 && healthPerc > 40)
- melee_mod = 10+(100-healthPerc)/3;
-
- int32 hasteModBasePoints0 = melee_mod; // (EffectBasePoints[0]+1)-1+(5-melee_mod) = (melee_mod-1+1)-1+5-melee_mod = 5-1
- int32 hasteModBasePoints1 = (5-melee_mod);
- int32 hasteModBasePoints2 = 5;
-
- // FIXME: custom spell required this aura state by some unknown reason, we not need remove it anyway
- m_caster->ModifyAuraState(AURA_STATE_BERSERKING,true);
- m_caster->CastCustomSpell(m_caster, 26635, &hasteModBasePoints0, &hasteModBasePoints1, &hasteModBasePoints2, true, NULL);
- return;
- }
- }
break;
}
case SPELLFAMILY_MAGE:
@@ -1501,6 +1517,10 @@ void Spell::EffectDummy(uint32 i)
{
int32 chargeBasePoints0 = damage;
m_caster->CastCustomSpell(m_caster, 34846, &chargeBasePoints0, NULL, NULL, true);
+
+ //Juggernaut crit bonus
+ if(m_caster->HasAura(64976))
+ m_caster->CastSpell(m_caster, 65156, true);
return;
}
//Slam
@@ -1533,8 +1553,8 @@ void Spell::EffectDummy(uint32 i)
}
else
{
- rage += m_caster->GetPower(POWER_RAGE);
- m_caster->SetPower(POWER_RAGE,0);
+ rage += m_powerCost;
+ m_caster->ModifyPower(POWER_RAGE,- m_powerCost);
}
bp = damage+int32(rage * m_spellInfo->DmgMultiplier[i] +
@@ -1629,9 +1649,9 @@ void Spell::EffectDummy(uint32 i)
if (!unitTarget || !unitTarget->isAlive())
return;
- uint32 hurt = 0;
- uint32 heal = 0;
- switch (m_spellInfo->Id)
+ int hurt = 0;
+ int heal = 0;
+ switch(m_spellInfo->Id)
{
case 47540: hurt = 47758; heal = 47757; break;
case 53005: hurt = 53001; heal = 52986; break;
@@ -1653,15 +1673,15 @@ void Spell::EffectDummy(uint32 i)
if (m_spellInfo->SpellFamilyFlags[2] & 0x100)
{
//Shapeshifting into an animal form or mounting cancels the effect.
- if (m_caster->GetCreatureType() == CREATURE_TYPE_BEAST || m_caster->IsMounted())
+ if(m_caster->GetCreatureType() == CREATURE_TYPE_BEAST || m_caster->IsMounted())
{
- if (m_triggeredByAuraSpell)
+ if(m_triggeredByAuraSpell)
m_caster->RemoveAurasDueToSpell(m_triggeredByAuraSpell->Id);
return;
}
//Any effect which causes you to lose control of your character will supress the starfall effect.
- if (m_caster->hasUnitState(UNIT_STAT_STUNNED | UNIT_STAT_FLEEING | UNIT_STAT_ROOT | UNIT_STAT_CONFUSED))
+ if(m_caster->hasUnitState(UNIT_STAT_STUNNED | UNIT_STAT_FLEEING | UNIT_STAT_ROOT | UNIT_STAT_CONFUSED))
return;
m_caster->CastSpell(unitTarget, damage, true);
@@ -1675,35 +1695,35 @@ void Spell::EffectDummy(uint32 i)
m_caster->CastSpell(m_caster, 63848, true);
break;
}
- switch(m_spellInfo->Id)
+ switch(m_spellInfo->Id )
{
case 5938: // Shiv
{
- if (m_caster->GetTypeId() != TYPEID_PLAYER)
+ if(m_caster->GetTypeId() != TYPEID_PLAYER)
return;
Player *pCaster = ((Player*)m_caster);
Item *item = pCaster->GetWeaponForAttack(OFF_ATTACK);
- if (!item)
+ if(!item)
return;
// all poison enchantments is temporary
uint32 enchant_id = item->GetEnchantmentId(TEMP_ENCHANTMENT_SLOT);
- if (!enchant_id)
+ if(!enchant_id)
return;
SpellItemEnchantmentEntry const *pEnchant = sSpellItemEnchantmentStore.LookupEntry(enchant_id);
- if (!pEnchant)
+ if(!pEnchant)
return;
- for (uint8 s = 0; s < 3; ++s)
+ for (int s=0; s<3; s++)
{
- if(pEnchant->type[s] != ITEM_ENCHANTMENT_TYPE_COMBAT_SPELL)
+ if(pEnchant->type[s]!=ITEM_ENCHANTMENT_TYPE_COMBAT_SPELL)
continue;
- SpellEntry const *combatEntry = sSpellStore.LookupEntry(pEnchant->spellid[s]);
- if (!combatEntry || combatEntry->Dispel != DISPEL_POISON)
+ SpellEntry const* combatEntry = sSpellStore.LookupEntry(pEnchant->spellid[s]);
+ if(!combatEntry || combatEntry->Dispel != DISPEL_POISON)
continue;
m_caster->CastSpell(unitTarget, combatEntry, true, item);
@@ -1714,7 +1734,7 @@ void Spell::EffectDummy(uint32 i)
}
case 14185: // Preparation
{
- if (m_caster->GetTypeId() != TYPEID_PLAYER)
+ if(m_caster->GetTypeId() != TYPEID_PLAYER)
return;
//immediately finishes the cooldown on certain Rogue abilities
@@ -1738,14 +1758,21 @@ void Spell::EffectDummy(uint32 i)
}
break;
case SPELLFAMILY_HUNTER:
- switch (m_spellInfo->Id)
+ switch(m_spellInfo->Id)
{
case 781: // Disengage
{
- if (m_caster->GetTypeId() != TYPEID_PLAYER || !m_caster->isInCombat()) // Does not require a target, but m_caster must be in combat (3.0.3?)
+ if (m_caster->GetTypeId() != TYPEID_PLAYER)
return;
- m_caster->JumpTo(15.0f, 7.0f, false);
+ WorldPacket data(SMSG_MOVE_KNOCK_BACK, 50);
+ data.append(m_caster->GetPackGUID());
+ data << getMSTime();
+ data << float(cosf(m_caster->GetOrientation()+M_PI));
+ data << float(sinf(m_caster->GetOrientation()+M_PI));
+ data << float(15);
+ data << float(-7.0f);
+ ((Player*)m_caster)->GetSession()->SendPacket(&data);
return;
}
case 23989: // Readiness talent
@@ -1759,7 +1786,7 @@ void Spell::EffectDummy(uint32 i)
{
SpellEntry const *spellInfo = sSpellStore.LookupEntry(itr->first);
- if (spellInfo->SpellFamilyName == SPELLFAMILY_HUNTER && spellInfo->Id != 23989 && GetSpellRecoveryTime(spellInfo) > 0)
+ if (spellInfo->SpellFamilyName == SPELLFAMILY_HUNTER && spellInfo->Id != 23989 && spellInfo->Id != 19574 && GetSpellRecoveryTime(spellInfo) > 0 )
((Player*)m_caster)->RemoveSpellCooldown((itr++)->first,true);
else
++itr;
@@ -1812,10 +1839,10 @@ void Spell::EffectDummy(uint32 i)
if (!unitTarget)
return;
- uint32 hurt = 0;
- uint32 heal = 0;
+ int hurt = 0;
+ int heal = 0;
- switch (m_spellInfo->Id)
+ switch(m_spellInfo->Id)
{
case 20473: hurt = 25912; heal = 25914; break;
case 20929: hurt = 25911; heal = 25913; break;
@@ -1825,7 +1852,7 @@ void Spell::EffectDummy(uint32 i)
case 48824: hurt = 48822; heal = 48820; break;
case 48825: hurt = 48823; heal = 48821; break;
default:
- sLog.outError("Spell::EffectDummy: Spell %u not handled in Holy Shock",m_spellInfo->Id);
+ sLog.outError("Spell::EffectDummy: Spell %u not handled in HS",m_spellInfo->Id);
return;
}
@@ -1858,13 +1885,26 @@ void Spell::EffectDummy(uint32 i)
}
case 31789: // Righteous Defense (step 1)
{
+ if (m_caster->GetTypeId() != TYPEID_PLAYER)
+ {
+ SendCastResult(SPELL_FAILED_TARGET_AFFECTING_COMBAT);
+ return;
+ }
+
// 31989 -> dummy effect (step 1) + dummy effect (step 2) -> 31709 (taunt like spell for each target)
+ Unit* friendTarget = !unitTarget || unitTarget->IsFriendlyTo(m_caster) ? unitTarget : unitTarget->getVictim();
+ if (friendTarget)
+ {
+ Player* player = friendTarget->GetCharmerOrOwnerPlayerOrPlayerItself();
+ if (!player || !player->IsInSameRaidWith((Player*)m_caster))
+ friendTarget = NULL;
+ }
+
// non-standard cast requirement check
- if (!unitTarget || unitTarget->getAttackers().empty())
+ if (!friendTarget || friendTarget->getAttackers().empty())
{
- if (m_caster->GetTypeId() == TYPEID_PLAYER)
- ((Player*)m_caster)->RemoveSpellCooldown(m_spellInfo->Id,true);
+ ((Player*)m_caster)->RemoveSpellCooldown(m_spellInfo->Id,true);
SendCastResult(SPELL_FAILED_TARGET_AFFECTING_COMBAT);
return;
}
@@ -1874,18 +1914,16 @@ void Spell::EffectDummy(uint32 i)
for (std::list<TargetInfo>::iterator ihit = m_UniqueTargetInfo.begin(); ihit != m_UniqueTargetInfo.end(); ++ihit)
ihit->effectMask &= ~(1<<1);
- // not empty (checked)
- Unit::AttackerSet const& attackers = unitTarget->getAttackers();
+ // not empty (checked), copy
+ Unit::AttackerSet attackers = friendTarget->getAttackers();
- // chance to be selected from list
- float chance = 100.0f / attackers.size();
- uint32 count = 0;
- for (Unit::AttackerSet::const_iterator aItr = attackers.begin(); aItr != attackers.end() && count < 3; ++aItr)
+ // selected from list 3
+ for(int i = 0; i < std::min(size_t(3),attackers.size()); ++i)
{
- if (!roll_chance_f(chance))
- continue;
- ++count;
+ Unit::AttackerSet::iterator aItr = attackers.begin();
+ std::advance(aItr, rand() % attackers.size());
AddUnitTarget((*aItr), 1);
+ attackers.erase(aItr);
}
// now let next effect cast spell at each target.
@@ -1912,55 +1950,6 @@ void Spell::EffectDummy(uint32 i)
}
break;
case SPELLFAMILY_SHAMAN:
- // Rockbiter Weapon
- if (m_spellInfo->SpellFamilyFlags[0] & 0x400000)
- {
- // TODO: use expect spell for enchant (if exist talent)
- // In 3.0.3 no mods present for rockbiter
- uint32 spell_id = 0;
- switch (m_spellInfo->Id)
- {
- case 8017: spell_id = 36494; break; // Rank 1
- case 8018: spell_id = 36750; break; // Rank 2
- case 8019: spell_id = 36755; break; // Rank 3
- case 10399: spell_id = 36759; break; // Rank 4
- default:
- sLog.outError("Spell::EffectDummy: Spell %u not handled in RW", m_spellInfo->Id);
- return;
- }
-
- SpellEntry const *spellInfo = sSpellStore.LookupEntry( spell_id );
-
- if (!spellInfo)
- {
- sLog.outError("WORLD: unknown spell id %i", spell_id);
- return;
- }
-
- if (m_caster->GetTypeId() != TYPEID_PLAYER)
- return;
-
- for (uint8 j = BASE_ATTACK; j <= OFF_ATTACK; ++j)
- {
- if (Item* item = ((Player*)m_caster)->GetWeaponForAttack(WeaponAttackType(j)))
- {
- if (item->IsFitToSpellRequirements(m_spellInfo))
- {
- Spell *spell = new Spell(m_caster, spellInfo, true);
-
- // enchanting spell selected by calculated damage-per-sec in enchanting effect
- // at calculation applied affect from Elemental Weapons talent
- // real enchantment damage-1
- spell->m_currentBasePoints[1] = damage-1;
-
- SpellCastTargets targets;
- targets.setItemTarget(item);
- spell->prepare(&targets);
- }
- }
- }
- return;
- }
// Cleansing Totem Pulse
if (m_spellInfo->SpellFamilyFlags[0] & 0x04000000 && m_spellInfo->SpellIconID==1673)
{
@@ -3377,6 +3366,7 @@ void Spell::EffectOpenLock(uint32 effIndex)
return;
}
}
+ // TODO: Add script for spell 41920 - Filling, becouse server it freze when use this spell
// handle outdoor pvp object opening, return true if go was registered for handling
// these objects must have been spawned by outdoorpvp!
else if(gameObjTarget->GetGOInfo()->type == GAMEOBJECT_TYPE_GOOBER && sOutdoorPvPMgr.HandleOpenGo(player, gameObjTarget->GetGUID()))
@@ -4111,64 +4101,61 @@ void Spell::EffectEnchantItemTmp(uint32 i)
Player* p_caster = (Player*)m_caster;
+ // Rockbiter Weapon apply to both weapon
if (!itemTarget)
- return;
-
- uint32 enchant_id = m_spellInfo->EffectMiscValue[i];
-
- // Shaman Rockbiter Weapon
- if (i == 0 && m_spellInfo->Effect[1] == SPELL_EFFECT_DUMMY)
+ return;
+ if (m_spellInfo->SpellFamilyName == SPELLFAMILY_SHAMAN && m_spellInfo->SpellFamilyFlags[0] & 0x400000)
{
- int32 enchnting_damage = CalculateDamage(1, NULL);//+1;
+ uint32 spell_id = 0;
- // enchanting id selected by calculated damage-per-sec stored in Effect[1] base value
- // with already applied percent bonus from Elemental Weapons talent
+ // enchanting spell selected by calculated damage-per-sec stored in Effect[1] base value
// Note: damage calculated (correctly) with rounding int32(float(v)) but
// RW enchantments applied damage int32(float(v)+0.5), this create 0..1 difference sometime
- switch (enchnting_damage)
+ switch(damage)
{
// Rank 1
- case 2: enchant_id = 29; break; // 0% [ 7% == 2, 14% == 2, 20% == 2]
+ case 2: spell_id = 36744; break; // 0% [ 7% == 2, 14% == 2, 20% == 2]
// Rank 2
- case 4: enchant_id = 6; break; // 0% [ 7% == 4, 14% == 4]
- case 5: enchant_id = 3025; break; // 20%
+ case 4: spell_id = 36753; break; // 0% [ 7% == 4, 14% == 4]
+ case 5: spell_id = 36751; break; // 20%
// Rank 3
- case 6: enchant_id = 1; break; // 0% [ 7% == 6, 14% == 6]
- case 7: enchant_id = 3027; break; // 20%
+ case 6: spell_id = 36754; break; // 0% [ 7% == 6, 14% == 6]
+ case 7: spell_id = 36755; break; // 20%
// Rank 4
- case 9: enchant_id = 3032; break; // 0% [ 7% == 6]
- case 10: enchant_id = 503; break; // 14%
- case 11: enchant_id = 3031; break; // 20%
- // Rank 5
- case 15: enchant_id = 3035; break; // 0%
- case 16: enchant_id = 1663; break; // 7%
- case 17: enchant_id = 3033; break; // 14%
- case 18: enchant_id = 3034; break; // 20%
- // Rank 6
- case 28: enchant_id = 3038; break; // 0%
- case 29: enchant_id = 683; break; // 7%
- case 31: enchant_id = 3036; break; // 14%
- case 33: enchant_id = 3037; break; // 20%
- // Rank 7
- case 40: enchant_id = 3041; break; // 0%
- case 42: enchant_id = 1664; break; // 7%
- case 45: enchant_id = 3039; break; // 14%
- case 48: enchant_id = 3040; break; // 20%
- // Rank 8
- case 49: enchant_id = 3044; break; // 0%
- case 52: enchant_id = 2632; break; // 7%
- case 55: enchant_id = 3042; break; // 14%
- case 58: enchant_id = 3043; break; // 20%
- // Rank 9
- case 62: enchant_id = 2633; break; // 0%
- case 66: enchant_id = 3018; break; // 7%
- case 70: enchant_id = 3019; break; // 14%
- case 74: enchant_id = 3020; break; // 20%
+ case 9: spell_id = 36761; break; // 0% [ 7% == 6]
+ case 10: spell_id = 36758; break; // 14%
+ case 11: spell_id = 36760; break; // 20%
default:
- sLog.outError("Spell::EffectEnchantItemTmp: Damage %u not handled in S'RW",enchnting_damage);
+ sLog.outError("Spell::EffectEnchantItemTmp: Damage %u not handled in S'RW",damage);
return;
}
+
+ SpellEntry const *spellInfo = sSpellStore.LookupEntry(spell_id);
+ if (!spellInfo)
+ {
+ sLog.outError("Spell::EffectEnchantItemTmp: unknown spell id %i", spell_id);
+ return;
+ }
+
+ for(int j = BASE_ATTACK; j <= OFF_ATTACK; ++j)
+ {
+ if (Item* item = p_caster->GetWeaponForAttack(WeaponAttackType(j)))
+ {
+ if (item->IsFitToSpellRequirements(m_spellInfo))
+ {
+ Spell *spell = new Spell(m_caster, spellInfo, true);
+ SpellCastTargets targets;
+ targets.setItemTarget( item );
+ spell->prepare(&targets);
+ }
+ }
+ }
+ return;
}
+ if (!itemTarget)
+ return;
+
+ uint32 enchant_id = m_spellInfo->EffectMiscValue[i];
if (!enchant_id)
{
@@ -4402,6 +4389,13 @@ void Spell::EffectTaunt(uint32 /*i*/)
return;
}
+ if (m_spellInfo->Id == 62124)
+ {
+ int32 damageDone = 1 + m_caster->GetTotalAttackPowerValue(BASE_ATTACK) * 0.5f;
+ m_caster->DealDamage(unitTarget, damageDone, NULL, SPELL_DIRECT_DAMAGE, SPELL_SCHOOL_MASK_HOLY, m_spellInfo, false);
+ m_caster->SendSpellNonMeleeDamageLog(unitTarget, m_spellInfo->Id, damageDone, SPELL_SCHOOL_MASK_HOLY, 0, 0, false, false, false);
+ }
+
// Also use this effect to set the taunter's threat to the taunted creature's highest value
if (unitTarget->getThreatManager().getCurrentVictim())
{
@@ -4583,15 +4577,6 @@ void Spell::SpellDamageWeaponDmg(uint32 i)
else
m_caster->CastCustomSpell(m_caster, 53725, &damagePoint, NULL, NULL, true);
}
- // Seal of Blood/of the Martyr backlash damage (10%)
- else if (m_spellInfo->SpellIconID==2293)
- {
- int32 damagePoint = m_damage * 10 / 100;
- if(m_spellInfo->Id == 31893)
- m_caster->CastCustomSpell(m_caster, 32221, &damagePoint, NULL, NULL, true);
- else
- m_caster->CastCustomSpell(m_caster, 53718, &damagePoint, NULL, NULL, true);
- }
}
case SPELLFAMILY_SHAMAN:
{
@@ -4676,10 +4661,10 @@ void Spell::SpellDamageWeaponDmg(uint32 i)
}
bool normalized = false;
- float weaponDamagePercentMod = 1.0f;
- for (uint8 j = 0; j < 3; ++j)
+ float weaponDamagePercentMod = 1.0;
+ for (int j = 0; j < 3; ++j)
{
- switch (m_spellInfo->Effect[j])
+ switch(m_spellInfo->Effect[j])
{
case SPELL_EFFECT_WEAPON_DAMAGE:
case SPELL_EFFECT_WEAPON_DAMAGE_NOSCHOOL:
@@ -4698,10 +4683,10 @@ void Spell::SpellDamageWeaponDmg(uint32 i)
}
// apply to non-weapon bonus weapon total pct effect, weapon total flat effect included in weapon damage
- if (fixed_bonus || spell_bonus)
+ if(fixed_bonus || spell_bonus)
{
UnitMods unitMod;
- switch (m_attackType)
+ switch(m_attackType)
{
default:
case BASE_ATTACK: unitMod = UNIT_MOD_DAMAGE_MAINHAND; break;
@@ -4710,23 +4695,23 @@ void Spell::SpellDamageWeaponDmg(uint32 i)
}
float weapon_total_pct = 1.0f;
- if (m_spellInfo->SchoolMask & SPELL_SCHOOL_MASK_NORMAL)
+ if ( m_spellInfo->SchoolMask & SPELL_SCHOOL_MASK_NORMAL )
weapon_total_pct = m_caster->GetModifierValue(unitMod, TOTAL_PCT);
- if (fixed_bonus)
+ if(fixed_bonus)
fixed_bonus = int32(fixed_bonus * weapon_total_pct);
- if (spell_bonus)
+ if(spell_bonus)
spell_bonus = int32(spell_bonus * weapon_total_pct);
}
int32 weaponDamage = m_caster->CalculateDamage(m_attackType, normalized, true);
// Sequence is important
- for (uint8 j = 0; j < 3; ++j)
+ for (int j = 0; j < 3; ++j)
{
// We assume that a spell have at most one fixed_bonus
// and at most one weaponDamagePercentMod
- switch (m_spellInfo->Effect[j])
+ switch(m_spellInfo->Effect[j])
{
case SPELL_EFFECT_WEAPON_DAMAGE:
case SPELL_EFFECT_WEAPON_DAMAGE_NOSCHOOL:
@@ -4753,7 +4738,7 @@ void Spell::SpellDamageWeaponDmg(uint32 i)
// Add melee damage bonuses (also check for negative)
m_caster->MeleeDamageBonus(unitTarget, &eff_damage, m_attackType, m_spellInfo);
- m_damage += eff_damage;
+ m_damage+= eff_damage;
}
void Spell::EffectThreat(uint32 /*i*/)
@@ -5218,11 +5203,17 @@ void Spell::EffectScriptEffect(uint32 effIndex)
switch(((Player*)unitTarget)->GetBaseSkillValue(762))
{
- case 75: unitTarget->CastSpell(unitTarget, 51621, true); break;;
- case 150: unitTarget->CastSpell(unitTarget, 48024, true); break;
- case 225: unitTarget->CastSpell(unitTarget, 51617, true); break;
- case 300: unitTarget->CastSpell(unitTarget, 48023, true); break;
- default: break;
+ case 75: unitTarget->CastSpell(unitTarget, 51621, true); break;;
+ case 150: unitTarget->CastSpell(unitTarget, 48024, true); break;
+ case 225:
+ if(((Player*)unitTarget)->GetMapId()==571 || ((Player*)unitTarget)->GetMapId()==530)
+ unitTarget->CastSpell(unitTarget, 51617, true);
+ break;
+ case 300:
+ if(((Player*)unitTarget)->GetMapId()==571 || ((Player*)unitTarget)->GetMapId()==530)
+ unitTarget->CastSpell(unitTarget, 48023, true);
+ break;
+ default: break;
}
break;
}
@@ -5492,25 +5483,6 @@ void Spell::EffectScriptEffect(uint32 effIndex)
}
return;
}
- // Great Feast
- case 57337:
- {
- if (!unitTarget)
- return;
-
- unitTarget->CastSpell(unitTarget, 58067, true);
- break;
- }
- //Fish Feast
- case 57397:
- {
- if (!unitTarget)
- return;
-
- unitTarget->CastSpell(unitTarget, 58648, true);
- unitTarget->CastSpell(unitTarget, 57398, true);
- break;
- }
case 58418: // Portal to Orgrimmar
case 58420: // Portal to Stormwind
{
@@ -5553,15 +5525,15 @@ void Spell::EffectScriptEffect(uint32 effIndex)
m_originalCaster->CastSpell(unitTarget, 58689, true);
m_originalCaster->CastSpell(unitTarget, 58692, true);
}
- if(m_originalCaster->GetMap()->IsHeroic())
+ if(((InstanceMap*)m_originalCaster->GetMap())->GetDifficulty() == REGULAR_DIFFICULTY)
{
- m_originalCaster->CastSpell(unitTarget, 60883, true);
- m_originalCaster->CastSpell(unitTarget, 60884, true);
+ m_originalCaster->CastSpell(unitTarget, 58695, true);
+ m_originalCaster->CastSpell(unitTarget, 58696, true);
}
else
{
- m_originalCaster->CastSpell(unitTarget, 58695, true);
- m_originalCaster->CastSpell(unitTarget, 58696, true);
+ m_originalCaster->CastSpell(unitTarget, 60883, true);
+ m_originalCaster->CastSpell(unitTarget, 60884, true);
}
}
return;
@@ -5611,12 +5583,15 @@ void Spell::EffectScriptEffect(uint32 effIndex)
return;
}
case 62428: // Load into Catapult
+ {
if(Vehicle *seat = m_caster->GetVehicleKit())
if(Unit *passenger = seat->GetPassenger(0))
if(Unit *demolisher = m_caster->GetVehicleBase())
passenger->CastSpell(demolisher, damage, true);
return;
+ }
case 62482: // Grab Crate
+ {
if(unitTarget)
{
if(Vehicle *seat = m_caster->GetVehicleKit())
@@ -5629,6 +5604,7 @@ void Spell::EffectScriptEffect(uint32 effIndex)
}
}
return;
+ }
case 60123: // Lightwell
{
if (m_caster->GetTypeId() != TYPEID_UNIT || !((Creature*)m_caster)->isSummon())
@@ -5803,9 +5779,6 @@ void Spell::EffectScriptEffect(uint32 effIndex)
AuraDivinePlea->RefreshAura();
return;
}
- case 45634: //Neural Needle
- unitTarget->CastSpell(unitTarget, 45702, true); //Neural Needle Impact
- return;
}
break;
}
@@ -6067,7 +6040,7 @@ void Spell::EffectScriptEffect(uint32 effIndex)
case SPELLFAMILY_WARRIOR:
{
// Shattering Throw
- if ( m_spellInfo->SpellFamilyFlags[1] & 0x1 )
+ if (m_spellInfo->SpellFamilyFlags[1] & 0x00400000)
{
if(!unitTarget)
return;
@@ -6098,7 +6071,7 @@ void Spell::EffectSanctuary(uint32 /*i*/)
if(!(*iter)->hasUnitState(UNIT_STAT_CASTING))
continue;
- for (uint32 i = CURRENT_FIRST_NON_MELEE_SPELL; i < CURRENT_MAX_SPELL; ++i)
+ for (uint32 i = CURRENT_FIRST_NON_MELEE_SPELL; i < CURRENT_MAX_SPELL; i++)
{
if((*iter)->GetCurrentSpell(i)
&& (*iter)->GetCurrentSpell(i)->m_targets.getUnitTargetGUID() == unitTarget->GetGUID())
@@ -6497,9 +6470,6 @@ void Spell::EffectSummonObject(uint32 i)
m_caster->AddGameObject(pGameObj);
map->Add(pGameObj);
- WorldPacket data(SMSG_GAMEOBJECT_SPAWN_ANIM_OBSOLETE, 8);
- data << uint64(pGameObj->GetGUID());
- m_caster->SendMessageToSet(&data, true);
m_caster->m_ObjectSlot[slot] = pGameObj->GetGUID();
}
@@ -7089,10 +7059,6 @@ void Spell::EffectTransmitted(uint32 effIndex)
cMap->Add(pGameObj);
- WorldPacket data(SMSG_GAMEOBJECT_SPAWN_ANIM_OBSOLETE, 8);
- data << uint64(pGameObj->GetGUID());
- m_caster->SendMessageToSet(&data,true);
-
if(uint32 linkedEntry = pGameObj->GetGOInfo()->GetLinkedGameObjectEntry())
{
GameObject* linkedGO = new GameObject;
@@ -7399,6 +7365,7 @@ void Spell::SummonGuardian(uint32 i, uint32 entry, SummonPropertiesEntry const *
}
else
summon->SetDisplayId(1126);
+
summon->AI()->EnterEvadeMode();
}
}
@@ -7484,3 +7451,34 @@ void Spell::EffectActivateSpec(uint32 /*eff_idx*/)
((Player*)unitTarget)->ActivateSpec(damage-1); // damage is 1 or 2, spec is 0 or 1
}
+void Spell::EffectCastButtons(uint32 i)
+{
+ if (!unitTarget || m_caster->GetTypeId() != TYPEID_PLAYER)
+ return;
+
+ Player *p_caster = (Player*)m_caster;
+ uint32 button_id = m_spellInfo->EffectMiscValue[i] + 132;
+ uint32 n_buttons = m_spellInfo->EffectMiscValueB[i];
+
+ for (; n_buttons; n_buttons--, button_id++)
+ {
+ if (uint32 spell_id = p_caster->GetActionButtonSpell(button_id))
+ {
+ if (!spell_id)
+ continue;
+
+ if (p_caster->HasSpellCooldown(spell_id))
+ continue;
+
+ SpellEntry const *spellInfo = sSpellStore.LookupEntry(spell_id);
+ uint32 cost = CalculatePowerCost(spellInfo, m_caster, GetSpellSchoolMask(spellInfo));
+
+ if (m_caster->GetPower(POWER_MANA) < cost)
+ break;
+
+ m_caster->CastSpell(unitTarget, spell_id, true);
+ m_caster->ModifyPower(POWER_MANA, -(int32)cost);
+ p_caster->AddSpellAndCategoryCooldowns(spellInfo, 0);
+ }
+ }
+}
diff --git a/src/game/SpellHandler.cpp b/src/game/SpellHandler.cpp
index 1fd07ff19e8..a9a28511d0c 100644
--- a/src/game/SpellHandler.cpp
+++ b/src/game/SpellHandler.cpp
@@ -325,7 +325,7 @@ void WorldSession::HandleCastSpellOpcode(WorldPacket& recvPacket)
else
{
// not have spell in spellbook or spell passive and not casted by client
- if (!((Creature*)mover)->HasSpell(spellId) || IsPassiveSpell(spellId) )
+ if ((mover->GetTypeId() == TYPEID_UNIT && !((Creature*)mover)->HasSpell(spellId)) || IsPassiveSpell(spellId))
{
//cheater? kick? ban?
recvPacket.rpos(recvPacket.wpos()); // prevent spam at ignore packet
@@ -356,10 +356,18 @@ void WorldSession::HandleCastSpellOpcode(WorldPacket& recvPacket)
{
//recvPacket.read_skip<float>(); // unk1, coords?
//recvPacket.read_skip<float>(); // unk1, coords?
- recvPacket.read_skip<uint8>(); // >> 1
- recvPacket.read_skip<uint32>(); // >> MSG_MOVE_STOP
- MovementInfo movementInfo;
- ReadMovementInfo(recvPacket, &movementInfo);
+ uint8 unk1;
+ recvPacket >> unk1; // >> 1 or 0
+ if(unk1)
+ {
+ recvPacket.read_skip<uint32>(); // >> MSG_MOVE_STOP
+ uint64 guid; // guid - unused
+ if(!recvPacket.readPackGUID(guid))
+ return;
+
+ MovementInfo movementInfo;
+ ReadMovementInfo(recvPacket, &movementInfo);
+ }
}
// auto-selection buff level base at target level (in spellInfo)
@@ -632,4 +640,3 @@ void WorldSession::HandleMirrrorImageDataRequest( WorldPacket & recv_data )
}
SendPacket( &data );
}
-
diff --git a/src/game/SpellMgr.cpp b/src/game/SpellMgr.cpp
index dc6bbc728df..5600f1d2bf2 100644
--- a/src/game/SpellMgr.cpp
+++ b/src/game/SpellMgr.cpp
@@ -819,6 +819,7 @@ bool SpellMgr::_isPositiveEffect(uint32 spellId, uint32 effIndex, bool deep) con
case 38638: // Nether Exhaustion (green)
case 38639: // Nether Exhaustion (blue)
case 11196: // Recently Bandaged
+ case 44689: // Relay Race Accept Hidden Debuff - DND
return false;
default:
break;
@@ -3030,31 +3031,17 @@ bool SpellArea::IsFitToRequirements(Player const* player, uint32 newZone, uint32
return false;
}
- if (auraSpell)
+ if(auraSpell)
{
// not have expected aura
- if (!player || auraSpell > 0 && !player->HasAura(auraSpell) || auraSpell < 0 && player->HasAura(-auraSpell))
+ if(!player)
return false;
- }
-
- // Extra conditions
- switch(spellId)
- {
- case 58045: // Essence of Wintergrasp - Wintergrasp
- case 57940: // Essence of Wintergrasp - Northrend
- if (!player || player->GetTeamId() != sWorld.getState(WORLDSTATE_WINTERGRASP_CONTROLING_FACTION))
- return false;
- break;
- case 58600: // No fly Zone - Dalaran (Krasus Landing exception)
- if (!player || player->GetAreaId() == 4564 || !player->HasAuraType(SPELL_AURA_MOD_INCREASE_MOUNTED_FLIGHT_SPEED) && !player->HasAuraType(SPELL_AURA_FLY)
- || player->HasAura(44795))
- return false;
- break;
- case 58730: // No fly Zone - Wintergrasp
- if (!player || !player->HasAuraType(SPELL_AURA_MOD_INCREASE_MOUNTED_FLIGHT_SPEED) && !player->HasAuraType(SPELL_AURA_FLY)
- || player->HasAura(45472) || player->HasAura(44795))
- return false;
- break;
+ if(auraSpell > 0)
+ // have expected aura
+ return player->HasAura(auraSpell);
+ else
+ // not have expected aura
+ return !player->HasAura(-auraSpell);
}
return true;
@@ -3656,6 +3643,10 @@ void SpellMgr::LoadSpellCustomAttr()
case 32182:
spellInfo->excludeCasterAuraSpell = 57723; // Exhaustion
break;
+ // Bloodlust
+ case 2825:
+ spellInfo->excludeCasterAuraSpell = 57724; // Sated
+ break;
// Heart of the Crusader
case 20335:
case 20336:
diff --git a/src/game/SpellMgr.h b/src/game/SpellMgr.h
index b3f98ec7fe3..f95da00ccb2 100644
--- a/src/game/SpellMgr.h
+++ b/src/game/SpellMgr.h
@@ -810,7 +810,7 @@ class SpellMgr
uint32 GetSpellElixirMask(uint32 spellid) const
{
SpellElixirMap::const_iterator itr = mSpellElixirs.find(spellid);
- if (itr == mSpellElixirs.end())
+ if(itr==mSpellElixirs.end())
return 0x0;
return itr->second;
@@ -819,13 +819,13 @@ class SpellMgr
SpellSpecific GetSpellElixirSpecific(uint32 spellid) const
{
uint32 mask = GetSpellElixirMask(spellid);
- if ((mask & ELIXIR_FLASK_MASK) == ELIXIR_FLASK_MASK)
+ if((mask & ELIXIR_FLASK_MASK)==ELIXIR_FLASK_MASK)
return SPELL_FLASK_ELIXIR;
- else if (mask & ELIXIR_BATTLE_MASK)
+ else if(mask & ELIXIR_BATTLE_MASK)
return SPELL_BATTLE_ELIXIR;
- else if (mask & ELIXIR_GUARDIAN_MASK)
+ else if(mask & ELIXIR_GUARDIAN_MASK)
return SPELL_GUARDIAN_ELIXIR;
- else if (mask & ELIXIR_WELL_FED)
+ else if(mask & ELIXIR_WELL_FED)
return SPELL_WELL_FED;
else
return SPELL_NORMAL;
@@ -834,7 +834,7 @@ class SpellMgr
uint16 GetSpellThreat(uint32 spellid) const
{
SpellThreatMap::const_iterator itr = mSpellThreatMap.find(spellid);
- if (itr == mSpellThreatMap.end())
+ if(itr==mSpellThreatMap.end())
return 0;
return itr->second;
@@ -844,7 +844,7 @@ class SpellMgr
SpellProcEventEntry const* GetSpellProcEvent(uint32 spellId) const
{
SpellProcEventMap::const_iterator itr = mSpellProcEventMap.find(spellId);
- if (itr != mSpellProcEventMap.end())
+ if( itr != mSpellProcEventMap.end( ) )
return &itr->second;
return NULL;
}
@@ -854,7 +854,7 @@ class SpellMgr
SpellEnchantProcEntry const* GetSpellEnchantProcEvent(uint32 enchId) const
{
SpellEnchantProcEventMap::const_iterator itr = mSpellEnchantProcEventMap.find(enchId);
- if (itr != mSpellEnchantProcEventMap.end())
+ if( itr != mSpellEnchantProcEventMap.end( ) )
return &itr->second;
return NULL;
}
@@ -864,13 +864,13 @@ class SpellMgr
{
// Lookup data
SpellBonusMap::const_iterator itr = mSpellBonusMap.find(spellId);
- if (itr != mSpellBonusMap.end())
+ if( itr != mSpellBonusMap.end( ) )
return &itr->second;
// Not found, try lookup for 1 spell rank if exist
if (uint32 rank_1 = GetFirstSpellInChain(spellId))
{
SpellBonusMap::const_iterator itr2 = mSpellBonusMap.find(rank_1);
- if (itr2 != mSpellBonusMap.end())
+ if( itr2 != mSpellBonusMap.end( ) )
return &itr2->second;
}
return NULL;
@@ -880,7 +880,7 @@ class SpellMgr
SpellTargetPosition const* GetSpellTargetPosition(uint32 spell_id) const
{
SpellTargetPositionMap::const_iterator itr = mSpellTargetPositions.find( spell_id );
- if (itr != mSpellTargetPositions.end())
+ if( itr != mSpellTargetPositions.end( ) )
return &itr->second;
return NULL;
}
@@ -889,7 +889,7 @@ class SpellMgr
SpellChainNode const* GetSpellChainNode(uint32 spell_id) const
{
SpellChainMap::const_iterator itr = mSpellChains.find(spell_id);
- if (itr == mSpellChains.end())
+ if(itr == mSpellChains.end())
return NULL;
return &itr->second;
@@ -1009,7 +1009,7 @@ class SpellMgr
{
SpellLearnSpellMapBounds bounds = GetSpellLearnSpellMapBounds(spell_id1);
for (SpellLearnSpellMap::const_iterator i = bounds.first; i != bounds.second; ++i)
- if (i->second.spell == spell_id2)
+ if (i->second.spell==spell_id2)
return true;
return false;
}
@@ -1191,4 +1191,3 @@ class SpellMgr
#define spellmgr SpellMgr::Instance()
#endif
-
diff --git a/src/game/StatSystem.cpp b/src/game/StatSystem.cpp
index ef7edc71cc8..3f4f9200e05 100644
--- a/src/game/StatSystem.cpp
+++ b/src/game/StatSystem.cpp
@@ -242,7 +242,7 @@ void Player::UpdateMaxPower(Powers power)
{
UnitMods unitMod = UnitMods(UNIT_MOD_POWER_START + power);
- float bonusPower = (power == POWER_MANA) ? GetManaBonusFromIntellect() : 0;
+ float bonusPower = (power == POWER_MANA && GetCreatePowers(power) > 0) ? GetManaBonusFromIntellect() : 0;
float value = GetModifierValue(unitMod, BASE_VALUE) + GetCreatePowers(power);
value *= GetModifierValue(unitMod, BASE_PCT);
@@ -694,6 +694,11 @@ void Player::ApplyManaRegenBonus(int32 amount, bool apply)
UpdateManaRegen();
}
+void Player::ApplyHealthRegenBonus(int32 amount, bool apply)
+{
+ m_baseHealthRegen+= apply ? amount : -amount;
+}
+
void Player::UpdateManaRegen()
{
float Intellect = GetStat(STAT_INTELLECT);
@@ -918,9 +923,9 @@ bool Guardian::UpdateStats(Stats stat)
Unit *owner = GetOwner();
// Handle Death Knight Glyphs and Talents
+ float mod = 0.75f;
if (IsPetGhoul() && (stat == STAT_STAMINA || stat == STAT_STRENGTH))
{
- float mod = 0.0f;
switch (stat)
{
case STAT_STAMINA: mod = 0.3f; break; // Default Owner's Stamina scale
@@ -945,7 +950,24 @@ bool Guardian::UpdateStats(Stats stat)
if (owner->getClass() == CLASS_WARLOCK && isPet())
value += float(owner->GetStat(STAT_STAMINA)) * 0.75f;
else
- value += float(owner->GetStat(stat)) * 0.3f;
+ {
+ mod = 0.3f;
+ if (((Creature*)this)->isPet())
+ {
+ PetSpellMap::const_iterator itr = (((Pet*)this)->m_spells.find(62758)); //Wild Hunt rank1
+ if (itr == ((Pet*)this)->m_spells.end())
+ {
+ itr = ((Pet*)this)->m_spells.find(62762); //Wild Hunt rank2
+ }
+ if (itr != ((Pet*)this)->m_spells.end()) // If pet has Wild Hunt
+ {
+
+ SpellEntry const* sProto = sSpellStore.LookupEntry(itr->first); // Then get the SpellProto and add the dummy effect value
+ mod += mod * (sProto->EffectBasePoints[0] / 100.0f);
+ }
+ }
+ value += float(owner->GetStat(stat)) * mod;
+ }
}
//warlock's and mage's pets gain 30% of owner's intellect
else if (stat == STAT_INTELLECT)
@@ -1095,8 +1117,23 @@ void Guardian::UpdateAttackPowerAndDamage(bool ranged)
{
if(isHunterPet()) //hunter pets benefit from owner's attack power
{
- bonusAP = owner->GetTotalAttackPowerValue(RANGED_ATTACK) * 0.22f;
- SetBonusDamage( int32(owner->GetTotalAttackPowerValue(RANGED_ATTACK) * 0.1287f));
+ float mod = 1.0f; //Hunter contribution modifier
+ if (((Creature*)this)->isPet())
+ {
+ PetSpellMap::const_iterator itr = ((Pet*)this)->m_spells.find(62758); //Wild Hunt rank1
+ if (itr == ((Pet*)this)->m_spells.end())
+ {
+ itr = ((Pet*)this)->m_spells.find(62762); //Wild Hunt rank2
+ }
+ if (itr != ((Pet*)this)->m_spells.end()) // If pet has Wild Hunt
+ {
+
+ SpellEntry const* sProto = sSpellStore.LookupEntry(itr->first); // Then get the SpellProto and add the dummy effect value
+ mod += (sProto->EffectBasePoints[1] / 100.0f);
+ }
+ }
+ bonusAP = owner->GetTotalAttackPowerValue(RANGED_ATTACK) * 0.22f * mod;
+ SetBonusDamage( int32(owner->GetTotalAttackPowerValue(RANGED_ATTACK) * 0.1287f * mod));
}
else if (IsPetGhoul()) //ghouls benefit from deathknight's attack power (may be summon pet or not)
{
@@ -1220,4 +1257,3 @@ void Guardian::UpdateDamagePhysical(WeaponAttackType attType)
SetStatFloatValue(UNIT_FIELD_MINDAMAGE, mindamage);
SetStatFloatValue(UNIT_FIELD_MAXDAMAGE, maxdamage);
}
-
diff --git a/src/game/TaxiHandler.cpp b/src/game/TaxiHandler.cpp
index a1f0bedf329..e0a1c2512a8 100644
--- a/src/game/TaxiHandler.cpp
+++ b/src/game/TaxiHandler.cpp
@@ -162,9 +162,9 @@ void WorldSession::HandleActivateTaxiExpressOpcode ( WorldPacket & recv_data )
sLog.outDebug( "WORLD: Received CMSG_ACTIVATETAXIEXPRESS" );
uint64 guid;
- uint32 node_count, _totalcost;
+ uint32 node_count;
- recv_data >> guid >> _totalcost >> node_count;
+ recv_data >> guid >> node_count;
Creature *npc = GetPlayer()->GetNPCIfCanInteractWith(guid, UNIT_NPC_FLAG_FLIGHTMASTER);
if (!npc)
@@ -197,6 +197,7 @@ void WorldSession::HandleMoveSplineDoneOpcode(WorldPacket& /*recv_data*/)
// 1) end taxi path in far (multi-node) flight
// 2) switch from one map to other in case multim-map taxi path
// we need process only (1)
+
uint32 curDest = GetPlayer()->m_taxi.GetTaxiDestination();
if(!curDest)
return;
@@ -275,4 +276,3 @@ void WorldSession::HandleActivateTaxiOpcode( WorldPacket & recv_data )
GetPlayer()->ActivateTaxiPathTo(nodes, npc);
}
-
diff --git a/src/game/Totem.cpp b/src/game/Totem.cpp
index c7ea9b1f123..a82f273bdbc 100644
--- a/src/game/Totem.cpp
+++ b/src/game/Totem.cpp
@@ -99,10 +99,6 @@ void Totem::InitStats(uint32 duration)
void Totem::InitSummon()
{
- WorldPacket data(SMSG_GAMEOBJECT_SPAWN_ANIM_OBSOLETE, 8);
- data << GetGUID();
- SendMessageToSet(&data, true);
-
if(m_type == TOTEM_PASSIVE)
CastSpell(this, GetSpell(), true);
@@ -113,8 +109,6 @@ void Totem::InitSummon()
void Totem::UnSummon()
{
- SendObjectDeSpawnAnim(GetGUID());
-
CombatStop();
RemoveAurasDueToSpell(GetSpell());
@@ -134,6 +128,7 @@ void Totem::UnSummon()
Group *pGroup = NULL;
if (m_owner->GetTypeId() == TYPEID_PLAYER)
{
+ ((Player*)m_owner)->SendAutoRepeatCancel(this);
// Not only the player can summon the totem (scripted AI)
pGroup = ((Player*)m_owner)->GetGroup();
if (pGroup)
diff --git a/src/game/Unit.cpp b/src/game/Unit.cpp
index 90836cd23ea..457439e3d08 100644
--- a/src/game/Unit.cpp
+++ b/src/game/Unit.cpp
@@ -926,7 +926,7 @@ void Unit::CastStop(uint32 except_spellid)
void Unit::CastSpell(Unit* Victim, uint32 spellId, bool triggered, Item *castItem, AuraEffect* triggeredByAura, uint64 originalCaster)
{
- SpellEntry const *spellInfo = sSpellStore.LookupEntry(spellId);
+ SpellEntry const *spellInfo = sSpellStore.LookupEntry(spellId );
if (!spellInfo)
{
@@ -934,10 +934,10 @@ void Unit::CastSpell(Unit* Victim, uint32 spellId, bool triggered, Item *castIte
return;
}
- CastSpell(Victim, spellInfo, triggered, castItem, triggeredByAura, originalCaster);
+ CastSpell(Victim,spellInfo,triggered,castItem,triggeredByAura, originalCaster);
}
-void Unit::CastSpell(Unit* Victim, SpellEntry const *spellInfo, bool triggered, Item *castItem, AuraEffect* triggeredByAura, uint64 originalCaster)
+void Unit::CastSpell(Unit* Victim,SpellEntry const *spellInfo, bool triggered, Item *castItem, AuraEffect* triggeredByAura, uint64 originalCaster)
{
if (!spellInfo)
{
@@ -1241,6 +1241,9 @@ void Unit::CalculateSpellDamageTaken(SpellNonMeleeDamage *damageInfo, int32 dama
if (damageSchoolMask & SPELL_SCHOOL_MASK_NORMAL)
damage = CalcArmorReducedDamage(pVictim, damage, spellInfo, attackType);
+ if (GetTypeId() == TYPEID_PLAYER && pVictim->GetTypeId() == TYPEID_PLAYER)
+ damage -= ((Player*)pVictim)->GetSpellDamageReduction(damage);
+
// Calculate absorb resist
if (damage > 0)
{
@@ -1488,6 +1491,14 @@ void Unit::CalculateMeleeDamage(Unit *pVictim, uint32 damage, CalcDamageInfo *da
break;
}
+ if (GetTypeId() == TYPEID_PLAYER && pVictim->GetTypeId() == TYPEID_PLAYER)
+ {
+ if (attackType != RANGED_ATTACK)
+ damage-=((Player*)pVictim)->GetMeleeDamageReduction(damage);
+ else
+ damage-=((Player*)pVictim)->GetRangedDamageReduction(damage);
+ }
+
// Calculate absorb resist
if (int32(damageInfo->damage) > 0)
{
@@ -1749,34 +1760,53 @@ void Unit::CalcAbsorbResist(Unit *pVictim, SpellSchoolMask schoolMask, DamageEff
// Magic damage, check for resists
if ((schoolMask & SPELL_SCHOOL_MASK_NORMAL) == 0)
{
- // Get base victim resistance for school
- float tmpvalue2 = (float)pVictim->GetResistance(GetFirstSchoolInMask(schoolMask));
- // Ignore resistance by self SPELL_AURA_MOD_TARGET_RESISTANCE aura
- tmpvalue2 += (float)GetTotalAuraModifierByMiscMask(SPELL_AURA_MOD_TARGET_RESISTANCE, schoolMask);
-
- tmpvalue2 *= (float)(0.15f / getLevel());
- if (tmpvalue2 < 0.0f)
- tmpvalue2 = 0.0f;
- if (tmpvalue2 > 0.75f)
- tmpvalue2 = 0.75f;
- uint32 ran = urand(0, 100);
- uint32 faq[4] = {24,6,4,6};
- uint8 m = 0;
- float Binom = 0.0f;
- for (uint8 i = 0; i < 4; ++i)
- {
- Binom += 2400 *( powf(tmpvalue2, i) * powf( (1-tmpvalue2), (4-i)))/faq[i];
- if (ran > Binom)
- ++m;
- else
- break;
+ float baseVictimResistance = (float) pVictim->GetResistance(GetFirstSchoolInMask(schoolMask));
+ float ignoredResistance = (float) GetTotalAuraModifierByMiscMask(SPELL_AURA_MOD_TARGET_RESISTANCE, schoolMask);
+ float victimResistance = baseVictimResistance + ignoredResistance;
+
+ uint32 BOSS_LEVEL = 83;
+ float BOSS_RESISTANCE_CONSTANT = 510.0;
+ uint32 level = getLevel();
+ float resistanceConstant = 0.0f;
+
+ if (level == BOSS_LEVEL)
+ {
+ resistanceConstant = BOSS_RESISTANCE_CONSTANT;
}
- if (damagetype == DOT && m == 4)
- *resist += uint32(damage - 1);
else
- *resist += uint32(damage * m / 4);
- if (*resist > damage)
- *resist = damage;
+ {
+ resistanceConstant = level * 5.0f;
+ }
+
+ float averageResist = victimResistance / (victimResistance + resistanceConstant);
+ float discreteResistProbability[11];
+ for (int i = 0; i < 11; i++)
+ {
+ discreteResistProbability[i] = 0.5f - 2.5f * abs(0.1f * i - averageResist);
+ if (discreteResistProbability[i] < 0.0f)
+ {
+ discreteResistProbability[i] = 0.0f;
+ }
+ }
+
+ if (averageResist <= 0.1f)
+ {
+ discreteResistProbability[0] = 1.0f - 7.5f * averageResist;
+ discreteResistProbability[1] = 5.0f * averageResist;
+ discreteResistProbability[2] = 2.5f * averageResist;
+ }
+
+ float r = rand_norm();
+ int i = 0;
+ float probabilitySum = discreteResistProbability[0];
+ while (r >= probabilitySum && i < 10)
+ {
+ i++;
+ probabilitySum += discreteResistProbability[i];
+ }
+ uint32 damageResisted = damage * i / 10;
+
+ *resist += damageResisted;
AuraEffectList const &ResIgnoreAurasAb = GetAurasByType(SPELL_AURA_MOD_ABILITY_IGNORE_TARGET_RESIST);
for (AuraEffectList::const_iterator j = ResIgnoreAurasAb.begin(); j != ResIgnoreAurasAb.end(); ++j)
@@ -1924,6 +1954,13 @@ void Unit::CalcAbsorbResist(Unit *pVictim, SpellSchoolMask schoolMask, DamageEff
Unit* caster = (*i)->GetCaster();
if (!caster)
break;
+ // Glyph of Power Word: Shield
+ if (Aura *glyph = pVictim->GetAura(55672,0))
+ {
+ int32 heal = int32(glyph->GetPartAura(0)->GetAmount() *
+ (RemainingDamage >= currentAbsorb ? currentAbsorb : RemainingDamage) / 100);
+ pVictim->CastCustomSpell(pVictim, 56160, &heal, NULL, NULL, true, 0, *i);
+ }
// Reflective Shield
if (AuraEffect const * aurEff = caster->GetDummyAura(SPELLFAMILY_PRIEST, 566, 0))
{
@@ -4478,9 +4515,7 @@ GameObject* Unit::GetGameObject(uint32 spellId) const
void Unit::AddGameObject(GameObject* gameObj)
{
- if(!gameObj || !gameObj->GetOwnerGUID()==0)
- return;
-
+ if(!gameObj || !gameObj->GetOwnerGUID()==0) return;
m_gameObj.push_back(gameObj);
gameObj->SetOwnerGUID(GetGUID());
@@ -4496,8 +4531,7 @@ void Unit::AddGameObject(GameObject* gameObj)
void Unit::RemoveGameObject(GameObject* gameObj, bool del)
{
- if(!gameObj || !gameObj->GetOwnerGUID()==GetGUID())
- return;
+ if(!gameObj || !gameObj->GetOwnerGUID()==GetGUID()) return;
gameObj->SetOwnerGUID(0);
@@ -4892,8 +4926,6 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, AuraEffect* trigger
uint32 triggered_spell_id = 0;
Unit* target = pVictim;
int32 basepoints0 = 0;
- int32 basepoints1 = 0;
- int32 basepoints2 = 0;
uint64 originalCaster = 0;
// Master of subtlety (checked here because ranks have different spellfamilynames)
@@ -4982,6 +5014,17 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, AuraEffect* trigger
triggered_spell_id = 58374;
break;
}
+ // Glyph of Devastate
+ if (dummySpell->Id == 58388)
+ {
+ if (!pVictim || !pVictim->isAlive())
+ return false;
+
+ if (Aura* aur = pVictim->GetAura(58567,0))
+ aur->modStackAmount(1);
+
+ return true;
+ }
// Unstable Power
case 24658:
{
@@ -5286,12 +5329,22 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, AuraEffect* trigger
target = this;
break;
}
+ // Shadowfiend Death (Gain mana if pet dies with Glyph of Shadowfiend)
+ case 57989:
+ {
+ Unit *owner = GetOwner();
+ if (!owner || owner->GetTypeId() != TYPEID_PLAYER)
+ return false;
+ // Glyph of Shadowfiend (need cast as self cast for owner, no hidden cooldown)
+ owner->CastSpell(owner,58227,true,castItem,triggeredByAura);
+ return true;
+ }
// Divine purpose
case 31871:
case 31872:
{
// Roll chane
- if (!roll_chance_i(triggerAmount))
+ if (!pVictim || !pVictim->isAlive() || !roll_chance_i(triggerAmount))
return false;
// Remove any stun effect on target
@@ -5324,7 +5377,7 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, AuraEffect* trigger
// mana cost save
int32 cost = procSpell->manaCost + procSpell->ManaCostPercentage * GetCreateMana() / 100;
basepoints0 = cost * triggerAmount/100;
- if (basepoints0 <= 0)
+ if( basepoints0 <=0 )
return false;
target = this;
@@ -5414,6 +5467,12 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, AuraEffect* trigger
target->RemoveAurasByType(SPELL_AURA_PERIODIC_DAMAGE_PERCENT);
return true;
}
+ // Glyph of Drain Soul
+ case 58070:
+ {
+ triggered_spell_id = 58068;
+ break;
+ }
// Glyph of Icy Veins
case 56374:
{
@@ -5453,7 +5512,7 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, AuraEffect* trigger
return true; // charge counting (will removed)
}
- CastSpell(this, 28682, true, castItem, triggeredByAura);
+ CastSpell(this, 11129, true, castItem, triggeredByAura);
return (procEx & PROC_EX_CRITICAL_HIT);// charge update only at crit hits, no hidden cooldowns
}
// Glyph of Ice Block
@@ -5523,9 +5582,9 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, AuraEffect* trigger
switch (dummySpell->Id)
{
- case 29838: triggered_spell_id = 29842; break;
- case 29834: triggered_spell_id = 29841; break;
- case 42770: triggered_spell_id = 42771; break;
+ case 29838: triggered_spell_id=29842; break;
+ case 29834: triggered_spell_id=29841; break;
+ case 42770: triggered_spell_id=42771; break;
default:
sLog.outError("Unit::HandleDummyAuraProc: non handled spell id: %u (SW)",dummySpell->Id);
return false;
@@ -5549,10 +5608,10 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, AuraEffect* trigger
// Seed of Corruption
if (dummySpell->SpellFamilyFlags[1] & 0x00000010)
{
- if (procSpell && procSpell->Id == 27285)
+ if(procSpell && procSpell->Id == 27285)
return false;
// if damage is more than need or target die from damage deal finish spell
- if (triggeredByAura->GetAmount() <= damage || GetHealth() <= damage)
+ if( triggeredByAura->GetAmount() <= damage || GetHealth() <= damage )
{
// remember guid before aura delete
uint64 casterGuid = triggeredByAura->GetCasterGUID();
@@ -5561,7 +5620,7 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, AuraEffect* trigger
RemoveAurasDueToSpell(triggeredByAura->GetId());
// Cast finish spell (triggeredByAura already not exist!)
- if (Unit *caster = GetUnit(*this, casterGuid))
+ if(Unit* caster = GetUnit(*this, casterGuid))
caster->CastSpell(this, 27285, true, castItem);
return true; // no hidden cooldown
}
@@ -5574,7 +5633,7 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, AuraEffect* trigger
if (dummySpell->SpellFamilyFlags.IsEqual(0,0,0) && dummySpell->SpellIconID == 1932)
{
// if damage is more than need deal finish spell
- if (triggeredByAura->GetAmount() <= damage)
+ if( triggeredByAura->GetAmount() <= damage )
{
// remember guid before aura delete
uint64 casterGuid = triggeredByAura->GetCasterGUID();
@@ -5583,7 +5642,7 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, AuraEffect* trigger
RemoveAurasDueToSpell(triggeredByAura->GetId());
// Cast finish spell (triggeredByAura already not exist!)
- if (Unit *caster = GetUnit(*this, casterGuid))
+ if(Unit* caster = GetUnit(*this, casterGuid))
caster->CastSpell(this, 32865, true, castItem);
return true; // no hidden cooldown
}
@@ -5726,7 +5785,7 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, AuraEffect* trigger
if(!pVictim || !pVictim->isAlive())
return false;
- if (effIndex != 0)
+ if (effIndex!=0)
return false;
// pVictim is caster of aura
@@ -5744,6 +5803,16 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, AuraEffect* trigger
triggered_spell_id = 47753;
break;
}
+ // Body and Soul
+ if (dummySpell->SpellIconID == 2218)
+ {
+ // Proc only from Abolish desease on self cast
+ if (procSpell->Id != 552 || pVictim != this || !roll_chance_i(triggerAmount))
+ return false;
+ triggered_spell_id = 64136;
+ target = this;
+ break;
+ }
switch(dummySpell->Id)
{
// Vampiric Embrace
@@ -5767,6 +5836,9 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, AuraEffect* trigger
case 15272:
case 15320:
{
+ if (!target)
+ return false;
+
basepoints0 = triggerAmount * target->GetCreateMana() / 100;
triggered_spell_id = 64103;
break;
@@ -5775,10 +5847,10 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, AuraEffect* trigger
case 40438:
{
// Shadow Word: Pain
- if (procSpell->SpellFamilyFlags[0] & 0x8000)
+ if( procSpell->SpellFamilyFlags[0] & 0x8000 )
triggered_spell_id = 40441;
// Renew
- else if (procSpell->SpellFamilyFlags[0] & 0x40)
+ else if( procSpell->SpellFamilyFlags[0] & 0x40 )
triggered_spell_id = 40440;
else
return false;
@@ -5796,7 +5868,7 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, AuraEffect* trigger
return false;
int EffIndex = 0;
- for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i)
+ for (uint8 i = 0; i < MAX_SPELL_EFFECTS; i++)
{
if(GoPoH->Effect[i] == SPELL_EFFECT_APPLY_AURA)
{
@@ -5805,7 +5877,7 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, AuraEffect* trigger
}
}
int32 tickcount = GetSpellMaxDuration(GoPoH) / GoPoH->EffectAmplitude[EffIndex];
- if (!tickcount)
+ if(!tickcount)
return false;
basepoints0 = damage * triggerAmount / tickcount / 100;
@@ -5864,7 +5936,7 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, AuraEffect* trigger
// Dispel Magic shares spellfamilyflag with abolish disease
if (procSpell->SpellIconID != 74)
return false;
- if(!target->IsFriendlyTo(this))
+ if(!target || !target->IsFriendlyTo(this))
return false;
basepoints0 = int32(target->GetMaxHealth() * triggerAmount / 100);
@@ -5883,7 +5955,7 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, AuraEffect* trigger
// Frozen Shadoweave (Shadow's Embrace set) warning! its not only priest set
case 39372:
{
- if (!procSpell || (GetSpellSchoolMask(procSpell) & (SPELL_SCHOOL_MASK_FROST | SPELL_SCHOOL_MASK_SHADOW)) == 0)
+ if(!procSpell || (GetSpellSchoolMask(procSpell) & (SPELL_SCHOOL_MASK_FROST | SPELL_SCHOOL_MASK_SHADOW))==0 )
return false;
// heal amount
@@ -5912,7 +5984,7 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, AuraEffect* trigger
}
case SPELLFAMILY_DRUID:
{
- switch (dummySpell->Id)
+ switch(dummySpell->Id)
{
// Glyph of Innervate
case 54832:
@@ -5968,11 +6040,11 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, AuraEffect* trigger
triggered_spell_id = 34299;
if (triggeredByAura->GetCasterGUID() != GetGUID())
break;
- int32 _basepoints0 = triggerAmount * 2;
+ int32 basepoints1 = triggerAmount * 2;
// Improved Leader of the Pack
// Check cooldown of heal spell cooldown
if (GetTypeId() == TYPEID_PLAYER && !((Player *)this)->HasSpellCooldown(34299))
- CastCustomSpell(this, 60889, &_basepoints0, NULL, NULL, true, 0, triggeredByAura);
+ CastCustomSpell(this,60889,&basepoints1,0,0,true,0,triggeredByAura);
break;
}
// Healing Touch (Dreamwalker Raiment set)
@@ -6054,7 +6126,7 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, AuraEffect* trigger
if (!procSpell)
return false;
// Only 0 aura can proc
- if (effIndex != 0)
+ if (effIndex!=0)
return false;
// Wrath crit
if (procSpell->SpellFamilyFlags[0] & 0x1)
@@ -6087,7 +6159,7 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, AuraEffect* trigger
else if (dummySpell->SpellIconID == 2850)
{
// Effect 0 - mod damage while having Enrage
- if (effIndex == 0)
+ if (effIndex==0)
{
if (!(procSpell->SpellFamilyFlags[0] & 0x00080000))
return false;
@@ -6097,7 +6169,7 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, AuraEffect* trigger
break;
}
// Effect 1 - Tiger's Fury restore energy
- else if (effIndex == 1)
+ else if (effIndex==1)
{
if (!(procSpell->SpellFamilyFlags[2] & 0x00000800))
return false;
@@ -6111,7 +6183,7 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, AuraEffect* trigger
}
case SPELLFAMILY_ROGUE:
{
- switch (dummySpell->Id)
+ switch(dummySpell->Id)
{
// Glyph of Backstab
case 56800:
@@ -6227,7 +6299,7 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, AuraEffect* trigger
// Seal of Righteousness - melee proc dummy (addition ${$MWS*(0.022*$AP+0.044*$SPH)} damage)
if (dummySpell->SpellFamilyFlags[0]&0x8000000)
{
- if (effIndex != 0)
+ if (effIndex!=0)
return false;
triggered_spell_id = 25742;
float ap = GetTotalAttackPowerValue(BASE_ATTACK);
@@ -6237,7 +6309,7 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, AuraEffect* trigger
break;
}
// Light's Beacon - Beacon of Light
- if (dummySpell->Id == 53651)
+ if ( dummySpell->Id == 53651 )
{
if (Unit *source = triggeredByAura->GetParentAura()->GetUnitSource())
{
@@ -6275,8 +6347,8 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, AuraEffect* trigger
triggered_spell_id = 57318;
target = this;
basepoints0 = triggerAmount;
- basepoints1 = triggerAmount;
- break;
+ CastCustomSpell(target,triggered_spell_id,&basepoints0,&basepoints0,NULL,true,castItem,triggeredByAura);
+ return true;
}
// Sacred Shield
if (dummySpell->SpellFamilyFlags[1]&0x00080000)
@@ -6316,13 +6388,18 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, AuraEffect* trigger
// Judgement of Light
case 20185:
{
- pVictim->CastCustomSpell(pVictim, 20267, &basepoints0, 0, 0, true, 0, triggeredByAura);
- return true;
+ if (pVictim->getPowerType() == POWER_MANA)
+ {
+ // 2% of base mana
+ basepoints0 = int32(pVictim->GetMaxHealth() * 2 / 100);
+ pVictim->CastCustomSpell(pVictim, 20267, &basepoints0, 0, 0, true, 0, triggeredByAura);
+ }
+ return true;
}
// Judgement of Wisdom
case 20186:
{
- if (pVictim->getPowerType() == POWER_MANA)
+ if (pVictim && pVictim->isAlive() && pVictim->getPowerType() == POWER_MANA)
{
// 2% of base mana
basepoints0 = int32(pVictim->GetCreateMana() * 2 / 100);
@@ -6361,6 +6438,20 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, AuraEffect* trigger
}
break;
}
+ case 25899: // Greater Blessing of Sanctuary
+ case 20911: // Blessing of Sanctuary
+ {
+ target = this;
+ switch (target->getPowerType())
+ {
+ case POWER_MANA:
+ triggered_spell_id = 57319;
+ break;
+ default:
+ return false;
+ }
+ break;
+ }
// Seal of Vengeance (damage calc on apply aura)
case 31801:
{
@@ -6384,51 +6475,33 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, AuraEffect* trigger
case 33776:
{
// if healed by another unit (pVictim)
- if (this == pVictim)
+ if(this == pVictim)
return false;
// heal amount
basepoints0 = triggerAmount*damage/100;
target = this;
- if (basepoints0)
+ if(basepoints0)
triggered_spell_id = 31786;
break;
}
- // Seal of Blood do damage trigger
- case 31892:
- {
- if (effIndex == 0 && procFlag & PROC_FLAG_SUCCESSFUL_MELEE_HIT) // 0 effect - is proc on enemy
- triggered_spell_id = 31893;
- else
- return true;
- break;
- }
- // Seal of the Martyr do damage trigger
- case 53720:
- {
- if (effIndex == 0 && procFlag & PROC_FLAG_SUCCESSFUL_MELEE_HIT) // 0 effect - is proc on enemy
- triggered_spell_id = 53719;
- else
- return true;
- break;
- }
// Paladin Tier 6 Trinket (Ashtongue Talisman of Zeal)
case 40470:
{
- if (!procSpell)
+ if( !procSpell )
return false;
float chance;
// Flash of light/Holy light
- if (procSpell->SpellFamilyFlags[0] & 0xC0000000)
+ if( procSpell->SpellFamilyFlags[0] & 0xC0000000)
{
triggered_spell_id = 40471;
chance = 15.0f;
}
// Judgement (any)
- else if (GetSpellSpecific(procSpell->Id) == SPELL_JUDGEMENT)
+ else if (GetSpellSpecific(procSpell->Id)==SPELL_JUDGEMENT)
{
triggered_spell_id = 40472;
chance = 50.0f;
@@ -6445,15 +6518,14 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, AuraEffect* trigger
case 54939:
{
// Lookup base amount mana restore
- for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i)
+ for (uint8 i=0; i<MAX_SPELL_EFFECTS; i++)
if (procSpell->Effect[i] == SPELL_EFFECT_ENERGIZE)
{
- basepoints1 = procSpell->EffectBasePoints[i]; // Not sure if this is right, maybe basepoints0?
- triggered_spell_id = 54986;
- target = this;
+ int32 mana = procSpell->EffectBasePoints[i];
+ CastCustomSpell(this, 54986, 0, &mana, 0, true, castItem, triggeredByAura);
break;
}
- break;
+ return true;
}
// Glyph of Flash of Light
case 54936:
@@ -6494,7 +6566,7 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, AuraEffect* trigger
// Totemic Power (The Earthshatterer set)
case 28823:
{
- if (!pVictim)
+ if( !pVictim )
return false;
// Set class defined buff
@@ -6532,17 +6604,32 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, AuraEffect* trigger
// Windfury Weapon (Passive) 1-5 Ranks
case 33757:
{
- if (GetTypeId() != TYPEID_PLAYER)
+ if(GetTypeId()!=TYPEID_PLAYER || !castItem || !castItem->IsEquipped() || !pVictim || !pVictim->isAlive())
return false;
- if (!castItem || !castItem->IsEquipped())
+ // custom cooldown processing case
+ if( cooldown && ((Player*)this)->HasSpellCooldown(dummySpell->Id))
return false;
- // custom cooldown processing case
- if (cooldown && ((Player*)this)->HasSpellCooldown(dummySpell->Id))
+ if(triggeredByAura->GetParentAura() && castItem->GetGUID() != triggeredByAura->GetParentAura()->GetCastItemGUID())
return false;
- if (triggeredByAura->GetParentAura() && castItem->GetGUID() != triggeredByAura->GetParentAura()->GetCastItemGUID())
+ WeaponAttackType attType = WeaponAttackType(((Player*)this)->GetAttackBySlot(castItem->GetSlot()));
+ if ((attType != BASE_ATTACK && attType != OFF_ATTACK) || !isAttackReady(attType))
+ return false;
+
+ // Now compute real proc chance...
+ Aura* aur = GetAura(55445, 0);
+ uint32 chance = 20/* + (aur ? aur->GetAmount()->m_amount : 0)*/;
+ ((Player*)this)->ApplySpellMod(dummySpell->Id,SPELLMOD_CHANCE_OF_SUCCESS,chance);
+
+ Item* addWeapon = ((Player*)this)->GetWeaponForAttack(attType == BASE_ATTACK ? OFF_ATTACK : BASE_ATTACK, true);
+ uint32 enchant_id_add = addWeapon ? addWeapon->GetEnchantmentId(EnchantmentSlot(TEMP_ENCHANTMENT_SLOT)) : 0;
+ SpellItemEnchantmentEntry const *pEnchant = sSpellItemEnchantmentStore.LookupEntry(enchant_id_add);
+ if (pEnchant && pEnchant->spellid[0] == dummySpell->Id)
+ chance += 14;
+
+ if (!roll_chance_i(chance))
return false;
// Now amount of extra power stored in 1 effect of Enchant spell
@@ -6575,30 +6662,17 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, AuraEffect* trigger
int32 extra_attack_power = CalculateSpellDamage(windfurySpellEntry, 1, windfurySpellEntry->EffectBasePoints[1], pVictim);
- // Main-Hand case
- if (castItem->GetSlot() == EQUIPMENT_SLOT_MAINHAND && isAttackReady(BASE_ATTACK))
- {
- // Value gained from additional AP
- basepoints0 = int32(extra_attack_power/14.0f * GetAttackTime(BASE_ATTACK)/1000);
- triggered_spell_id = 25504;
- }
- // Off-Hand case
- else if (castItem->GetSlot() == EQUIPMENT_SLOT_OFFHAND && isAttackReady(OFF_ATTACK))
- {
- // Value gained from additional AP
- basepoints0 = int32(extra_attack_power/14.0f * GetAttackTime(OFF_ATTACK)/1000/2);
- triggered_spell_id = 33750;
- }
- else
- return false;
+ // Value gained from additional AP
+ basepoints0 = int32(extra_attack_power/14.0f * GetAttackTime(BASE_ATTACK)/1000);
+ triggered_spell_id = 25504;
// apply cooldown before cast to prevent processing itself
- if (cooldown)
- ((Player*)this)->AddSpellCooldown(dummySpell->Id, 0, time(NULL) + cooldown);
+ if( cooldown )
+ ((Player*)this)->AddSpellCooldown(dummySpell->Id,0,time(NULL) + cooldown);
// Attack Twice
- for (uint8 i = 0; i < 2; ++i)
- CastCustomSpell(pVictim, triggered_spell_id, &basepoints0, NULL, NULL, true, castItem, triggeredByAura);
+ for (uint32 i = 0; i<2; ++i )
+ CastCustomSpell(pVictim,triggered_spell_id,&basepoints0,NULL,NULL,true,castItem,triggeredByAura);
return true;
}
@@ -6658,7 +6732,7 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, AuraEffect* trigger
// Shaman T8 Elemental 4P Bonus
case 64928:
{
- basepoints0 = triggerAmount * damage / 100;
+ basepoints0 = int32( triggerAmount * damage / 100 );
triggered_spell_id = 64930; // Electrified
break;
}
@@ -6666,7 +6740,7 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, AuraEffect* trigger
// Frozen Power
if (dummySpell->SpellIconID == 3780)
{
- if (GetDistance(target) < 15.0f)
+ if (this->GetDistance(target) < 15.0f)
return false;
float chance = triggerAmount;
if (!roll_chance_f(chance))
@@ -6698,7 +6772,7 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, AuraEffect* trigger
break;
}
// Earth Shield
- if (dummySpell->SpellFamilyFlags[1] & 0x00000400)
+ if(dummySpell->SpellFamilyFlags[1] & 0x00000400)
{
// 3.0.8: Now correctly uses the Shaman's own spell critical strike chance to determine the chance of a critical heal.
originalCaster = triggeredByAura->GetCasterGUID();
@@ -6717,10 +6791,7 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, AuraEffect* trigger
// Flametongue Weapon (Passive)
if (dummySpell->SpellFamilyFlags[0] & 0x200000)
{
- if(GetTypeId() != TYPEID_PLAYER)
- return false;
-
- if(!castItem || !castItem->IsEquipped())
+ if(GetTypeId()!=TYPEID_PLAYER || !pVictim || !pVictim->isAlive() || !castItem || !castItem->IsEquipped())
return false;
// firehit = dummySpell->EffectBasePoints[0] / ((4*19.25) * 1.3);
@@ -6738,24 +6809,26 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, AuraEffect* trigger
float BaseWeaponSpeed = GetAttackTime(OFF_ATTACK)/1000.0;
// Value1: add the tooltip damage by swingspeed + Value2: add spelldmg by swingspeed
- basepoints0 = int32((fire_onhit * BaseWeaponSpeed) + (add_spellpower * BaseWeaponSpeed));
+ basepoints0 = int32( (fire_onhit * BaseWeaponSpeed) + (add_spellpower * BaseWeaponSpeed) );
triggered_spell_id = 10444;
}
+
// Enchant on Main-Hand and ready?
- else if (castItem->GetSlot() == EQUIPMENT_SLOT_MAINHAND && isAttackReady(BASE_ATTACK))
+ else if ( castItem->GetSlot() == EQUIPMENT_SLOT_MAINHAND && isAttackReady(BASE_ATTACK))
{
float BaseWeaponSpeed = GetAttackTime(BASE_ATTACK)/1000.0;
// Value1: add the tooltip damage by swingspeed + Value2: add spelldmg by swingspeed
- basepoints0 = int32((fire_onhit * BaseWeaponSpeed) + (add_spellpower * BaseWeaponSpeed));
+ basepoints0 = int32( (fire_onhit * BaseWeaponSpeed) + (add_spellpower * BaseWeaponSpeed) );
triggered_spell_id = 10444;
}
- // If not ready, we should return, shouldn't we?!
+
+ // If not ready, we should return, shouldn't we?!
else
return false;
- target = pVictim;
- break;
+ CastCustomSpell(pVictim,triggered_spell_id,&basepoints0,NULL,NULL,true,castItem,triggeredByAura);
+ return true;
}
// Improved Water Shield
if (dummySpell->SpellIconID == 2287)
@@ -6776,34 +6849,66 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, AuraEffect* trigger
// Lightning Overload
if (dummySpell->SpellIconID == 2018) // only this spell have SpellFamily Shaman SpellIconID == 2018 and dummy aura
{
- if(!procSpell || GetTypeId() != TYPEID_PLAYER || !pVictim)
+ if(!procSpell || GetTypeId() != TYPEID_PLAYER || !pVictim )
return false;
// custom cooldown processing case
- if (cooldown && GetTypeId() == TYPEID_PLAYER && ((Player*)this)->HasSpellCooldown(dummySpell->Id))
+ if( cooldown && GetTypeId() == TYPEID_PLAYER && ((Player*)this)->HasSpellCooldown(dummySpell->Id))
return false;
- uint32 spell;
- if (procSpell->SpellFamilyFlags[0] & 0x2)
- spell = 45297;
- else
- spell = 45284;
- uint32 spellId = spellmgr.GetSpellWithRank(spell, spellmgr.GetSpellRank(procSpell->Id));
+ uint32 spellId = 0;
+ // Every Lightning Bolt and Chain Lightning spell have duplicate vs half damage and zero cost
+ switch (procSpell->Id)
+ {
+ // Lightning Bolt
+ case 403: spellId = 45284; break; // Rank 1
+ case 529: spellId = 45286; break; // Rank 2
+ case 548: spellId = 45287; break; // Rank 3
+ case 915: spellId = 45288; break; // Rank 4
+ case 943: spellId = 45289; break; // Rank 5
+ case 6041: spellId = 45290; break; // Rank 6
+ case 10391: spellId = 45291; break; // Rank 7
+ case 10392: spellId = 45292; break; // Rank 8
+ case 15207: spellId = 45293; break; // Rank 9
+ case 15208: spellId = 45294; break; // Rank 10
+ case 25448: spellId = 45295; break; // Rank 11
+ case 25449: spellId = 45296; break; // Rank 12
+ case 49237: spellId = 49239; break; // Rank 13
+ case 49238: spellId = 49240; break; // Rank 14
+ // Chain Lightning
+ case 421: spellId = 45297; break; // Rank 1
+ case 930: spellId = 45298; break; // Rank 2
+ case 2860: spellId = 45299; break; // Rank 3
+ case 10605: spellId = 45300; break; // Rank 4
+ case 25439: spellId = 45301; break; // Rank 5
+ case 25442: spellId = 45302; break; // Rank 6
+ case 49270: spellId = 49268; break; // Rank 7
+ case 49271: spellId = 49269; break; // Rank 8
+ default:
+ sLog.outError("Unit::HandleDummyAuraProc: non handled spell id: %u (LO)", procSpell->Id);
+ return false;
+ }
+ // No thread generated mod
+ // TODO: exist special flag in spell attributes for this, need found and use!
+ SpellModifier *mod = new SpellModifier;
+ mod->op = SPELLMOD_THREAT;
+ mod->value = -100;
+ mod->type = SPELLMOD_PCT;
+ mod->spellId = dummySpell->Id;
+ mod->mask[0] = 0x02;
+ mod->mask[2] = 0x00;
+ ((Player*)this)->AddSpellMod(mod, true);
// Remove cooldown (Chain Lightning - have Category Recovery time)
if (procSpell->SpellFamilyFlags[0] & 0x2)
((Player*)this)->RemoveSpellCooldown(spellId);
- // do not reduce damage-spells have correct basepoints
- basepoints1 = 0;
-
- // Apply spellmod
- CastCustomSpell(this, 39805, NULL, &basepoints1, NULL, true, castItem, triggeredByAura);
-
CastSpell(pVictim, spellId, true, castItem, triggeredByAura);
- if (cooldown && GetTypeId() == TYPEID_PLAYER)
- ((Player*)this)->AddSpellCooldown(dummySpell->Id, 0, time(NULL) + cooldown);
+ ((Player*)this)->AddSpellMod(mod, false);
+
+ if( cooldown && GetTypeId() == TYPEID_PLAYER )
+ ((Player*)this)->AddSpellCooldown(dummySpell->Id,0,time(NULL) + cooldown);
return true;
}
@@ -6827,6 +6932,9 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, AuraEffect* trigger
// Blood-Caked Strike - Blood-Caked Blade
if (dummySpell->SpellIconID == 138)
{
+ if (!target || !target->isAlive())
+ return false;
+
triggered_spell_id = dummySpell->EffectTriggerSpell[effIndex];
break;
}
@@ -6850,7 +6958,7 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, AuraEffect* trigger
if (dummySpell->Id == 49028)
{
// 1 dummy aura for dismiss rune blade
- if (effIndex != 2)
+ if (effIndex!=2)
return false;
uint64 PetGUID = NULL;
for (ControlList::const_iterator itr = m_Controlled.begin(); itr != m_Controlled.end(); ++itr) //Find Rune Weapon
@@ -6891,6 +6999,62 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, AuraEffect* trigger
triggered_spell_id = 51460;
break;
}
+ // Threat of Thassarian
+ if (dummySpell->SpellIconID == 2023)
+ {
+ // Must Dual Wield
+ if (!procSpell || !haveOffhandWeapon())
+ return false;
+ // Chance as basepoints for dummy aura
+ if (!roll_chance_i(triggerAmount))
+ return false;
+
+ switch (procSpell->Id)
+ {
+ // Obliterate
+ case 49020: triggered_spell_id = 66198; break; // Rank 1
+ case 51423: triggered_spell_id = 66972; break; // Rank 2
+ case 51424: triggered_spell_id = 66973; break; // Rank 3
+ case 51425: triggered_spell_id = 66974; break; // Rank 4
+
+ // Frost Strike
+ case 49143: triggered_spell_id = 66196; break; // Rank 1
+ case 51416: triggered_spell_id = 66958; break; // Rank 2
+ case 51417: triggered_spell_id = 66959; break; // Rank 3
+ case 51418: triggered_spell_id = 66960; break; // Rank 4
+ case 51419: triggered_spell_id = 66961; break; // Rank 5
+ case 51420: triggered_spell_id = 66962; break; // Rank 6
+
+ // Plague Strike
+ case 45462: triggered_spell_id = 66216; break; // Rank 1
+ case 49917: triggered_spell_id = 66988; break; // Rank 2
+ case 49918: triggered_spell_id = 66989; break; // Rank 3
+ case 49919: triggered_spell_id = 66990; break; // Rank 4
+ case 49920: triggered_spell_id = 66991; break; // Rank 5
+ case 49921: triggered_spell_id = 66992; break; // Rank 6
+
+ // Death Strike
+ case 49998: triggered_spell_id = 66188; break; // Rank 1
+ case 49999: triggered_spell_id = 66950; break; // Rank 2
+ case 45463: triggered_spell_id = 66951; break; // Rank 3
+ case 49923: triggered_spell_id = 66952; break; // Rank 4
+ case 49924: triggered_spell_id = 66953; break; // Rank 5
+
+ // Rune Strike
+ case 56815: triggered_spell_id = 66217; break; // Rank 1
+
+ // Blood Strike
+ case 45902: triggered_spell_id = 66215; break; // Rank 1
+ case 49926: triggered_spell_id = 66975; break; // Rank 2
+ case 49927: triggered_spell_id = 66976; break; // Rank 3
+ case 49928: triggered_spell_id = 66977; break; // Rank 4
+ case 49929: triggered_spell_id = 66978; break; // Rank 5
+ case 49930: triggered_spell_id = 66979; break; // Rank 6
+ default:
+ return false;
+ }
+ break;
+ }
// Runic Power Back on Snare/Root
if (dummySpell->Id == 61257)
{
@@ -6958,17 +7122,21 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, AuraEffect* trigger
{
if (procSpell->SpellFamilyName == SPELLFAMILY_POTION)
{
- for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i)
+ for (uint8 i=0; i<MAX_SPELL_EFFECTS; i++)
{
- if (procSpell->Effect[i] == SPELL_EFFECT_HEAL)
+ if (procSpell->Effect[i]==SPELL_EFFECT_HEAL)
+ {
triggered_spell_id = 21399;
- else if (procSpell->Effect[i] == SPELL_EFFECT_ENERGIZE)
+ }
+ else if (procSpell->Effect[i]==SPELL_EFFECT_ENERGIZE)
+ {
triggered_spell_id = 21400;
+ }
else
continue;
- basepoints0 = CalculateSpellDamage(procSpell, i, procSpell->EffectBasePoints[i], this) * 0.4f;
- CastCustomSpell(this, triggered_spell_id, &basepoints0, NULL, NULL, true, NULL, triggeredByAura);
+ basepoints0 = CalculateSpellDamage(procSpell,i,procSpell->EffectBasePoints[i],this) * 0.4f;
+ CastCustomSpell(this,triggered_spell_id,&basepoints0,NULL,NULL,true,NULL,triggeredByAura);
}
return true;
}
@@ -6989,7 +7157,7 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, AuraEffect* trigger
{
triggered_spell_id = 54445;
target = this;
- pVictim->AddThreat(this, procSpell->EffectBasePoints[0]*triggerAmount/100.0f);
+ pVictim->AddThreat(this,procSpell->EffectBasePoints[0]*triggerAmount/100.0f);
break;
}
break;
@@ -6999,30 +7167,30 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, AuraEffect* trigger
}
// processed charge only counting case
- if (!triggered_spell_id)
+ if(!triggered_spell_id)
return true;
SpellEntry const* triggerEntry = sSpellStore.LookupEntry(triggered_spell_id);
- if (!triggerEntry)
+ if(!triggerEntry)
{
- sLog.outError("Unit::HandleDummyAuraProc: Spell %u have not existed triggered spell %u", dummySpell->Id, triggered_spell_id);
+ sLog.outError("Unit::HandleDummyAuraProc: Spell %u have not existed triggered spell %u",dummySpell->Id,triggered_spell_id);
return false;
}
// default case
- if ((!target && !spellmgr.IsSrcTargetSpell(triggerEntry)) || (target && target!=this && !target->isAlive()))
+ if((!target && !spellmgr.IsSrcTargetSpell(triggerEntry)) || (target && target!=this && !target->isAlive()))
return false;
- if (cooldown && GetTypeId() == TYPEID_PLAYER && ((Player*)this)->HasSpellCooldown(triggered_spell_id))
+ if( cooldown && GetTypeId() == TYPEID_PLAYER && ((Player*)this)->HasSpellCooldown(triggered_spell_id))
return false;
- if (basepoints0 || basepoints1 || basepoints2)
- CastCustomSpell(target, triggered_spell_id, &basepoints0, &basepoints1, &basepoints2, true, castItem, triggeredByAura, originalCaster);
+ if(basepoints0)
+ CastCustomSpell(target,triggered_spell_id,&basepoints0,NULL,NULL,true,castItem,triggeredByAura, originalCaster);
else
- CastSpell(target, triggered_spell_id, true, castItem, triggeredByAura, originalCaster);
+ CastSpell(target,triggered_spell_id,true,castItem,triggeredByAura, originalCaster);
- if (cooldown && GetTypeId() == TYPEID_PLAYER)
+ if( cooldown && GetTypeId() == TYPEID_PLAYER )
((Player*)this)->AddSpellCooldown(triggered_spell_id,0,time(NULL) + cooldown);
return true;
@@ -7273,7 +7441,25 @@ bool Unit::HandleProcTriggerSpell(Unit *pVictim, uint32 damage, AuraEffect* trig
// intellect
if (GetStat(STAT_INTELLECT)> stat) { trigger_spell_id = 60234;stat = GetStat(STAT_INTELLECT);}
// spirit
- if (GetStat(STAT_SPIRIT) > stat) { trigger_spell_id = 60235;stat = GetStat(STAT_SPIRIT); }
+ if (GetStat(STAT_SPIRIT) > stat) { trigger_spell_id = 60235; }
+ break;
+ }
+ case 67702: // Death's Choice, Item - Coliseum 25 Normal Melee Trinket
+ {
+ float stat = 0.0f;
+ // strength
+ if (GetStat(STAT_STRENGTH) > stat) { trigger_spell_id = 67708;stat = GetStat(STAT_STRENGTH); }
+ // agility
+ if (GetStat(STAT_AGILITY) > stat) { trigger_spell_id = 67703; }
+ break;
+ }
+ case 67771: // Death's Choice (heroic), Item - Coliseum 25 Heroic Melee Trinket
+ {
+ float stat = 0.0f;
+ // strength
+ if (GetStat(STAT_STRENGTH) > stat) { trigger_spell_id = 67773;stat = GetStat(STAT_STRENGTH); }
+ // agility
+ if (GetStat(STAT_AGILITY) > stat) { trigger_spell_id = 67772; }
break;
}
// Mana Drain Trigger
@@ -7390,6 +7576,18 @@ bool Unit::HandleProcTriggerSpell(Unit *pVictim, uint32 damage, AuraEffect* trig
return false;
}
}
+ // Druid T9 Feral Relic (Lacerate, Swipe, Mangle, and Shred)
+ else if (auraSpellInfo->Id==67353)
+ {
+ switch(m_form)
+ {
+ case FORM_CAT: trigger_spell_id = 67355; break;
+ case FORM_BEAR:
+ case FORM_DIREBEAR: trigger_spell_id = 67354; break;
+ default:
+ return false;
+ }
+ }
break;
}
case SPELLFAMILY_HUNTER:
@@ -7626,18 +7824,11 @@ bool Unit::HandleProcTriggerSpell(Unit *pVictim, uint32 damage, AuraEffect* trig
trigger_spell_id = 26470;
break;
}
- // Unyielding Knights
- case 38164:
- {
- if (pVictim->GetEntry() != 19457) // Proc only if you target is Grillok
- return false;
- break;
- }
// Deflection
case 52420:
{
- if (GetHealth()*100 / GetMaxHealth() >= 35)
- return false;
+ if(GetHealth()*100 / GetMaxHealth() >= 35)
+ return false;
break;
}
@@ -7653,7 +7844,7 @@ bool Unit::HandleProcTriggerSpell(Unit *pVictim, uint32 damage, AuraEffect* trig
case 31255:
{
// whenever you deal damage to a target who is below 20% health.
- if (pVictim->GetHealth() > pVictim->GetMaxHealth() / 5)
+ if (!pVictim || !pVictim->isAlive() || (pVictim->GetHealth() > pVictim->GetMaxHealth() / 5))
return false;
target = this;
@@ -7662,6 +7853,9 @@ bool Unit::HandleProcTriggerSpell(Unit *pVictim, uint32 damage, AuraEffect* trig
// Greater Heal Refund (Avatar Raiment set)
case 37594:
{
+ if (!pVictim || !pVictim->isAlive())
+ return false;
+
// Not give if target already have full health
if (pVictim->GetHealth() == pVictim->GetMaxHealth())
return false;
@@ -7674,7 +7868,7 @@ bool Unit::HandleProcTriggerSpell(Unit *pVictim, uint32 damage, AuraEffect* trig
case 40971:
{
// If your target is below $s1% health
- if (pVictim->GetHealth() > pVictim->GetMaxHealth() * triggerAmount / 100)
+ if (!pVictim || !pVictim->isAlive() || (pVictim->GetHealth() > pVictim->GetMaxHealth() * triggerAmount / 100))
return false;
break;
}
@@ -7695,6 +7889,14 @@ bool Unit::HandleProcTriggerSpell(Unit *pVictim, uint32 damage, AuraEffect* trig
return false;
break;
}
+ // Blessing of Ancient Kings (Val'anyr, Hammer of Ancient Kings)
+ case 64411:
+ {
+ basepoints0 = damage * 15 / 100;
+ target = pVictim;
+ trigger_spell_id = 26470;
+ break;
+ }
// Decimation
case 63156:
case 63158:
@@ -7768,7 +7970,6 @@ bool Unit::HandleProcTriggerSpell(Unit *pVictim, uint32 damage, AuraEffect* trig
{
if (!pVictim || pVictim == this)
return false;
-
// Need add combopoint AFTER finish movie (or they dropped in finish phase)
break;
}
@@ -7888,6 +8089,15 @@ bool Unit::HandleProcTriggerSpell(Unit *pVictim, uint32 damage, AuraEffect* trig
basepoints0 = int32(GetTotalAttackPowerValue(BASE_ATTACK) * triggerAmount / 100.0f);
break;
}
+ // Body and Soul
+ case 64128:
+ case 65081:
+ {
+ // Proc only from PW:S cast
+ if (!(procSpell->SpellFamilyFlags[0] & 0x00000001))
+ return false;
+ break;
+ }
}
if( cooldown && GetTypeId() == TYPEID_PLAYER && ((Player*)this)->HasSpellCooldown(trigger_spell_id))
@@ -8388,7 +8598,7 @@ bool Unit::Attack(Unit *victim, bool meleeAttack)
m_attacking = victim;
m_attacking->_addAttacker(this);
- //Set our target
+ // Set our target
SetUInt64Value(UNIT_FIELD_TARGET, victim->GetGUID());
if (meleeAttack)
@@ -8434,7 +8644,7 @@ bool Unit::AttackStop()
m_attacking->_removeAttacker(this);
m_attacking = NULL;
- //Clear our target
+ // Clear our target
SetUInt64Value(UNIT_FIELD_TARGET, 0);
clearUnitState(UNIT_STAT_MELEE_ATTACKING);
@@ -8528,7 +8738,7 @@ void Unit::ModifyAuraState(AuraState flag, bool apply)
Pet *pet = ((Pet*)this);
for (PetSpellMap::const_iterator itr = pet->m_spells.begin(); itr != pet->m_spells.end(); ++itr)
{
- if (itr->second.state == PLAYERSPELL_REMOVED) continue;
+ if (itr->second.state == PETSPELL_REMOVED) continue;
SpellEntry const *spellInfo = sSpellStore.LookupEntry(itr->first);
if (!spellInfo || !IsPassiveSpell(itr->first)) continue;
if (spellInfo->CasterAuraState == flag)
@@ -9709,12 +9919,7 @@ bool Unit::isSpellCrit(Unit *pVictim, SpellEntry const *spellProto, SpellSchoolM
if (spellProto->SpellFamilyFlags[1] & 0x00001000)
{
if (AuraEffect const* flameShock = pVictim->GetAura(SPELL_AURA_PERIODIC_DAMAGE, SPELLFAMILY_SHAMAN, 0x10000000, 0,0, GetGUID()))
- {
- // Consume shock aura if not have Glyph of Flame Shock
- if (!GetAuraEffect(55447, 0))
- pVictim->RemoveAurasDueToSpell(flameShock->GetId(), GetGUID());
return true;
- }
break;
}
break;
@@ -10458,6 +10663,18 @@ void Unit::MeleeDamageBonus(Unit *pVictim, uint32 *pdamage, WeaponAttackType att
TakenTotalMod *= (mod+100.0f)/100.0f;
}
break;
+ // Blessing of Sanctuary
+ // Greater Blessing of Sanctuary
+ case 19:
+ case 1804:
+ {
+ if ((*i)->GetSpellProto()->SpellFamilyName != SPELLFAMILY_PALADIN)
+ continue;
+
+ if ((*i)->GetMiscValue() & (spellProto ? GetSpellSchoolMask(spellProto) : 0))
+ TakenTotalMod *= ((*i)->GetAmount() + 100.0f) / 100.0f;
+ break;
+ }
// Ebon Plague
case 1933:
if ((*i)->GetMiscValue() & (spellProto ? GetSpellSchoolMask(spellProto) : 0))
@@ -10637,7 +10854,7 @@ void Unit::Unmount()
{
if (Pet *pPet = ((Player*)this)->GetPet())
{
- if (pPet->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_STUNNED) && !pPet->hasUnitState(UNIT_STAT_STUNNED))
+ if (pPet && pPet->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_STUNNED) && !pPet->hasUnitState(UNIT_STAT_STUNNED))
pPet->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_STUNNED);
}
else
@@ -11066,7 +11283,7 @@ void Unit::UpdateSpeed(UnitMoveType mtype, bool forced)
stack_bonus = GetTotalAuraMultiplier(SPELL_AURA_MOD_MOUNTED_FLIGHT_SPEED_ALWAYS);
}
else // Use not mount (shapeshift for example) auras (should stack)
- main_speed_mod = GetTotalAuraModifier(SPELL_AURA_MOD_INCREASE_FLIGHT_SPEED);
+ main_speed_mod = GetTotalAuraModifier(SPELL_AURA_MOD_INCREASE_FLIGHT_SPEED) + GetTotalAuraModifier(SPELL_AURA_MOD_INCREASE_VEHICLE_FLIGHT_SPEED);
non_stack_bonus = (100.0 + GetMaxPositiveAuraModifier(SPELL_AURA_MOD_FLIGHT_SPEED_NOT_STACK))/100.0f;
@@ -11113,7 +11330,12 @@ void Unit::UpdateSpeed(UnitMoveType mtype, bool forced)
// Apply strongest slow aura mod to speed
int32 slow = GetMaxNegativeAuraModifier(SPELL_AURA_MOD_DECREASE_SPEED);
if (slow)
+ {
speed *=(100.0f + slow)/100.0f;
+ float min_speed = (float)GetMaxPositiveAuraModifier(SPELL_AURA_MOD_MINIMUM_SPEED) / 100.0f;
+ if (speed < min_speed)
+ speed = min_speed;
+ }
SetSpeed(mtype, speed, forced);
}
@@ -12312,6 +12534,9 @@ void Unit::RemoveFromWorld()
RemoveBindSightAuras();
RemoveNotOwnSingleTargetAuras();
+ RemoveAllGameObjects();
+ RemoveAllDynObjects();
+
ExitVehicle();
UnsummonAllTotems();
RemoveAllControlled();
@@ -12351,8 +12576,6 @@ void Unit::CleanupsBeforeDelete()
ClearComboPointHolders();
DeleteThreatList();
getHostilRefManager().setOnlineOfflineState(false);
- RemoveAllGameObjects();
- RemoveAllDynObjects();
GetMotionMaster()->Clear(false); // remove different non-standard movement generators.
if (IsInWorld())
@@ -12602,12 +12825,12 @@ void CharmInfo::LoadPetActionBar(const std::string& data )
Tokens tokens = StrSplit(data, " ");
- if (tokens.size() != (ACTION_BAR_INDEX_PET_SPELL_END-ACTION_BAR_INDEX_PET_SPELL_START)*2)
+ if (tokens.size() != (ACTION_BAR_INDEX_END-ACTION_BAR_INDEX_START)*2)
return; // non critical, will reset to default
uint8 index;
Tokens::iterator iter;
- for (iter = tokens.begin(), index = ACTION_BAR_INDEX_PET_SPELL_START; index < ACTION_BAR_INDEX_PET_SPELL_END; ++iter, ++index )
+ for (iter = tokens.begin(), index = ACTION_BAR_INDEX_START; index < ACTION_BAR_INDEX_END; ++iter, ++index)
{
// use unsigned cast to avoid sign negative format use at long-> ActiveStates (int) conversion
uint8 type = atol((*iter).c_str());
@@ -13843,6 +14066,14 @@ void Unit::Kill(Unit *pVictim, bool durabilityLoss)
// call kill spell proc event (before real die and combat stop to triggering auras removed at death/combat stop)
if (bRewardIsAllowed && player && player!=pVictim)
{
+ WorldPacket data(SMSG_PARTYKILLLOG, (8+8)); //send event PARTY_KILL
+ data << uint64(player->GetGUID()); //player with killing blow
+ data << uint64(pVictim->GetGUID()); //victim
+ if (Group *group = player->GetGroup())
+ group->BroadcastPacket(&data, group->GetMemberGroup(player->GetGUID()));
+ else
+ player->SendDirectMessage(&data);
+
if (player->RewardPlayerAndGroupAtKill(pVictim))
player->ProcDamageAndSpell(pVictim, PROC_FLAG_KILL, PROC_FLAG_KILLED, PROC_EX_NONE, 0);
else
@@ -13943,7 +14174,7 @@ void Unit::Kill(Unit *pVictim, bool durabilityLoss)
if (m->IsDungeon() && creditedPlayer)
{
- if (m->IsRaid() || m->IsHeroic())
+ if (m->IsRaidOrHeroicDungeon())
{
if (cVictim->GetCreatureInfo()->flags_extra & CREATURE_FLAG_EXTRA_INSTANCE_BIND)
((InstanceMap *)m)->PermBindAllPlayers(creditedPlayer);
@@ -14805,7 +15036,9 @@ void Unit::KnockbackFrom(float x, float y, float speedXY, float speedZ)
}
if (!player)
+ {
GetMotionMaster()->MoveKnockbackFrom(x, y, speedXY, speedZ);
+ }
else
{
float vcos, vsin;
@@ -14823,6 +15056,208 @@ void Unit::KnockbackFrom(float x, float y, float speedXY, float speedZ)
}
}
+uint32 Unit::GetModelForForm(ShapeshiftForm form)
+{
+ switch(form)
+ {
+ case FORM_CAT:
+ // Based on Hair color
+ if (getRace() == RACE_NIGHTELF)
+ {
+ uint8 hairColor = GetByteValue(PLAYER_BYTES, 3);
+ switch (hairColor)
+ {
+ case 7: // Violet
+ case 8:
+ return 29405;
+ case 3: // Light Blue
+ return 29406;
+ case 0: // Green
+ case 1: // Light Green
+ case 2: // Dark Green
+ return 29407;
+ case 4: // White
+ return 29408;
+ default: // original - Dark Blue
+ return 892;
+ }
+ }
+ // Based on Skin color
+ else if (getRace() == RACE_TAUREN)
+ {
+ uint8 skinColor = GetByteValue(PLAYER_BYTES, 0);
+ // Male
+ if (getGender() == GENDER_MALE)
+ {
+ switch(skinColor)
+ {
+ case 12: // White
+ case 13:
+ case 14:
+ case 18: // Completly White
+ return 29409;
+ case 9: // Light Brown
+ case 10:
+ case 11:
+ return 29410;
+ case 6: // Brown
+ case 7:
+ case 8:
+ return 29411;
+ case 0: // Dark
+ case 1:
+ case 2:
+ case 3: // Dark Grey
+ case 4:
+ case 5:
+ return 29412;
+ default: // original - Grey
+ return 8571;
+ }
+ }
+ // Female
+ else switch (skinColor)
+ {
+ case 10: // White
+ return 29409;
+ case 6: // Light Brown
+ case 7:
+ return 29410;
+ case 4: // Brown
+ case 5:
+ return 29411;
+ case 0: // Dark
+ case 1:
+ case 2:
+ case 3:
+ return 29412;
+ default: // original - Grey
+ return 8571;
+ }
+ }
+ else if(Player::TeamForRace(getRace())==ALLIANCE)
+ return 892;
+ else
+ return 8571;
+ case FORM_DIREBEAR:
+ case FORM_BEAR:
+ // Based on Hair color
+ if (getRace() == RACE_NIGHTELF)
+ {
+ uint8 hairColor = GetByteValue(PLAYER_BYTES, 3);
+ switch (hairColor)
+ {
+ case 0: // Green
+ case 1: // Light Green
+ case 2: // Dark Green
+ return 29413; // 29415?
+ case 6: // Dark Blue
+ return 29414;
+ case 4: // White
+ return 29416;
+ case 3: // Light Blue
+ return 29417;
+ default: // original - Violet
+ return 2281;
+ }
+ }
+ // Based on Skin color
+ else if (getRace() == RACE_TAUREN)
+ {
+ uint8 skinColor = GetByteValue(PLAYER_BYTES, 0);
+ // Male
+ if (getGender() == GENDER_MALE)
+ {
+ switch (skinColor)
+ {
+ case 0: // Dark (Black)
+ case 1:
+ case 2:
+ return 29418;
+ case 3: // White
+ case 4:
+ case 5:
+ case 12:
+ case 13:
+ case 14:
+ return 29419;
+ case 9: // Light Brown/Grey
+ case 10:
+ case 11:
+ case 15:
+ case 16:
+ case 17:
+ return 29420;
+ case 18: // Completly White
+ return 29421;
+ default: // original - Brown
+ return 2289;
+ }
+ }
+ // Female
+ else switch (skinColor)
+ {
+ case 0: // Dark (Black)
+ case 1:
+ return 29418;
+ case 2: // White
+ case 3:
+ return 29419;
+ case 6: // Light Brown/Grey
+ case 7:
+ case 8:
+ case 9:
+ return 29420;
+ case 10: // Completly White
+ return 29421;
+ default: // original - Brown
+ return 2289;
+ }
+ }
+ else if(Player::TeamForRace(getRace())==ALLIANCE)
+ return 2281;
+ else
+ return 2289;
+ case FORM_TRAVEL:
+ return 632;
+ case FORM_AQUA:
+ if(Player::TeamForRace(getRace())==ALLIANCE)
+ return 2428;
+ else
+ return 2428;
+ case FORM_GHOUL:
+ return 24994;
+ case FORM_CREATUREBEAR:
+ return 902;
+ case FORM_GHOSTWOLF:
+ return 4613;
+ case FORM_FLIGHT:
+ if(Player::TeamForRace(getRace())==ALLIANCE)
+ return 20857;
+ else
+ return 20872;
+ case FORM_MOONKIN:
+ if(Player::TeamForRace(getRace())==ALLIANCE)
+ return 15374;
+ else
+ return 15375;
+ case FORM_FLIGHT_EPIC:
+ if(Player::TeamForRace(getRace())==ALLIANCE)
+ return 21243;
+ else
+ return 21244;
+ case FORM_METAMORPHOSIS:
+ return 25277;
+ case FORM_MASTER_ANGLER:
+ return 15234;
+ case FORM_TREE:
+ return 864;
+ case FORM_SPIRITOFREDEMPTION:
+ return 16031;
+ }
+ return 0;
+}
+
void Unit::JumpTo(float speedXY, float speedZ, bool forward)
{
float angle = forward ? 0 : M_PI;
diff --git a/src/game/Unit.h b/src/game/Unit.h
index b54fd00f1de..b439cf35dc6 100644
--- a/src/game/Unit.h
+++ b/src/game/Unit.h
@@ -715,6 +715,7 @@ enum MonsterMovementFlags
struct MovementInfo
{
// common
+ uint64 guid;
uint32 flags;
uint16 unk1;
uint32 time;
@@ -1623,18 +1624,6 @@ class TRINITY_DLL_SPEC Unit : public WorldObject
SetOrientation(GetAngle(target));
}
bool isInBackInMap(Unit const* target, float distance, float arc = M_PI) const;
- void ChangeOrient(float fAngle, Unit* pUnit = NULL)
- {
- if(!this)
- return;
-
- if(!pUnit)
- this->SetOrientation(fAngle);
- else
- this->SetInFront(pUnit);
-
- this->SendMovementFlagUpdate();
- }
// Visibility system
UnitVisibility GetVisibility() const { return m_Visibility; }
@@ -1852,6 +1841,8 @@ class TRINITY_DLL_SPEC Unit : public WorldObject
void AddPetAura(PetAura const* petSpell);
void RemovePetAura(PetAura const* petSpell);
+ uint32 GetModelForForm(ShapeshiftForm form);
+
// relocation notification
void SetToNotify();
bool m_Notified;
@@ -2030,4 +2021,3 @@ namespace Trinity
}
#endif
-
diff --git a/src/game/UpdateFields.h b/src/game/UpdateFields.h
index 8fa05a4cb86..d8b6ae9d284 100644
--- a/src/game/UpdateFields.h
+++ b/src/game/UpdateFields.h
@@ -21,7 +21,7 @@
#ifndef _UPDATEFIELDS_AUTO_H
#define _UPDATEFIELDS_AUTO_H
-// Auto generated for version 3, 1, 3, 9947
+// Auto generated for version 3, 2, 2, 10505
enum EObjectFields
{
@@ -72,7 +72,7 @@ enum EItemFields
ITEM_FIELD_ITEM_TEXT_ID = OBJECT_END + 0x0036, // Size: 1, Type: INT, Flags: OWNER
ITEM_FIELD_DURABILITY = OBJECT_END + 0x0037, // Size: 1, Type: INT, Flags: OWNER, ITEM_OWNER
ITEM_FIELD_MAXDURABILITY = OBJECT_END + 0x0038, // Size: 1, Type: INT, Flags: OWNER, ITEM_OWNER
- ITEM_FIELD_PAD = OBJECT_END + 0x0039, // Size: 1, Type: INT, Flags: NONE
+ ITEM_FIELD_CREATE_PLAYED_TIME = OBJECT_END + 0x0039, // Size: 1, Type: INT, Flags: PUBLIC
ITEM_END = OBJECT_END + 0x003A,
};
@@ -325,7 +325,7 @@ enum EUnitFields
PLAYER_VISIBLE_ITEM_19_ENTRYID = UNIT_END + 0x0092, // Size: 1, Type: INT, Flags: PUBLIC
PLAYER_VISIBLE_ITEM_19_ENCHANTMENT = UNIT_END + 0x0093, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC
PLAYER_CHOSEN_TITLE = UNIT_END + 0x0094, // Size: 1, Type: INT, Flags: PUBLIC
- PLAYER_FIELD_PAD_0 = UNIT_END + 0x0095, // Size: 1, Type: INT, Flags: NONE
+ PLAYER_FAKE_INEBRIATION = UNIT_END + 0x0095, // Size: 1, Type: INT, Flags: PUBLIC
PLAYER_FIELD_INV_SLOT_HEAD = UNIT_END + 0x0096, // Size: 46, Type: LONG, Flags: PRIVATE
PLAYER_FIELD_PACK_SLOT_1 = UNIT_END + 0x00C4, // Size: 32, Type: LONG, Flags: PRIVATE
PLAYER_FIELD_BANK_SLOT_1 = UNIT_END + 0x00E4, // Size: 56, Type: LONG, Flags: PRIVATE
@@ -363,32 +363,35 @@ enum EUnitFields
PLAYER_FIELD_MOD_DAMAGE_DONE_NEG = UNIT_END + 0x03EC, // Size: 7, Type: INT, Flags: PRIVATE
PLAYER_FIELD_MOD_DAMAGE_DONE_PCT = UNIT_END + 0x03F3, // Size: 7, Type: INT, Flags: PRIVATE
PLAYER_FIELD_MOD_HEALING_DONE_POS = UNIT_END + 0x03FA, // Size: 1, Type: INT, Flags: PRIVATE
- PLAYER_FIELD_MOD_TARGET_RESISTANCE = UNIT_END + 0x03FB, // Size: 1, Type: INT, Flags: PRIVATE
- PLAYER_FIELD_MOD_TARGET_PHYSICAL_RESISTANCE = UNIT_END + 0x03FC, // Size: 1, Type: INT, Flags: PRIVATE
- PLAYER_FIELD_BYTES = UNIT_END + 0x03FD, // Size: 1, Type: BYTES, Flags: PRIVATE
- PLAYER_AMMO_ID = UNIT_END + 0x03FE, // Size: 1, Type: INT, Flags: PRIVATE
- PLAYER_SELF_RES_SPELL = UNIT_END + 0x03FF, // Size: 1, Type: INT, Flags: PRIVATE
- PLAYER_FIELD_PVP_MEDALS = UNIT_END + 0x0400, // Size: 1, Type: INT, Flags: PRIVATE
- PLAYER_FIELD_BUYBACK_PRICE_1 = UNIT_END + 0x0401, // Size: 12, Type: INT, Flags: PRIVATE
- PLAYER_FIELD_BUYBACK_TIMESTAMP_1 = UNIT_END + 0x040D, // Size: 12, Type: INT, Flags: PRIVATE
- PLAYER_FIELD_KILLS = UNIT_END + 0x0419, // Size: 1, Type: TWO_SHORT, Flags: PRIVATE
- PLAYER_FIELD_TODAY_CONTRIBUTION = UNIT_END + 0x041A, // Size: 1, Type: INT, Flags: PRIVATE
- PLAYER_FIELD_YESTERDAY_CONTRIBUTION = UNIT_END + 0x041B, // Size: 1, Type: INT, Flags: PRIVATE
- PLAYER_FIELD_LIFETIME_HONORABLE_KILLS = UNIT_END + 0x041C, // Size: 1, Type: INT, Flags: PRIVATE
- PLAYER_FIELD_BYTES2 = UNIT_END + 0x041D, // Size: 1, Type: BYTES, Flags: PRIVATE
- PLAYER_FIELD_WATCHED_FACTION_INDEX = UNIT_END + 0x041E, // Size: 1, Type: INT, Flags: PRIVATE
- PLAYER_FIELD_COMBAT_RATING_1 = UNIT_END + 0x041F, // Size: 25, Type: INT, Flags: PRIVATE
- PLAYER_FIELD_ARENA_TEAM_INFO_1_1 = UNIT_END + 0x0438, // Size: 18, Type: INT, Flags: PRIVATE
- PLAYER_FIELD_HONOR_CURRENCY = UNIT_END + 0x044A, // Size: 1, Type: INT, Flags: PRIVATE
- PLAYER_FIELD_ARENA_CURRENCY = UNIT_END + 0x044B, // Size: 1, Type: INT, Flags: PRIVATE
- PLAYER_FIELD_MAX_LEVEL = UNIT_END + 0x044C, // Size: 1, Type: INT, Flags: PRIVATE
- PLAYER_FIELD_DAILY_QUESTS_1 = UNIT_END + 0x044D, // Size: 25, Type: INT, Flags: PRIVATE
- PLAYER_RUNE_REGEN_1 = UNIT_END + 0x0466, // Size: 4, Type: FLOAT, Flags: PRIVATE
- PLAYER_NO_REAGENT_COST_1 = UNIT_END + 0x046A, // Size: 3, Type: INT, Flags: PRIVATE
- PLAYER_FIELD_GLYPH_SLOTS_1 = UNIT_END + 0x046D, // Size: 6, Type: INT, Flags: PRIVATE
- PLAYER_FIELD_GLYPHS_1 = UNIT_END + 0x0473, // Size: 6, Type: INT, Flags: PRIVATE
- PLAYER_GLYPHS_ENABLED = UNIT_END + 0x0479, // Size: 1, Type: INT, Flags: PRIVATE
- PLAYER_END = UNIT_END + 0x047A,
+ PLAYER_FIELD_MOD_HEALING_PCT = UNIT_END + 0x03FB, // Size: 1, Type: FLOAT, Flags: PRIVATE
+ PLAYER_FIELD_MOD_HEALING_DONE_PCT = UNIT_END + 0x03FC, // Size: 1, Type: FLOAT, Flags: PRIVATE
+ PLAYER_FIELD_MOD_TARGET_RESISTANCE = UNIT_END + 0x03FD, // Size: 1, Type: INT, Flags: PRIVATE
+ PLAYER_FIELD_MOD_TARGET_PHYSICAL_RESISTANCE = UNIT_END + 0x03FE, // Size: 1, Type: INT, Flags: PRIVATE
+ PLAYER_FIELD_BYTES = UNIT_END + 0x03FF, // Size: 1, Type: BYTES, Flags: PRIVATE
+ PLAYER_AMMO_ID = UNIT_END + 0x0400, // Size: 1, Type: INT, Flags: PRIVATE
+ PLAYER_SELF_RES_SPELL = UNIT_END + 0x0401, // Size: 1, Type: INT, Flags: PRIVATE
+ PLAYER_FIELD_PVP_MEDALS = UNIT_END + 0x0402, // Size: 1, Type: INT, Flags: PRIVATE
+ PLAYER_FIELD_BUYBACK_PRICE_1 = UNIT_END + 0x0403, // Size: 12, Type: INT, Flags: PRIVATE
+ PLAYER_FIELD_BUYBACK_TIMESTAMP_1 = UNIT_END + 0x040F, // Size: 12, Type: INT, Flags: PRIVATE
+ PLAYER_FIELD_KILLS = UNIT_END + 0x041B, // Size: 1, Type: TWO_SHORT, Flags: PRIVATE
+ PLAYER_FIELD_TODAY_CONTRIBUTION = UNIT_END + 0x041C, // Size: 1, Type: INT, Flags: PRIVATE
+ PLAYER_FIELD_YESTERDAY_CONTRIBUTION = UNIT_END + 0x041D, // Size: 1, Type: INT, Flags: PRIVATE
+ PLAYER_FIELD_LIFETIME_HONORABLE_KILLS = UNIT_END + 0x041E, // Size: 1, Type: INT, Flags: PRIVATE
+ PLAYER_FIELD_BYTES2 = UNIT_END + 0x041F, // Size: 1, Type: 6, Flags: PRIVATE
+ PLAYER_FIELD_WATCHED_FACTION_INDEX = UNIT_END + 0x0420, // Size: 1, Type: INT, Flags: PRIVATE
+ PLAYER_FIELD_COMBAT_RATING_1 = UNIT_END + 0x0421, // Size: 25, Type: INT, Flags: PRIVATE
+ PLAYER_FIELD_ARENA_TEAM_INFO_1_1 = UNIT_END + 0x043A, // Size: 21, Type: INT, Flags: PRIVATE
+ PLAYER_FIELD_HONOR_CURRENCY = UNIT_END + 0x044F, // Size: 1, Type: INT, Flags: PRIVATE
+ PLAYER_FIELD_ARENA_CURRENCY = UNIT_END + 0x0450, // Size: 1, Type: INT, Flags: PRIVATE
+ PLAYER_FIELD_MAX_LEVEL = UNIT_END + 0x0451, // Size: 1, Type: INT, Flags: PRIVATE
+ PLAYER_FIELD_DAILY_QUESTS_1 = UNIT_END + 0x0452, // Size: 25, Type: INT, Flags: PRIVATE
+ PLAYER_RUNE_REGEN_1 = UNIT_END + 0x046B, // Size: 4, Type: FLOAT, Flags: PRIVATE
+ PLAYER_NO_REAGENT_COST_1 = UNIT_END + 0x046F, // Size: 3, Type: INT, Flags: PRIVATE
+ PLAYER_FIELD_GLYPH_SLOTS_1 = UNIT_END + 0x0472, // Size: 6, Type: INT, Flags: PRIVATE
+ PLAYER_FIELD_GLYPHS_1 = UNIT_END + 0x0478, // Size: 6, Type: INT, Flags: PRIVATE
+ PLAYER_GLYPHS_ENABLED = UNIT_END + 0x047E, // Size: 1, Type: INT, Flags: PRIVATE
+ PLAYER_FIELD_PADDING = UNIT_END + 0x047F, // Size: 1, Type: INT, Flags: NONE
+ PLAYER_END = UNIT_END + 0x0480,
};
enum EGameObjectFields
@@ -410,12 +413,8 @@ enum EDynamicObjectFields
DYNAMICOBJECT_BYTES = OBJECT_END + 0x0002, // Size: 1, Type: BYTES, Flags: PUBLIC
DYNAMICOBJECT_SPELLID = OBJECT_END + 0x0003, // Size: 1, Type: INT, Flags: PUBLIC
DYNAMICOBJECT_RADIUS = OBJECT_END + 0x0004, // Size: 1, Type: FLOAT, Flags: PUBLIC
- DYNAMICOBJECT_POS_X = OBJECT_END + 0x0005, // Size: 1, Type: FLOAT, Flags: PUBLIC
- DYNAMICOBJECT_POS_Y = OBJECT_END + 0x0006, // Size: 1, Type: FLOAT, Flags: PUBLIC
- DYNAMICOBJECT_POS_Z = OBJECT_END + 0x0007, // Size: 1, Type: FLOAT, Flags: PUBLIC
- DYNAMICOBJECT_FACING = OBJECT_END + 0x0008, // Size: 1, Type: FLOAT, Flags: PUBLIC
- DYNAMICOBJECT_CASTTIME = OBJECT_END + 0x0009, // Size: 1, Type: INT, Flags: PUBLIC
- DYNAMICOBJECT_END = OBJECT_END + 0x000A,
+ DYNAMICOBJECT_CASTTIME = OBJECT_END + 0x0005, // Size: 1, Type: INT, Flags: PUBLIC
+ DYNAMICOBJECT_END = OBJECT_END + 0x0006,
};
enum ECorpseFields
@@ -433,4 +432,3 @@ enum ECorpseFields
CORPSE_END = OBJECT_END + 0x001E,
};
#endif
-
diff --git a/src/game/World.cpp b/src/game/World.cpp
index a822d202288..7d103c0457f 100644
--- a/src/game/World.cpp
+++ b/src/game/World.cpp
@@ -259,6 +259,8 @@ World::AddSession_ (WorldSession* s)
pkt << uint32(sWorld.getConfig(CONFIG_CLIENTCACHE_VERSION));
s->SendPacket(&pkt);
+ s->SendAccountDataTimes(GLOBAL_CACHE_MASK);
+
s->SendTutorialsData();
UpdateMaxSessionCounters ();
@@ -269,7 +271,6 @@ World::AddSession_ (WorldSession* s)
float popu = GetActiveSessionCount (); // updated number of users on the server
popu /= pLimit;
popu *= 2;
- loginDatabase.PExecute ("UPDATE realmlist SET population = '%f' WHERE id = '%d'", popu, realmID);
sLog.outDetail ("Server Population (%f).", popu);
}
}
@@ -365,6 +366,7 @@ bool World::RemoveQueuedPlayer(WorldSession* sess)
pkt << uint32(sWorld.getConfig(CONFIG_CLIENTCACHE_VERSION));
pop_sess->SendPacket(&pkt);
+ pop_sess->SendAccountDataTimes(GLOBAL_CACHE_MASK);
pop_sess->SendTutorialsData();
m_QueuedPlayer.pop_front();
@@ -553,41 +555,40 @@ void World::LoadConfigSettings(bool reload)
rate_values[RATE_DURABILITY_LOSS_ON_DEATH] = sConfig.GetFloatDefault("DurabilityLoss.OnDeath", 10.0f);
if (rate_values[RATE_DURABILITY_LOSS_ON_DEATH] < 0.0f)
{
- sLog.outError("DurabilityLoss.OnDeath (%f) must be >= 0. Using 0.0 instead.",rate_values[RATE_DURABILITY_LOSS_ON_DEATH]);
+ sLog.outError("DurabilityLoss.OnDeath (%f) must be >=0. Using 0.0 instead.",rate_values[RATE_DURABILITY_LOSS_ON_DEATH]);
rate_values[RATE_DURABILITY_LOSS_ON_DEATH] = 0.0f;
}
if (rate_values[RATE_DURABILITY_LOSS_ON_DEATH] > 100.0f)
{
- sLog.outError("DurabilityLoss.OnDeath (%f) must be <= 100. Using 100.0 instead.",rate_values[RATE_DURABILITY_LOSS_ON_DEATH]);
- rate_values[RATE_DURABILITY_LOSS_ON_DEATH] = 100.0f;
+ sLog.outError("DurabilityLoss.OnDeath (%f) must be <=100. Using 100.0 instead.",rate_values[RATE_DURABILITY_LOSS_ON_DEATH]);
+ rate_values[RATE_DURABILITY_LOSS_ON_DEATH] = 0.0f;
}
rate_values[RATE_DURABILITY_LOSS_ON_DEATH] = rate_values[RATE_DURABILITY_LOSS_ON_DEATH] / 100.0f;
rate_values[RATE_DURABILITY_LOSS_DAMAGE] = sConfig.GetFloatDefault("DurabilityLossChance.Damage",0.5f);
if (rate_values[RATE_DURABILITY_LOSS_DAMAGE] < 0.0f)
{
- sLog.outError("DurabilityLossChance.Damage (%f) must be >= 0. Using 0.0 instead.",rate_values[RATE_DURABILITY_LOSS_DAMAGE]);
+ sLog.outError("DurabilityLossChance.Damage (%f) must be >=0. Using 0.0 instead.",rate_values[RATE_DURABILITY_LOSS_DAMAGE]);
rate_values[RATE_DURABILITY_LOSS_DAMAGE] = 0.0f;
}
rate_values[RATE_DURABILITY_LOSS_ABSORB] = sConfig.GetFloatDefault("DurabilityLossChance.Absorb",0.5f);
if (rate_values[RATE_DURABILITY_LOSS_ABSORB] < 0.0f)
{
- sLog.outError("DurabilityLossChance.Absorb (%f) must be >= 0. Using 0.0 instead.",rate_values[RATE_DURABILITY_LOSS_ABSORB]);
+ sLog.outError("DurabilityLossChance.Absorb (%f) must be >=0. Using 0.0 instead.",rate_values[RATE_DURABILITY_LOSS_ABSORB]);
rate_values[RATE_DURABILITY_LOSS_ABSORB] = 0.0f;
}
rate_values[RATE_DURABILITY_LOSS_PARRY] = sConfig.GetFloatDefault("DurabilityLossChance.Parry",0.05f);
if (rate_values[RATE_DURABILITY_LOSS_PARRY] < 0.0f)
{
- sLog.outError("DurabilityLossChance.Parry (%f) must be >= 0. Using 0.0 instead.",rate_values[RATE_DURABILITY_LOSS_PARRY]);
+ sLog.outError("DurabilityLossChance.Parry (%f) must be >=0. Using 0.0 instead.",rate_values[RATE_DURABILITY_LOSS_PARRY]);
rate_values[RATE_DURABILITY_LOSS_PARRY] = 0.0f;
}
rate_values[RATE_DURABILITY_LOSS_BLOCK] = sConfig.GetFloatDefault("DurabilityLossChance.Block",0.05f);
if (rate_values[RATE_DURABILITY_LOSS_BLOCK] < 0.0f)
{
- sLog.outError("DurabilityLossChance.Block (%f) must be >= 0. Using 0.0 instead.",rate_values[RATE_DURABILITY_LOSS_BLOCK]);
+ sLog.outError("DurabilityLossChance.Block (%f) must be >=0. Using 0.0 instead.",rate_values[RATE_DURABILITY_LOSS_BLOCK]);
rate_values[RATE_DURABILITY_LOSS_BLOCK] = 0.0f;
}
-
///- Read other configuration items from the config file
m_configs[CONFIG_DURABILITY_LOSS_IN_PVP] = sConfig.GetBoolDefault("DurabilityLoss.InPvP", false);
@@ -1193,7 +1194,7 @@ void World::LoadConfigSettings(bool reload)
m_configs[CONFIG_INTERVAL_LOG_UPDATE] = sConfig.GetIntDefault("RecordUpdateTimeDiffInterval", 60000);
m_configs[CONFIG_MIN_LOG_UPDATE] = sConfig.GetIntDefault("MinRecordUpdateTimeDiff", 10);
m_configs[CONFIG_CHECK_DB] = sConfig.GetBoolDefault("CheckDB", true);
- m_configs[CONFIG_NUMTHREADS] = sConfig.GetIntDefault("MapUpdate.Threads",1);
+ m_configs[CONFIG_NUMTHREADS] = sConfig.GetIntDefault("MapUpdate.Threads", 1);
std::string forbiddenmaps = sConfig.GetStringDefault("ForbiddenMaps", "");
char * forbiddenMaps = new char[forbiddenmaps.length() + 1];
@@ -1303,9 +1304,6 @@ void World::SetInitialWorldSettings()
sLog.outString("Loading Page Texts...");
objmgr.LoadPageTexts();
- sLog.outString("Loading Player info in cache...");
- objmgr.LoadPlayerInfoInCache();
-
sLog.outString("Loading Game Object Templates..."); // must be after LoadPageTexts
objmgr.LoadGameobjectInfo();
@@ -2584,6 +2582,16 @@ void World::LoadDBVersion()
m_CreatureEventAIVersion = "Unknown creature EventAI.";
}
+void World::ProcessStartEvent()
+{
+ isEventKillStart = true;
+}
+
+void World::ProcessStopEvent()
+{
+ isEventKillStart = false;
+}
+
void World::UpdateAreaDependentAuras()
{
SessionMap::const_iterator itr;
diff --git a/src/game/World.h b/src/game/World.h
index fb73d4ed08c..79c621d9a51 100644
--- a/src/game/World.h
+++ b/src/game/World.h
@@ -45,6 +45,7 @@ struct ScriptInfo;
class SqlResultQueue;
class QueryResult;
class WorldSocket;
+class SystemMgr;
// ServerMessages.dbc
enum ServerMessageType
@@ -81,7 +82,8 @@ enum WorldTimers
WUPDATE_EVENTS = 6,
WUPDATE_CLEANDB = 7,
WUPDATE_AUTOBROADCAST = 8,
- WUPDATE_COUNT = 9
+ WUPDATE_MAILBOXQUEUE = 9,
+ WUPDATE_COUNT = 10
};
// States than may change after server started
@@ -261,6 +263,7 @@ enum WorldConfigs
CONFIG_MIN_LOG_UPDATE,
CONFIG_CHECK_DB,
CONFIG_ENABLE_SINFO_LOGIN,
+ CONFIG_PLAYER_ALLOW_COMMANDS,
CONFIG_PET_LOS,
CONFIG_NUMTHREADS,
CONFIG_OFFHAND_CHECK_AT_SPELL_UNLEARN,
@@ -610,6 +613,19 @@ class World
static float GetVisibleUnitGreyDistance() { return m_VisibleUnitGreyDistance; }
static float GetVisibleObjectGreyDistance() { return m_VisibleObjectGreyDistance; }
+
+ void SetWintergrapsTimer(uint32 timer, uint32 state)
+ {
+ m_WintergrapsTimer = timer;
+ m_WintergrapsState = state;
+ }
+
+ uint32 GetWintergrapsTimer() { return m_WintergrapsTimer; }
+ uint32 GetWintergrapsState() { return m_WintergrapsState; }
+
+ uint32 m_WintergrapsTimer;
+ uint32 m_WintergrapsState;
+
void ProcessCliCommands();
void QueueCliCommand( CliCommandHolder::Print* zprintf, char const* input ) { cliCmdQueue.add(new CliCommandHolder(input, zprintf)); }
@@ -638,6 +654,12 @@ class World
void LoadAutobroadcasts();
void UpdateAreaDependentAuras();
+
+ void ProcessStartEvent();
+ void ProcessStopEvent();
+ bool GetEventKill() { return isEventKillStart; }
+
+ bool isEventKillStart;
protected:
void _UpdateGameTime();
// callback for UpdateRealmCharacters
@@ -728,4 +750,3 @@ extern uint32 realmID;
#define sWorld Trinity::Singleton<World>::Instance()
#endif
/// @}
-
diff --git a/src/game/WorldSession.cpp b/src/game/WorldSession.cpp
index bbcf4fcbf70..569c8fade62 100644
--- a/src/game/WorldSession.cpp
+++ b/src/game/WorldSession.cpp
@@ -655,13 +655,15 @@ void WorldSession::SetAccountData(AccountDataType type, time_t time_, std::strin
m_accountData[type].Data = data;
}
-void WorldSession::SendAccountDataTimes()
+void WorldSession::SendAccountDataTimes(uint32 mask)
{
- WorldPacket data( SMSG_ACCOUNT_DATA_TIMES, 4+1+8*4 ); // changed in WotLK
+ WorldPacket data( SMSG_ACCOUNT_DATA_TIMES, 4+1+4+8*4 ); // changed in WotLK
data << uint32(time(NULL)); // unix time of something
data << uint8(1);
- for (int i = 0; i < NUM_ACCOUNT_DATA_TYPES; ++i)
- data << uint32(m_accountData[i].Time); // also unix time
+ data << uint32(mask); // type mask
+ for(uint32 i = 0; i < NUM_ACCOUNT_DATA_TYPES; ++i)
+ if(mask & (1 << i))
+ data << uint32(GetAccountData(AccountDataType(i))->Time);// also unix time
SendPacket(&data);
}
@@ -768,6 +770,51 @@ void WorldSession::ReadMovementInfo(WorldPacket &data, MovementInfo *mi)
}
}
+void WorldSession::WriteMovementInfo(WorldPacket *data, MovementInfo *mi)
+{
+ data->appendPackGUID(mi->guid);
+
+ *data << mi->flags;
+ *data << mi->unk1;
+ *data << mi->time;
+ *data << mi->x;
+ *data << mi->y;
+ *data << mi->z;
+ *data << mi->o;
+
+ if(mi->HasMovementFlag(MOVEMENTFLAG_ONTRANSPORT))
+ {
+ data->appendPackGUID(mi->t_guid);
+
+ *data << mi->t_x;
+ *data << mi->t_y;
+ *data << mi->t_z;
+ *data << mi->t_o;
+ *data << mi->t_time;
+ *data << mi->t_seat;
+ }
+
+ if((mi->HasMovementFlag(MovementFlags(MOVEMENTFLAG_SWIMMING | MOVEMENTFLAG_FLYING))) || (mi->unk1 & 0x20))
+ {
+ *data << mi->s_pitch;
+ }
+
+ *data << mi->fallTime;
+
+ if(mi->HasMovementFlag(MOVEMENTFLAG_JUMPING))
+ {
+ *data << mi->j_zspeed;
+ *data << mi->j_sinAngle;
+ *data << mi->j_cosAngle;
+ *data << mi->j_xyspeed;
+ }
+
+ if(mi->HasMovementFlag(MOVEMENTFLAG_SPLINE))
+ {
+ *data << mi->u_unk1;
+ }
+}
+
void WorldSession::ReadAddonsInfo(WorldPacket &data)
{
if (data.rpos() + 4 > data.size())
diff --git a/src/game/WorldSession.h b/src/game/WorldSession.h
index 0e0d5df9480..7e81a3d338f 100644
--- a/src/game/WorldSession.h
+++ b/src/game/WorldSession.h
@@ -126,6 +126,7 @@ class TRINITY_DLL_SPEC WorldSession
void SendAddonsInfo();
void ReadMovementInfo(WorldPacket &data, MovementInfo *mi);
+ void WriteMovementInfo(WorldPacket *data, MovementInfo *mi);
void SendPacket(WorldPacket const* packet);
void SendNotification(const char *format,...) ATTR_PRINTF(2,3);
@@ -203,7 +204,7 @@ class TRINITY_DLL_SPEC WorldSession
// Account Data
AccountData *GetAccountData(AccountDataType type) { return &m_accountData[type]; }
void SetAccountData(AccountDataType type, time_t time_, std::string data);
- void SendAccountDataTimes();
+ void SendAccountDataTimes(uint32 mask);
void LoadGlobalAccountData();
void LoadAccountData(QueryResult* result, uint32 mask);
void LoadTutorialsData();
@@ -222,9 +223,8 @@ class TRINITY_DLL_SPEC WorldSession
m_TutorialsChanged = true;
}
}
- //used with item_page table
+ //used with item_page table
bool SendItemInfo( uint32 itemid, WorldPacket data );
-
//auction
void SendAuctionHello( uint64 guid, Creature * unit );
void SendAuctionCommandResult( uint32 auctionId, uint32 Action, uint32 ErrorCode, uint32 bidError = 0);
@@ -573,6 +573,7 @@ class TRINITY_DLL_SPEC WorldSession
void HandleReclaimCorpseOpcode( WorldPacket& recvPacket );
void HandleCorpseQueryOpcode( WorldPacket& recvPacket );
+ void HandleCorpseMapPositionQuery( WorldPacket& recvPacket );
void HandleResurrectResponseOpcode(WorldPacket& recvPacket);
void HandleSummonResponseOpcode(WorldPacket& recv_data);
@@ -647,6 +648,7 @@ class TRINITY_DLL_SPEC WorldSession
void HandleFarSightOpcode(WorldPacket& recv_data);
void HandleSetLfgOpcode(WorldPacket& recv_data);
void HandleSetDungeonDifficultyOpcode(WorldPacket& recv_data);
+ void HandleSetRaidDifficultyOpcode(WorldPacket& recv_data);
void HandleMoveSetCanFlyAckOpcode(WorldPacket& recv_data);
void HandleLfgSetAutoJoinOpcode(WorldPacket& recv_data);
void HandleLfgClearAutoJoinOpcode(WorldPacket& recv_data);
@@ -687,6 +689,9 @@ class TRINITY_DLL_SPEC WorldSession
void HandleCancelTempEnchantmentOpcode(WorldPacket& recv_data);
+ void HandleItemRefundInfoRequest(WorldPacket& recv_data);
+ void HandleItemRefund(WorldPacket& recv_data);
+
void HandleChannelVoiceOnOpcode(WorldPacket & recv_data);
void HandleVoiceSessionEnableOpcode(WorldPacket& recv_data);
void HandleSetActiveVoiceChannel(WorldPacket& recv_data);
@@ -733,6 +738,7 @@ class TRINITY_DLL_SPEC WorldSession
void HandleEquipmentSetSave(WorldPacket& recv_data);
void HandleEquipmentSetDelete(WorldPacket& recv_data);
void HandleEquipmentSetUse(WorldPacket& recv_data);
+ void HandleWorldStateUITimerUpdate(WorldPacket& recv_data);
void HandleOnPVPKill(Player *killed);
bool HandleOnPlayerChat(const char *text);
uint32 HandleOnGetXP(uint32 amount);
@@ -776,4 +782,3 @@ class TRINITY_DLL_SPEC WorldSession
};
#endif
/// @}
-
diff --git a/src/game/WorldSocket.cpp b/src/game/WorldSocket.cpp
index 6991e4d112f..680d0515d61 100644
--- a/src/game/WorldSocket.cpp
+++ b/src/game/WorldSocket.cpp
@@ -255,8 +255,13 @@ int WorldSocket::open (void *a)
m_Address = remote_addr.get_host_addr ();
// Send startup packet.
- WorldPacket packet (SMSG_AUTH_CHALLENGE, 4);
+ WorldPacket packet (SMSG_AUTH_CHALLENGE, 24);
+ packet << uint32(1); // 1...31
packet << m_Seed;
+ packet << uint32(0xF3539DA3); // random data
+ packet << uint32(0x6E8547B9); // random data
+ packet << uint32(0x9A6AA2F8); // random data
+ packet << uint32(0xA4F170F4); // random data
if (SendPacket (packet) == -1)
return -1;
@@ -690,6 +695,7 @@ int WorldSocket::HandleAuthSession (WorldPacket& recvPacket)
uint8 digest[20];
uint32 clientSeed;
uint32 unk2, unk3;
+ uint64 unk4;
uint32 BuiltNumberClient;
uint32 id, security;
//uint8 expansion = 0;
@@ -717,6 +723,7 @@ int WorldSocket::HandleAuthSession (WorldPacket& recvPacket)
recvPacket >> account;
recvPacket >> unk3;
recvPacket >> clientSeed;
+ recvPacket >> unk4;
recvPacket.read (digest, 20);
DEBUG_LOG ("WorldSocket::HandleAuthSession: client %u, unk2 %u, account %s, unk3 %u, clientseed %u",
@@ -1066,4 +1073,3 @@ bool WorldSocket::iFlushPacketQueue()
return haveone;
}
-
diff --git a/src/shared/Database/SQLStorage.cpp b/src/shared/Database/SQLStorage.cpp
index 0ea5c3d826b..0b2c0ffdf84 100644
--- a/src/shared/Database/SQLStorage.cpp
+++ b/src/shared/Database/SQLStorage.cpp
@@ -27,19 +27,19 @@ extern DatabasePostgre WorldDatabase;
extern DatabaseMysql WorldDatabase;
#endif
-const char CreatureInfosrcfmt[]="iiiiiiiisssiiiiiiiiiiffiffiifiiiiiiiiiiffiiiiiiiiiiiiiiiiiiiiiiiisiiffliiiiiiiliiis";
-const char CreatureInfodstfmt[]="iiiiiiiisssiiiiiiiiiiffiffiifiiiiiiiiiiffiiiiiiiiiiiiiiiiiiiiiiiisiiffliiiiiiiliiii";
+const char CreatureInfosrcfmt[]="iiiiiiiiiisssiiiiiiiiiiffiffiifiiiiiiiiiiffiiiiiiiiiiiiiiiiiiiiiiiisiiffliiiiiiiliiis";
+const char CreatureInfodstfmt[]="iiiiiiiiiisssiiiiiiiiiiffiffiifiiiiiiiiiiffiiiiiiiiiiiiiiiiiiiiiiiisiiffliiiiiiiliiii";
const char CreatureDataAddonInfofmt[]="iiiiiiis";
const char CreatureModelfmt[]="iffbi";
const char CreatureInfoAddonInfofmt[]="iiiiiiis";
const char EquipmentInfofmt[]="iiii";
const char GameObjectInfosrcfmt[]="iiissssiifiiiiiiiiiiiiiiiiiiiiiiiiiiiiiis";
const char GameObjectInfodstfmt[]="iiissssiifiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii";
-const char ItemPrototypesrcfmt[]="iiiisiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiffiffiiiiiiiiiifiiifiiiiiifiiiiiifiiiiiifiiiiiifiiiisiiiiiiiiiiiiiiiiiiiiiiiiifiiisiiii";
-const char ItemPrototypedstfmt[]="iiiisiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiffiffiiiiiiiiiifiiifiiiiiifiiiiiifiiiiiifiiiiiifiiiisiiiiiiiiiiiiiiiiiiiiiiiiifiiiiiiii";
+const char ItemPrototypesrcfmt[]="iiiisiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiffiffiiiiiiiiiifiiifiiiiiifiiiiiifiiiiiifiiiiiifiiiisiiiiiiiiiiiiiiiiiiiiiiiiifiiisiiii";
+const char ItemPrototypedstfmt[]="iiiisiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiffiffiiiiiiiiiifiiifiiiiiifiiiiiifiiiiiifiiiiiifiiiisiiiiiiiiiiiiiiiiiiiiiiiiifiiiiiiii";
const char PageTextfmt[]="isi";
-const char InstanceTemplatesrcfmt[]="iiiiiiffffs";
-const char InstanceTemplatedstfmt[]="iiiiiiffffi";
+const char InstanceTemplatesrcfmt[]="iiiffffs";
+const char InstanceTemplatedstfmt[]="iiiffffi";
SQLStorage sCreatureStorage(CreatureInfosrcfmt, CreatureInfodstfmt, "entry","creature_template");
SQLStorage sCreatureDataAddonStorage(CreatureDataAddonInfofmt,"guid","creature_addon");
@@ -79,4 +79,3 @@ void SQLStorage::Load()
SQLStorageLoader loader;
loader.Load(*this);
}
-
diff --git a/src/trinityrealm/AuthCodes.h b/src/trinityrealm/AuthCodes.h
index 73728898503..53ae2236bcd 100644
--- a/src/trinityrealm/AuthCodes.h
+++ b/src/trinityrealm/AuthCodes.h
@@ -72,7 +72,8 @@ enum LoginResult
//2.4.3 build 8606
//3.1.3 build 9947
//3.1.3 build 10146 Chinese build
+//3.2.2a build 10505
-#define EXPECTED_TRINITY_CLIENT_BUILD {10146, 9947, 8606, 5875, 6005, 0}
+#define EXPECTED_TRINITY_CLIENT_BUILD {10505, 10146, 9947, 8606, 5875, 6005, 0}
#endif
diff --git a/src/trinityrealm/AuthSocket.cpp b/src/trinityrealm/AuthSocket.cpp
index 90a2a27d5b9..bd79fc5d207 100644
--- a/src/trinityrealm/AuthSocket.cpp
+++ b/src/trinityrealm/AuthSocket.cpp
@@ -706,7 +706,7 @@ bool AuthSocket::_HandleLogonProof()
sha.UpdateBigNumbers(&A, &M, &K, NULL);
sha.Finalize();
- if (_build == 8606 || _build == 9947 || _build == 10146)//2.4.3 and 3.1.3 clients (10146 is Chinese build for 3.1.3)
+ if (_build == 8606 || _build == 9947 || _build == 10146 || _build == 10505)//2.4.3, 3.1.3 and 3.2.2a clients (10146 is Chinese build for 3.1.3)
{
sAuthLogonProof_S proof;
memcpy(proof.M2, sha.GetDigest(), 20);
@@ -909,7 +909,7 @@ bool AuthSocket::_HandleRealmList()
RealmList built_realmList;
for (rlm = m_realmList.begin(); rlm != m_realmList.end(); ++rlm)
{
- if (_build == 8606 || _build == 9947 || _build == 10146)//2.4.3 and 3.1.3 cliens
+ if (_build == 8606 || _build == 9947 || _build == 10146 || _build == 10505)//2.4.3, 3.1.3 and 3.2.2a clients
{
if (rlm->second.gamebuild == _build)
built_realmList.AddRealm(rlm->second);
@@ -925,7 +925,7 @@ bool AuthSocket::_HandleRealmList()
///- Circle through realms in the RealmList and construct the return packet (including # of user characters in each realm)
ByteBuffer pkt;
pkt << (uint32) 0;
- if (_build == 8606 || _build == 9947 || _build == 10146)//only 2.4.3 and 3.1.3 cliens
+ if (_build == 8606 || _build == 9947 || _build == 10146 || _build == 10505)//only 2.4.3, 3.1.3 and 3.2.2a clients
pkt << (uint16) built_realmList.size();
else
pkt << (uint32) built_realmList.size();
@@ -948,7 +948,7 @@ bool AuthSocket::_HandleRealmList()
uint8 lock = (i->second.allowedSecurityLevel > _accountSecurityLevel) ? 1 : 0;
pkt << i->second.icon; // realm type
- if (i->second.gamebuild == 9947 || i->second.gamebuild == 10146 || i->second.gamebuild == 8606)//only 2.4.3 and 3.1.3 cliens
+ if (i->second.gamebuild == 10505 || i->second.gamebuild == 9947 || i->second.gamebuild == 10146 || i->second.gamebuild == 8606)//only 2.4.3, 3.1.3 and 3.2.2a clients
pkt << lock; // if 1, then realm locked
pkt << i->second.color; // if 2, then realm is offline
pkt << i->first;
@@ -956,13 +956,13 @@ bool AuthSocket::_HandleRealmList()
pkt << i->second.populationLevel;
pkt << AmountOfCharacters;
pkt << i->second.timezone; // realm category
- if (i->second.gamebuild == 9947 || i->second.gamebuild == 10146 || i->second.gamebuild == 8606)//2.4.3 and 3.1.3 clients
+ if (i->second.gamebuild == 10505 || i->second.gamebuild == 9947 || i->second.gamebuild == 10146 || i->second.gamebuild == 8606)//2.4.3, 3.1.3 and 3.2.2a clients
pkt << (uint8) 0x2C; // unk, may be realm number/id?
else
pkt << (uint8) 0x0; //1.12.1 and 1.12.2 clients
}
- if (_build == 9947 || _build == 10146 || _build == 8606)//2.4.3 and 3.1.3 cliens
+ if (_build == 10505 || _build == 9947 || _build == 10146 || _build == 8606)//2.4.3, 3.1.3 and 3.2.2a clients
{
pkt << (uint8) 0x10;
pkt << (uint8) 0x00;
diff --git a/win/VC90/game.vcproj b/win/VC90/game.vcproj
index 8266c4a7a6c..41888f323e2 100644
--- a/win/VC90/game.vcproj
+++ b/win/VC90/game.vcproj
@@ -567,6 +567,14 @@
>
</File>
<File
+ RelativePath="..\..\src\game\BattleGroundABG.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\game\BattleGroundABG.h"
+ >
+ </File>
+ <File
RelativePath="..\..\src\game\BattleGroundAV.cpp"
>
</File>
@@ -599,6 +607,14 @@
>
</File>
<File
+ RelativePath="..\..\src\game\BattleGroundIC.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\game\BattleGroundIC.h"
+ >
+ </File>
+ <File
RelativePath="..\..\src\game\BattleGroundHandler.cpp"
>
</File>