Created
July 11, 2010 14:26
-
-
Save Emtec/471587 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
diff --git a/sql/v01_vehicle_data.sql b/sql/v01_vehicle_data.sql | |
new file mode 100644 | |
index 0000000..74dc665 | |
--- /dev/null | |
+++ b/sql/v01_vehicle_data.sql | |
@@ -0,0 +1,21 @@ | |
+-- | |
+-- Table structure for table `vehicle_data` | |
+-- | |
+ | |
+DROP TABLE IF EXISTS `vehicle_data`; | |
+CREATE TABLE `vehicle_data` ( | |
+ `entry` mediumint(5) unsigned NOT NULL, | |
+ `flags` mediumint(8) unsigned NOT NULL default '0', | |
+ `Spell1` mediumint(8) unsigned NOT NULL default '0', | |
+ `Spell2` mediumint(8) unsigned NOT NULL default '0', | |
+ `Spell3` mediumint(8) unsigned NOT NULL default '0', | |
+ `Spell4` mediumint(8) unsigned NOT NULL default '0', | |
+ `Spell5` mediumint(8) unsigned NOT NULL default '0', | |
+ `Spell6` mediumint(8) unsigned NOT NULL default '0', | |
+ `Spell7` mediumint(8) unsigned NOT NULL default '0', | |
+ `Spell8` mediumint(8) unsigned NOT NULL default '0', | |
+ `Spell9` mediumint(8) unsigned NOT NULL default '0', | |
+ `Spell10` mediumint(8) unsigned NOT NULL default '0', | |
+ `req_aura` mediumint(8) unsigned NOT NULL default '0', | |
+ PRIMARY KEY (`entry`) | |
+) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=FIXED COMMENT='Vehicle System'; | |
\ No newline at end of file | |
diff --git a/sql/v02_vehicle_seat_data.sql b/sql/v02_vehicle_seat_data.sql | |
new file mode 100644 | |
index 0000000..5c3a390 | |
--- /dev/null | |
+++ b/sql/v02_vehicle_seat_data.sql | |
@@ -0,0 +1,10 @@ | |
+-- | |
+-- Table structure for table `vehicle_seat_data` | |
+-- | |
+ | |
+DROP TABLE IF EXISTS `vehicle_seat_data`; | |
+CREATE TABLE `vehicle_seat_data` ( | |
+ `seat` mediumint(5) unsigned NOT NULL, | |
+ `flags` mediumint(8) unsigned NOT NULL default '0', | |
+ PRIMARY KEY (`seat`) | |
+) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=FIXED COMMENT='Vehicle Seat System'; | |
\ No newline at end of file | |
diff --git a/sql/v03_creature_addon_tables.sql b/sql/v03_creature_addon_tables.sql | |
new file mode 100644 | |
index 0000000..7240ed4 | |
--- /dev/null | |
+++ b/sql/v03_creature_addon_tables.sql | |
@@ -0,0 +1,7 @@ | |
+ALTER TABLE creature_addon | |
+ ADD COLUMN vehicle_id smallint(5) unsigned NOT NULL default '0' AFTER moveflags, | |
+ ADD COLUMN passengers text AFTER vehicle_id; | |
+ | |
+ALTER TABLE creature_template_addon | |
+ ADD COLUMN vehicle_id smallint(5) unsigned NOT NULL default '0' AFTER moveflags, | |
+ ADD COLUMN passengers text AFTER vehicle_id; | |
\ No newline at end of file | |
diff --git a/sql/v10_vehicle_test_data.sql b/sql/v10_vehicle_test_data.sql | |
new file mode 100644 | |
index 0000000..e6aeecc | |
--- /dev/null | |
+++ b/sql/v10_vehicle_test_data.sql | |
@@ -0,0 +1,553 @@ | |
+INSERT INTO `vehicle_data` VALUES | |
+('106', '4', '50896', '0', '50652', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('116', '5', '51362', '51421', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('117', '4', '50652', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('156', '24', '53114', '0', '53110', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('200', '30', '52362', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('210', '166', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('7', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('8', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('14', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('16', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('17', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('21', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('22', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('23', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('24', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('25', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('26', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('27', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('28', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('29', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('30', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('31', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('32', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('33', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('34', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('35', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('36', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('37', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('38', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('39', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('40', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('41', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('42', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('43', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('44', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('46', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('47', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('48', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('49', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('50', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('51', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('52', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('53', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('54', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('55', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('56', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('57', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('58', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('59', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('60', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('61', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('62', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('64', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('65', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('69', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('70', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('71', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('72', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('74', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('75', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('76', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('77', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('79', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('80', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('81', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('86', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('87', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('88', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('89', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('90', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('91', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('92', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('93', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('97', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('99', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('100', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('102', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('104', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('105', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('107', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('108', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('109', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('110', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('111', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('112', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('113', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('114', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('115', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('118', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('120', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('121', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('122', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('124', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('125', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('126', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('127', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('128', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('129', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('130', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('131', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('132', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('134', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('137', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('138', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('139', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('142', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('143', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('145', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('146', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('147', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('148', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('149', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('150', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('152', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('153', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('154', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('158', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('160', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('162', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('163', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('164', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('165', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('166', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('167', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('168', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('169', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('171', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('173', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('174', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('175', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('176', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('177', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('178', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('179', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('180', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('181', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('182', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('183', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('186', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('188', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('189', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('190', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('191', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('192', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('193', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('194', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('196', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('197', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('198', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('199', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('201', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('202', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('203', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('204', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('205', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('206', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('207', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('208', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('209', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('211', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('212', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('213', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('214', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('215', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('216', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('217', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('218', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('219', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('220', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('221', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('222', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('223', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('224', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('225', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('226', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('227', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('228', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('229', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('230', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('231', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('232', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('233', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('234', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('236', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('237', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('238', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('240', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('241', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('242', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('243', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('244', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('245', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('246', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('247', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('248', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('249', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('250', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('252', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('253', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('254', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('255', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('256', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('257', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('258', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('259', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('260', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('261', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('262', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('263', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('264', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('265', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('266', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('267', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('268', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('269', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('270', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('271', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('272', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('273', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('274', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('275', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('276', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('277', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('278', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('279', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('280', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('281', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('282', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('283', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('284', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('285', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('286', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('287', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('288', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('289', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('290', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('291', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('292', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('293', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('294', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('295', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('296', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('297', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('298', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('299', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('300', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('301', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('302', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('303', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('304', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('305', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('308', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('309', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('310', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('311', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('312', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('313', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('314', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('315', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('316', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('317', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('318', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('320', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('321', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('322', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('323', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('324', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('325', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('327', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('328', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('329', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('331', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('332', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('335', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('336', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('337', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('338', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('339', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('340', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('341', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('342', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('343', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('344', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('345', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('347', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('348', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('352', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('353', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('354', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('356', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('357', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('358', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('359', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('363', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('368', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('369', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('370', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('371', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('372', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('373', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('374', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('375', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('376', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('380', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('381', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('385', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('387', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('388', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('389', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('390', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('392', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('395', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('396', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('397', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('399', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('135', '12', '52362', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), | |
+('349', '24', '62544', '62575', '62960', '62552', '64077', '62863', '0', '0', '0', '0', '62853'), | |
+('68', '24', '52435', '52576', '52588', '0', '0', '0', '0', '0', '0', '0', '0'); | |
+ | |
+UPDATE creature_template SET maxhealth = 133525, minhealth = 133525, maxmana = 51360, minmana = 51360 WHERE entry = 28670; | |
+UPDATE creature_template SET maxhealth = 50000, minhealth = 50000 WHERE entry = 28094; | |
+UPDATE creature_template SET maxhealth = 75000, minhealth = 75000 WHERE entry IN (28312,32627); | |
+UPDATE creature_template SET maxhealth = 50000, minhealth = 50000 WHERE entry IN (28319,32629); | |
+ | |
+UPDATE creature_template SET minlevel = 80, maxlevel = 80 WHERE entry IN (28312,32627,28319,32629,28094,28670); | |
+ | |
+UPDATE creature_template SET speed_run = 2, InhabitType = 1 WHERE entry IN (28312,32627,28319,32629,28094,29929,28782); | |
+UPDATE creature_template SET speed_run = 2.4, InhabitType = 4 WHERE entry IN (28670); | |
+UPDATE creature_template SET mechanic_immune_mask = 652951551 WHERE entry IN (28670,28312,32627,28319,32629,28094,29929,28782); | |
+ | |
+DELETE FROM npc_spellclick_spells WHERE npc_entry in (28670, 28312, 32629, 28319, 32627, 28094, 29929, 28782); | |
+INSERT INTO npc_spellclick_spells VALUES | |
+(28670, 52196, 0, 0, 0, 0), | |
+(28312, 60968, 0, 0, 0, 1), | |
+(32627, 60968, 0, 0, 0, 1), | |
+(28319, 60968, 0, 0, 0, 1), | |
+(32629, 60968, 0, 0, 0, 1), | |
+(28094, 60968, 0, 0, 0, 1), | |
+(29929, 58961, 0, 0, 0, 1), | |
+(28782, 52280, 12687, 1, 12687, 1); | |
+ | |
+DELETE FROM creature_template_addon WHERE entry in (28670, 28312, 32629, 28319, 32627, 28094, 29929, 28782); | |
+INSERT INTO creature_template_addon VALUES | |
+(28670, 0, 50331648, 1, 0, 1024, 156, NULL, '53112 0 53112 1'), | |
+(28312, 0, 0, 0, 0, 0, 117, '28319 7', NULL), | |
+(32627, 0, 0, 0, 0, 0, 117, '32629 7', NULL), | |
+(28319, 0, 0, 0, 0, 0, 116, NULL, NULL), | |
+(32629, 0, 0, 0, 0, 0, 116, NULL, NULL), | |
+(28094, 0, 0, 0, 0, 0, 106, NULL, NULL), | |
+(29929, 0, 0, 0, 0, 0, 210, NULL, NULL), | |
+(28782, 0, 0, 0, 0, 0, 200, NULL, NULL); | |
+ | |
+DELETE FROM vehicle_data WHERE entry in (106, 116, 117, 156, 200, 210); | |
+INSERT INTO vehicle_data VALUES (106, 4, 50896, 0, 50652, 0, 0, 0, 0, 0, 0, 0, 0), | |
+(116, 5, 51362, 51421, 0, 0, 0, 0, 0, 0, 0, 0, 0), | |
+(117, 4, 50652, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), | |
+(156, 24, 53114, 0, 53110, 0, 0, 0, 0, 0, 0, 0, 0), | |
+(200, 30, 52362, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), | |
+(210, 166, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); | |
+ | |
+DELETE FROM vehicle_seat_data WHERE seat in (1643, 1648, 1649, 1650, 1652, 1554, 1556, 1557, 1986, 1987, 2144, 2181, 2182); | |
+INSERT INTO vehicle_seat_data VALUES | |
+(1643, 3), | |
+(1648, 3), | |
+(1649, 2), | |
+(1650, 2), | |
+(1652, 4), | |
+(1554, 3), | |
+(1556, 6), | |
+(1557, 6), | |
+(1986, 3), | |
+(1987, 8), | |
+(2144, 1), | |
+(2181, 1), | |
+(2182, 0); | |
+ | |
+/* Some quests | |
+Argent tournament*/ | |
+UPDATE creature_template SET speed_run = '1.5', unit_flags = 8 WHERE entry IN (33844,33845); | |
+DELETE FROM creature_addon WHERE guid IN (SELECT guid FROM creature WHERE id IN (33844,33845)); | |
+DELETE FROM creature WHERE id IN (33844,33845); | |
+DELETE FROM vehicle_data WHERE entry in (349); | |
+INSERT INTO `vehicle_data` VALUES ('349', '24', '62544', '62575', '62960', '62552', '64077', '62863', '0', '0', '0', '0', '62853'); | |
+DELETE FROM vehicle_seat_data WHERE seat in (3129); | |
+INSERT INTO `vehicle_seat_data` VALUES ('3129', '1'); | |
+INSERT INTO `npc_spellclick_spells` VALUES ('33842', '63791', '13829', '1', '0', '3'); | |
+INSERT INTO `npc_spellclick_spells` VALUES ('33842', '63791', '13839', '1', '0', '3'); | |
+INSERT INTO `npc_spellclick_spells` VALUES ('33842', '63791', '13838', '1', '0', '3'); | |
+INSERT INTO `npc_spellclick_spells` VALUES ('33843', '63792', '13828', '1', '0', '3'); | |
+INSERT INTO `npc_spellclick_spells` VALUES ('33843', '63792', '13837', '1', '0', '3'); | |
+INSERT INTO `npc_spellclick_spells` VALUES ('33843', '63792', '13835', '1', '0', '3'); | |
+DELETE FROM creature_template_addon WHERE entry IN (33844,33845); | |
+INSERT INTO creature_template_addon (`entry`, `mount`, `bytes1`, `bytes2`, `emote`, `moveflags`, `vehicle_id`, `passengers`, `auras`) VALUES (33844, 0, 0, 2049, 0, 0, 349, '', ''); | |
+INSERT INTO creature_template_addon (`entry`, `mount`, `bytes1`, `bytes2`, `emote`, `moveflags`, `vehicle_id`, `passengers`, `auras`) VALUES (33845, 0, 0, 2049, 0, 0, 349, '', ''); | |
+ | |
+/*Quest Into the Realm of Shadows (12687)*/ | |
+UPDATE creature_template SET faction_A = 2082, faction_H = 2082, unit_flags = 0 WHERE entry = 28782; | |
+DELETE FROM creature_addon WHERE guid IN (SELECT guid FROM creature WHERE id = 28782); | |
+DELETE FROM vehicle_data WHERE entry in (135); | |
+INSERT INTO vehicle_data VALUES (135, 12, 52362, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); | |
+DELETE FROM vehicle_seat_data WHERE seat in (1871); | |
+INSERT INTO vehicle_seat_data VALUES (1871, 1); | |
+DELETE FROM npc_spellclick_spells WHERE npc_entry in (28782); | |
+INSERT INTO npc_spellclick_spells VALUES (28782, 52349, 12687, 1, 12687, 3); | |
+DELETE FROM creature_template_addon WHERE entry IN (28782); | |
+INSERT INTO creature_template_addon (`entry`, `mount`, `bytes1`, `bytes2`, `emote`, `moveflags`, `vehicle_id`, `passengers`, `auras`) VALUES (28782, 0, 0, 1, 0, 0, 135, '', ''); | |
+ | |
+/*Quest Grand Theft Palomino (12680)*/ | |
+DELETE FROM creature_addon WHERE guid IN (SELECT guid FROM creature WHERE id IN (28605,28606,28607)); | |
+REPLACE INTO spell_script_target VALUES (52264,1,28653); | |
+DELETE FROM vehicle_data WHERE entry in (123); | |
+INSERT INTO vehicle_data VALUES (123, 12, 52264, 52268, 0, 0, 0, 0, 0, 0, 0, 0, 0); | |
+DELETE FROM vehicle_seat_data WHERE seat in (1782); | |
+INSERT INTO vehicle_seat_data VALUES (1782, 1); | |
+DELETE FROM npc_spellclick_spells WHERE npc_entry in (28605,28606,28607); | |
+INSERT INTO npc_spellclick_spells VALUES (28605, 52263, 12680, 1, 12680, 3); | |
+INSERT INTO npc_spellclick_spells VALUES (28606, 52263, 12680, 1, 12680, 3); | |
+INSERT INTO npc_spellclick_spells VALUES (28607, 52263, 12680, 1, 12680, 3); | |
+DELETE FROM creature_template_addon WHERE entry IN (28605,28606,28607); | |
+INSERT INTO creature_template_addon (`entry`, `mount`, `bytes1`, `bytes2`, `emote`, `moveflags`, `vehicle_id`, `passengers`, `auras`) VALUES (28605, 0, 0, 1, 0, 0, 123, '', ''); | |
+INSERT INTO creature_template_addon (`entry`, `mount`, `bytes1`, `bytes2`, `emote`, `moveflags`, `vehicle_id`, `passengers`, `auras`) VALUES (28606, 0, 0, 1, 0, 0, 123, '', ''); | |
+INSERT INTO creature_template_addon (`entry`, `mount`, `bytes1`, `bytes2`, `emote`, `moveflags`, `vehicle_id`, `passengers`, `auras`) VALUES (28607, 0, 0, 1, 0, 0, 123, '', ''); | |
+ | |
+/*Quest Going Bearback*/ | |
+DELETE FROM npc_spellclick_spells WHERE npc_entry in (29598); | |
+INSERT INTO npc_spellclick_spells VALUES (29598, 54908, 12851, 1, 12851, 1); | |
+DELETE FROM creature_template_addon WHERE entry IN (29598); | |
+INSERT INTO creature_template_addon (`entry`, `mount`, `bytes1`, `bytes2`, `emote`, `moveflags`, `vehicle_id`, `passengers`, `auras`) VALUES (29598, 0, 0, 1, 0, 0, 308, '', ''); | |
+DELETE FROM vehicle_data WHERE entry in (308); | |
+INSERT INTO `vehicle_data` VALUES ('308', '24', '54897', '54907', '0', '0', '0', '0', '0', '0', '0', '0', '0'); | |
+REPLACE INTO vehicle_seat_data VALUES (2699, 3); | |
+ | |
+/*Mamonth*/ | |
+DELETE FROM creature_template_addon WHERE entry in (32633,32640); | |
+INSERT INTO creature_template_addon (`entry`, `mount`, `bytes1`, `bytes2`, `emote`, `moveflags`, `vehicle_id`, `passengers`, `auras`) VALUES (32633, 0, 0, 1, 0, 0, 312, '', ''); | |
+INSERT INTO creature_template_addon (`entry`, `mount`, `bytes1`, `bytes2`, `emote`, `moveflags`, `vehicle_id`, `passengers`, `auras`) VALUES (32640, 0, 0, 1, 0, 0, 312, '', ''); | |
+DELETE FROM vehicle_data WHERE entry in (312); | |
+ | |
+/*Massacre At Light's Point*/ | |
+UPDATE `creature_template` SET `minhealth` = 26140, `maxhealth` = 26140, `dynamicflags` = 0, `minmana` = 2117, `maxmana` = 2117, `unit_flags` = 772, `minlevel` = 55, `maxlevel` = 55, `unk16` = 10, `unk17` = 1, `InhabitType` = 3, `scale` = 1, `mindmg` = 685, `maxdmg` = 715, `armor` = 3232, `attackpower` = 214, `unit_class` = 2, `type` = 10 WHERE `entry` = 28833; | |
+UPDATE `creature_template` SET `minhealth` = 26140, `maxhealth` = 26140, `dynamicflags` = 0, `minmana` = 0, `maxmana` = 0, `unit_flags` = 772, `minlevel` = 55, `maxlevel` = 55, `unk16` = 10, `unk17` = 1, `InhabitType` = 3, `scale` = 1, `mindmg` = 685, `maxdmg` = 715, `armor` = 3232, `attackpower` = 214, `unit_class` = 2, `type` = 10 WHERE `entry` = 28887; | |
+ | |
+DELETE FROM creature_addon WHERE guid IN (SELECT guid FROM creature WHERE id IN (28887,28833)); | |
+DELETE FROM vehicle_data WHERE entry in (68); | |
+INSERT INTO `vehicle_data` VALUES ('68', '24', '52435', '52576', '52588', '0', '0', '0', '0', '0', '0', '0', '0'); | |
+DELETE FROM vehicle_seat_data WHERE seat in (1301); | |
+INSERT INTO `vehicle_seat_data` VALUES ('1301', '3'); | |
+INSERT INTO `npc_spellclick_spells` VALUES ('28833', '52447', '12701', '1', '12701', '1'); | |
+INSERT INTO `npc_spellclick_spells` VALUES ('28887', '52447', '12701', '1', '12701', '1'); | |
+ | |
+DELETE FROM creature_template_addon WHERE entry IN (28887,28833); | |
+INSERT INTO creature_template_addon (`entry`, `mount`, `bytes1`, `bytes2`, `emote`, `moveflags`, `vehicle_id`, `passengers`, `auras`) VALUES (28887, 0, 0, 2049, 0, 0, 68, '', ''); | |
+INSERT INTO creature_template_addon (`entry`, `mount`, `bytes1`, `bytes2`, `emote`, `moveflags`, `vehicle_id`, `passengers`, `auras`) VALUES (28833, 0, 0, 2049, 0, 0, 68, '', ''); | |
+ | |
+ | |
+ | |
+/*Traveler's Tundra Mammoth */ | |
+REPLACE INTO npc_spellclick_spells VALUES (32633, 52196, 0, 0, 0, 0); | |
+REPLACE INTO creature_template_addon VALUES (32633, 0, 0, 0, 0, 0, 312, NULL, NULL); | |
+REPLACE INTO vehicle_data VALUES (312, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); | |
+ | |
+/* Grand Ice Mammoth */ | |
+REPLACE INTO npc_spellclick_spells VALUES (31857, 52196, 0, 0, 0, 0); | |
+REPLACE INTO creature_template_addon VALUES (31857, 0, 0, 0, 0, 0, 312, NULL, NULL); | |
+ | |
+/* Salvaged Chopper */ | |
+REPLACE INTO npc_spellclick_spells VALUES (33062, 52196, 0, 0, 0, 0); | |
+REPLACE INTO creature_template_addon VALUES (33062, 0, 0, 0, 0, 0, 335, NULL, NULL); | |
+REPLACE INTO vehicle_data VALUES (335, 12, 62974, 62286, 62299, 64660, 0, 0, 0, 0, 0, 0, 0); | |
+REPLACE INTO vehicle_seat_data VALUES (3005, 1); | |
+ | |
+/* Salvaged Demolisher */ | |
+REPLACE INTO npc_spellclick_spells VALUES (33109, 52196, 0, 0, 0, 0); | |
+REPLACE INTO creature_template_addon VALUES (33109, 0, 0, 0, 0, 0, 338, NULL, NULL); | |
+REPLACE INTO vehicle_data VALUES (338, 12, 62306, 62490, 62308, 62324, 0, 0, 0, 0, 0, 0, 0); | |
+REPLACE INTO vehicle_seat_data VALUES (3011, 1),(3005, 1),(3004, 2); | |
+ | |
+/* Salvaged Siege Engine */ | |
+REPLACE INTO npc_spellclick_spells VALUES (33060, 52196, 0, 0, 0, 0); | |
+REPLACE INTO creature_template_addon VALUES (33060, 0, 0, 0, 0, 0, 336, NULL, NULL); | |
+REPLACE INTO vehicle_data VALUES (336, 12, 62345, 62522, 62346, 0, 0, 0, 0, 0, 0, 0, 0); | |
+REPLACE INTO vehicle_seat_data VALUES (3006, 1); | |
+ | |
+/* Wintergrasp Tower Cannon */ | |
+DELETE FROM npc_spellclick_spells WHERE npc_entry IN (28366); | |
+INSERT INTO npc_spellclick_spells VALUES (28366, 60968, 0, 0, 0, 1); | |
+REPLACE INTO creature_template_addon VALUES (28366, 0, 0, 0, 0, 0, 160, NULL, NULL); | |
+REPLACE INTO vehicle_data VALUES (160, 5, 51362, 51421, 0, 0, 0, 0, 0, 0, 0, 0, 0); | |
+REPLACE INTO vehicle_seat_data VALUES (2029, 1); | |
+ | |
+/* Salvaged Siege Turret */ | |
+DELETE FROM npc_spellclick_spells WHERE npc_entry = 33067; | |
+INSERT INTO npc_spellclick_spells VALUES (33067, 67373, 0, 0, 0, 1); | |
+REPLACE INTO creature_template_addon VALUES (33067, 0, 0, 0, 0, 0, 337, NULL, NULL); | |
+REPLACE INTO vehicle_data VALUES (337, 5, 62358, 64677, 62359, 0, 0, 0, 0, 0, 0, 0, 0); | |
+REPLACE INTO vehicle_data VALUES (336, 4, 62345, 62522, 62346, 0, 0, 0, 0, 0, 0, 0, 0); | |
+REPLACE INTO vehicle_seat_data VALUES (3006, 1),(3010, 1),(4026, 8),(4027, 8),(3009, 8); | |
+UPDATE `creature_template` SET `minhealth` = 1134000, `maxhealth` = 1134000 WHERE `entry` = 33067; | |
+UPDATE `creature_template` SET `unit_flags` = 16384 WHERE `entry` = 33067; | |
+DELETE FROM `creature` WHERE `id`= 33067; | |
+ | |
+/* Gunner Salvaged Demolisher */ | |
+DELETE FROM npc_spellclick_spells WHERE npc_entry IN (33167); | |
+INSERT INTO npc_spellclick_spells VALUES (33167, 67373, 0, 0, 0, 1); | |
+REPLACE INTO creature_template_addon VALUES (33167, 0, 0, 0, 0, 0, 345, NULL, NULL); | |
+REPLACE INTO vehicle_data VALUES (345, 5, 62634, 64979, 62479, 62471, 0, 62428, 0, 0, 0, 0, 0); | |
+REPLACE INTO vehicle_data VALUES (338, 4, 62306, 62490, 62308, 62324, 0, 0, 0, 0, 0, 0, 0); | |
+REPLACE INTO vehicle_seat_data VALUES (3077, 1),(3106, 8); | |
+REPLACE INTO vehicle_seat_data VALUES (3011, 1),(3146, 8),(3013, 8),(3147, 8); | |
+UPDATE `creature_template` SET `unit_flags` = 16384 WHERE `entry` = 33167; | |
+UPDATE `creature_template` SET `minhealth` = 630000, `maxhealth` = 630000 WHERE `entry` = 33167; | |
+DELETE FROM `creature` WHERE `id`=33167; | |
+ | |
+/* Massacre At Light's Point */ | |
+DELETE FROM creature_addon WHERE guid IN (SELECT guid FROM creature WHERE id IN (28887, 28833, 28864)); | |
+DELETE FROM vehicle_data WHERE entry IN (25, 79); | |
+INSERT INTO vehicle_data VALUES (25, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0),(79, 5, 52435, 52576, 52588, 0, 0, 0, 0, 0, 0, 0, 0); | |
+DELETE FROM vehicle_seat_data WHERE seat IN (1427, 341); | |
+INSERT INTO vehicle_seat_data VALUES (1427, 1),(341, 1); | |
+DELETE FROM npc_spellclick_spells WHERE npc_entry IN (28887, 28833, 28864); | |
+INSERT INTO npc_spellclick_spells VALUES (28833, 52447, 12701, 1, 12701, 1),(28887, 52447, 12701, 1, 12701, 1),(28864, 67373, 0, 0, 0, 1); | |
+DELETE FROM creature_template_addon WHERE entry IN (28887, 28833, 28864); | |
+INSERT INTO creature_template_addon VALUES (28887, 0, 0, 2049, 0, 0, 79, '', ''),(28833, 0, 0, 2049, 0, 0, 79, '', ''),(28864,0,0,0,0,0,25,NULL,'61453 0 61453 2'); | |
+ | |
+DELETE FROM creature_template_addon WHERE entry = 28670; | |
+INSERT INTO creature_template_addon VALUES (28670, 0, 50331648, 1, 0, 1024, 156, NULL, '53112 0 53112 1 53112 2'); | |
+UPDATE creature_template SET InhabitType = 3 WHERE entry = 28670; | |
+ | |
+/* the Oculus */ | |
+DELETE FROM spell_script_target where entry IN (49460, 49346, 49464); | |
+DELETE FROM npc_spellclick_spells where npc_entry IN (27755, 27692, 27756); | |
+DELETE FROM creature_template_addon where entry IN (27755, 27692, 27756); | |
+/* Amber Drake */ | |
+INSERT INTO spell_script_target VALUES (49460, 1, 27755); | |
+INSERT INTO npc_spellclick_spells VALUES (27755, 49459, 0, 0, 0, 1); | |
+INSERT INTO creature_template_addon VALUES (27755, 0, 0, 0, 0, 0, 29, NULL, '53112 0 53112 1'); | |
+REPLACE INTO vehicle_data VALUES (29, 12, 49840, 49838, 49592, 0, 0, 0, 0, 0, 0, 0, 0); | |
+REPLACE INTO vehicle_seat_data VALUES (422, 3); | |
+/* Emerald Drake */ | |
+INSERT INTO spell_script_target VALUES (49346, 1, 27692); | |
+INSERT INTO npc_spellclick_spells VALUES (27692, 49427, 0, 0, 0, 1); | |
+INSERT INTO creature_template_addon VALUES (27692, 0, 0, 0, 0, 0, 39, NULL, '53112 0 53112 1'); | |
+REPLACE INTO vehicle_data VALUES (39, 12, 50328, 50341, 50344, 0, 0, 0, 0, 0, 0, 0, 0); | |
+REPLACE INTO vehicle_seat_data VALUES (662, 3); | |
+/* Ruby Drake */ | |
+INSERT INTO spell_script_target VALUES (49464, 1, 27756); | |
+INSERT INTO npc_spellclick_spells VALUES (27756, 49463, 0, 0, 0, 1); | |
+INSERT INTO creature_template_addon VALUES (27756, 0, 0, 0, 0, 0, 43, NULL, '53112 0 53112 1'); | |
+REPLACE INTO vehicle_data VALUES (43, 12, 50232, 50248, 50240, 0, 0, 0, 0, 0, 0, 0, 0); | |
+REPLACE INTO vehicle_seat_data VALUES (742, 3); | |
\ No newline at end of file | |
diff --git a/src/game/AggressorAI.cpp b/src/game/AggressorAI.cpp | |
index 2cb7606..2fb5d75 100644 | |
--- a/src/game/AggressorAI.cpp | |
+++ b/src/game/AggressorAI.cpp | |
@@ -103,7 +103,7 @@ void AggressorAI::EnterEvadeMode() | |
//i_tracker.Reset(TIME_INTERVAL_LOOK); | |
} | |
- if (!m_creature->isCharmed()) | |
+ if(!m_creature->isCharmed() && !m_creature->GetVehicleGUID()) | |
{ | |
m_creature->RemoveAllAuras(); | |
diff --git a/src/game/BattleGroundMgr.cpp b/src/game/BattleGroundMgr.cpp | |
index a735417..206da8d 100644 | |
--- a/src/game/BattleGroundMgr.cpp | |
+++ b/src/game/BattleGroundMgr.cpp | |
@@ -1345,11 +1345,15 @@ void BattleGroundMgr::BuildPvpLogDataPacket(WorldPacket *data, BattleGround *bg) | |
*data << (uint32)0x00000001; // count of next fields | |
*data << (uint32)((BattleGroundEYScore*)itr->second)->FlagCaptures; // flag captures | |
break; | |
+ case BATTLEGROUND_SA: | |
+ *data << (uint32)0x00000002; // count of next fields | |
+ *data << (uint32)((BattleGroundSAScore*)itr->second)->DemolishersDestroyed; // demolishers destroyed | |
+ *data << (uint32)((BattleGroundSAScore*)itr->second)->GatesDestroyed; // gates destroyed | |
+ break; | |
case BATTLEGROUND_NA: | |
case BATTLEGROUND_BE: | |
case BATTLEGROUND_AA: | |
case BATTLEGROUND_RL: | |
- case BATTLEGROUND_SA: // wotlk | |
case BATTLEGROUND_DS: // wotlk | |
case BATTLEGROUND_RV: // wotlk | |
case BATTLEGROUND_IC: // wotlk | |
diff --git a/src/game/BattleGroundSA.h b/src/game/BattleGroundSA.h | |
index 31a3ffa..9324999 100644 | |
--- a/src/game/BattleGroundSA.h | |
+++ b/src/game/BattleGroundSA.h | |
@@ -24,8 +24,10 @@ class BattleGround; | |
class BattleGroundSAScore : public BattleGroundScore | |
{ | |
public: | |
- BattleGroundSAScore() {}; | |
+ BattleGroundSAScore(): DemolishersDestroyed(0), GatesDestroyed(0) {}; | |
virtual ~BattleGroundSAScore() {}; | |
+ uint32 DemolishersDestroyed; | |
+ uint32 GatesDestroyed; | |
}; | |
class BattleGroundSA : public BattleGround | |
diff --git a/src/game/Chat.cpp b/src/game/Chat.cpp | |
index 8dc9148..ee7f905 100644 | |
--- a/src/game/Chat.cpp | |
+++ b/src/game/Chat.cpp | |
@@ -497,6 +497,8 @@ ChatCommand * ChatHandler::getCommandTable() | |
{ "spell_scripts", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadSpellScriptsCommand, "", NULL }, | |
{ "spell_target_position", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadSpellTargetPositionCommand, "", NULL }, | |
{ "spell_threats", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadSpellThreatsCommand, "", NULL }, | |
+ { "vehicle_data", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadVehicleDataCommand, "", NULL }, | |
+ { "vehicle_seat_data", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadVehicleSeatDataCommand, "", NULL }, | |
{ NULL, 0, false, NULL, "", NULL } | |
}; | |
@@ -1815,7 +1817,7 @@ Creature* ChatHandler::getSelectedCreature() | |
if(!m_session) | |
return NULL; | |
- return m_session->GetPlayer()->GetMap()->GetCreatureOrPetOrVehicle(m_session->GetPlayer()->GetSelection()); | |
+ return ObjectAccessor::GetCreatureOrPetOrVehicle(*m_session->GetPlayer(),m_session->GetPlayer()->GetSelection()); | |
} | |
char* ChatHandler::extractKeyFromLink(char* text, char const* linkType, char** something1) | |
diff --git a/src/game/Chat.h b/src/game/Chat.h | |
index b82899e..daa5170 100644 | |
--- a/src/game/Chat.h | |
+++ b/src/game/Chat.h | |
@@ -405,6 +405,8 @@ class ChatHandler | |
bool HandleReloadSpellTargetPositionCommand(const char* args); | |
bool HandleReloadSpellThreatsCommand(const char* args); | |
bool HandleReloadSpellPetAurasCommand(const char* args); | |
+ bool HandleReloadVehicleDataCommand(const char* args); | |
+ bool HandleReloadVehicleSeatDataCommand(const char* args); | |
bool HandleResetAchievementsCommand(const char * args); | |
bool HandleResetAllCommand(const char * args); | |
diff --git a/src/game/Creature.cpp b/src/game/Creature.cpp | |
index ee759fd..be296fa 100644 | |
--- a/src/game/Creature.cpp | |
+++ b/src/game/Creature.cpp | |
@@ -43,6 +43,7 @@ | |
#include "GridNotifiers.h" | |
#include "GridNotifiersImpl.h" | |
#include "CellImpl.h" | |
+#include "Vehicle.h" | |
// apply implementation of the singletons | |
#include "Policies/SingletonImp.h" | |
@@ -1129,7 +1130,7 @@ bool Creature::CreateFromProto(uint32 guidlow, uint32 Entry, uint32 team, const | |
} | |
m_originalEntry = Entry; | |
- Object::_Create(guidlow, Entry, HIGHGUID_UNIT); | |
+ Object::_Create(guidlow, Entry, HIGHGUID_UNIT); | |
if (!UpdateEntry(Entry, team, data, false)) | |
return false; | |
@@ -1351,6 +1352,8 @@ void Creature::setDeathState(DeathState s) | |
} | |
Unit::setDeathState(CORPSE); | |
+ if(isVehicle()) | |
+ ((Vehicle*)this)->Die(); | |
} | |
if (s == JUST_ALIVED) | |
{ | |
@@ -1454,6 +1457,32 @@ bool Creature::IsImmunedToSpellEffect(SpellEntry const* spellInfo, SpellEffectIn | |
return true; | |
} | |
+ // Heal immunity | |
+ if (isVehicle() && !(((Vehicle*)this)->GetVehicleFlags() & VF_CAN_BE_HEALED)) | |
+ { | |
+ switch(spellInfo->Effect[index]) | |
+ { | |
+ case SPELL_EFFECT_APPLY_AURA: | |
+ switch(spellInfo->EffectApplyAuraName[index]) | |
+ { | |
+ case SPELL_AURA_PERIODIC_HEAL: | |
+ case SPELL_AURA_OBS_MOD_HEALTH: | |
+ case SPELL_AURA_PERIODIC_HEALTH_FUNNEL: | |
+ case SPELL_AURA_MOD_REGEN: | |
+ return true; | |
+ default: break; | |
+ } | |
+ break; | |
+ case SPELL_EFFECT_HEAL: | |
+ case SPELL_EFFECT_HEAL_MAX_HEALTH: | |
+ // NOTE : this too? | |
+ case SPELL_EFFECT_HEAL_MECHANICAL: | |
+ case SPELL_EFFECT_HEAL_PCT: | |
+ return true; | |
+ default : break; | |
+ } | |
+ } | |
+ | |
return Unit::IsImmunedToSpellEffect(spellInfo, index); | |
} | |
@@ -1977,6 +2006,29 @@ bool Creature::IsInEvadeMode() const | |
return !i_motionMaster.empty() && i_motionMaster.GetCurrentMovementGeneratorType() == HOME_MOTION_TYPE; | |
} | |
+float Creature::GetBaseSpeed() const | |
+{ | |
+ if( isPet() ) | |
+ { | |
+ switch( ((Pet*)this)->getPetType() ) | |
+ { | |
+ case SUMMON_PET: | |
+ case HUNTER_PET: | |
+ { | |
+ //fixed speed fur hunter (and summon!?) pets | |
+ return 1.15; | |
+ } | |
+ case GUARDIAN_PET: | |
+ case MINI_PET: | |
+ { | |
+ //speed of CreatureInfo for guardian- and minipets | |
+ break; | |
+ } | |
+ } | |
+ } | |
+ return m_creatureInfo->speed_run; | |
+} | |
+ | |
bool Creature::HasSpell(uint32 spellID) const | |
{ | |
uint8 i; | |
diff --git a/src/game/Creature.h b/src/game/Creature.h | |
index 23d47e5..89e4514 100644 | |
--- a/src/game/Creature.h | |
+++ b/src/game/Creature.h | |
@@ -212,6 +212,15 @@ struct CreatureDataAddonAura | |
SpellEffectIndex effect_idx; | |
}; | |
+struct CreatureDataAddonPassengers | |
+{ | |
+ CreatureDataAddonPassengers() : entry(0), guid(0), seat_idx(-1) {} | |
+ | |
+ uint32 entry; | |
+ uint32 guid; | |
+ int8 seat_idx; | |
+}; | |
+ | |
// from `creature_addon` table | |
struct CreatureDataAddon | |
{ | |
@@ -220,7 +229,9 @@ struct CreatureDataAddon | |
uint32 bytes1; | |
uint32 bytes2; | |
uint32 emote; | |
- uint32 splineFlags; | |
+ uint32 splineFlags; | |
+ uint32 vehicle_id; | |
+ CreatureDataAddonPassengers const* passengers; // loaded as char* "entry1 seatid1 entry2 seatid2 ... " | |
CreatureDataAddonAura const* auras; // loaded as char* "spell1 eff1 spell2 eff2 ... " | |
}; | |
@@ -400,6 +411,9 @@ class MANGOS_DLL_SPEC Creature : public Unit | |
void GetRespawnCoord(float &x, float &y, float &z, float* ori = NULL, float* dist =NULL) const; | |
uint32 GetEquipmentId() const { return m_equipmentId; } | |
+ bool CreateVehicleKit(uint32 id); | |
+ Vehicle *GetVehicleKit()const { return m_vehicleKit; } | |
+ | |
CreatureSubtype GetSubtype() const { return m_subtype; } | |
bool isPet() const { return m_subtype == CREATURE_SUBTYPE_PET; } | |
bool isVehicle() const { return m_subtype == CREATURE_SUBTYPE_VEHICLE; } | |
@@ -570,6 +584,7 @@ class MANGOS_DLL_SPEC Creature : public Unit | |
MovementGeneratorType GetDefaultMovementType() const { return m_defaultMovementType; } | |
void SetDefaultMovementType(MovementGeneratorType mgt) { m_defaultMovementType = mgt; } | |
+ float GetBaseSpeed() const; | |
// for use only in LoadHelper, Map::Add Map::CreatureCellRelocation | |
Cell const& GetCurrentCell() const { return m_currentCell; } | |
@@ -681,7 +696,7 @@ class MANGOS_DLL_SPEC Creature : public Unit | |
float CombatStartX; | |
float CombatStartY; | |
float CombatStartZ; | |
- | |
+ Vehicle* m_vehicleKit; | |
float m_summonXpoint; | |
float m_summonYpoint; | |
float m_summonZpoint; | |
diff --git a/src/game/CreatureAI.cpp b/src/game/CreatureAI.cpp | |
index 33cb568..f14bf62 100644 | |
--- a/src/game/CreatureAI.cpp | |
+++ b/src/game/CreatureAI.cpp | |
@@ -26,6 +26,10 @@ CreatureAI::~CreatureAI() | |
void CreatureAI::AttackedBy( Unit* attacker ) | |
{ | |
+ // vehicle dont have threat list, so this is unnecessary, because it calls move chase | |
+ if(m_creature->isVehicle()) | |
+ return; | |
+ | |
if(!m_creature->getVictim()) | |
AttackStart(attacker); | |
} | |
diff --git a/src/game/CreatureAISelector.cpp b/src/game/CreatureAISelector.cpp | |
index 87eb1fe..5b5dfbc 100644 | |
--- a/src/game/CreatureAISelector.cpp | |
+++ b/src/game/CreatureAISelector.cpp | |
@@ -47,7 +47,7 @@ namespace FactorySelector | |
// excplicit check for isControlled() and owner type to allow guardian, mini-pets and pets controlled by NPCs to be scripted by EventAI | |
Unit *owner=NULL; | |
if ((creature->isPet() && ((Pet*)creature)->isControlled() && | |
- ((owner=creature->GetOwner()) && owner->GetTypeId()==TYPEID_PLAYER)) || creature->isCharmed()) | |
+ ((owner=creature->GetOwner()) && owner->GetTypeId()==TYPEID_PLAYER)) || (creature->isCharmed() && !creature->isVehicle())) | |
ai_factory = ai_registry.GetRegistryItem("PetAI"); | |
else if (creature->isTotem()) | |
ai_factory = ai_registry.GetRegistryItem("TotemAI"); | |
diff --git a/src/game/CreatureEventAI.cpp b/src/game/CreatureEventAI.cpp | |
index 65cfedd..4ab3f69 100644 | |
--- a/src/game/CreatureEventAI.cpp | |
+++ b/src/game/CreatureEventAI.cpp | |
@@ -847,6 +847,7 @@ void CreatureEventAI::JustReachedHome() | |
void CreatureEventAI::EnterEvadeMode() | |
{ | |
+ m_creature->ExitVehicle(); | |
m_creature->RemoveAllAuras(); | |
m_creature->DeleteThreatList(); | |
m_creature->CombatStop(true); | |
diff --git a/src/game/DBCStructure.h b/src/game/DBCStructure.h | |
index 07d40a2..185a726 100644 | |
--- a/src/game/DBCStructure.h | |
+++ b/src/game/DBCStructure.h | |
@@ -1725,7 +1725,7 @@ struct VehicleEntry | |
uint32 m_uiLocomotionType; // 34 | |
float m_msslTrgtImpactTexRadius; // 35 | |
uint32 m_uiSeatIndicatorType; // 36 | |
- // 37, new in 3.1 | |
+ uint32 m_powerType; // 37, new in 3.1 // 37, new in 3.1 | |
// 38, new in 3.1 | |
// 39, new in 3.1 | |
}; | |
@@ -1779,6 +1779,8 @@ struct VehicleSeatEntry | |
int32 m_uiSkin; // 44 | |
uint32 m_flagsB; // 45 | |
// 46-57 added in 3.1, floats mostly | |
+ | |
+ bool IsUsable() const { return m_flags & 0x2000000; } | |
}; | |
struct WMOAreaTableEntry | |
diff --git a/src/game/DBCfmt.h b/src/game/DBCfmt.h | |
index 3538095..ff83d03 100644 | |
--- a/src/game/DBCfmt.h | |
+++ b/src/game/DBCfmt.h | |
@@ -104,7 +104,7 @@ const char TaxiNodesEntryfmt[]="nifffssssssssssssssssxii"; | |
const char TaxiPathEntryfmt[]="niii"; | |
const char TaxiPathNodeEntryfmt[]="diiifffiiii"; | |
const char TotemCategoryEntryfmt[]="nxxxxxxxxxxxxxxxxxii"; | |
-const char VehicleEntryfmt[]="niffffiiiiiiiifffffffffffffffssssfifixxx"; | |
+const char VehicleEntryfmt[]="niffffiiiiiiiifffffffffffffffssssfifiixx"; | |
const char VehicleSeatEntryfmt[]="niiffffffffffiiiiiifffffffiiifffiiiiiiiffiiiiixxxxxxxxxxxx"; | |
const char WMOAreaTableEntryfmt[]="niiixxxxxiixxxxxxxxxxxxxxxxx"; | |
const char WorldMapAreaEntryfmt[]="xinxffffixx"; | |
diff --git a/src/game/GameObject.cpp b/src/game/GameObject.cpp | |
index 0834d18..94580b0 100644 | |
--- a/src/game/GameObject.cpp | |
+++ b/src/game/GameObject.cpp | |
@@ -418,11 +418,7 @@ void GameObject::Update(uint32 /*p_time*/) | |
if(!m_respawnDelayTime) | |
return; | |
- if(!m_spawnedByDefault) | |
- { | |
- m_respawnTime = 0; | |
- return; | |
- } | |
+ m_respawnTime = m_spawnedByDefault ? time(NULL) + m_respawnDelayTime : 0; | |
// since pool system can fail to roll unspawned object, this one can remain spawned, so must set respawn nevertheless | |
m_respawnTime = time(NULL) + m_respawnDelayTime; | |
@@ -1515,6 +1511,18 @@ bool GameObject::IsFriendlyTo(Unit const* unit) const | |
// common faction based case (GvC,GvP) | |
return tester_faction->IsFriendlyTo(*target_faction); | |
} | |
+void GameObject::DealSiegeDamage(uint32 damage) | |
+{ | |
+ m_actualHealth -= damage; | |
+ | |
+ // TODO : there are a lot of thinghts to do here | |
+ if(m_actualHealth < 0) | |
+ { | |
+ m_actualHealth = GetGOInfo()->destructibleBuilding.intactNumHits; | |
+ SetLootState(GO_JUST_DEACTIVATED); | |
+ } | |
+} | |
+ | |
float GameObject::GetObjectBoundingRadius() const | |
{ | |
@@ -1525,4 +1533,4 @@ float GameObject::GetObjectBoundingRadius() const | |
return fabs(dispEntry->unknown12) * GetObjectScale(); | |
return DEFAULT_WORLD_OBJECT_SIZE; | |
-} | |
\ No newline at end of file | |
+} | |
diff --git a/src/game/GameObject.h b/src/game/GameObject.h | |
index d7a9ee6..d77b23a 100644 | |
--- a/src/game/GameObject.h | |
+++ b/src/game/GameObject.h | |
@@ -706,12 +706,14 @@ class MANGOS_DLL_SPEC GameObject : public WorldObject | |
GridReference<GameObject> &GetGridRef() { return m_gridRef; } | |
uint64 GetRotation() const { return m_rotation; } | |
+ void DealSiegeDamage(uint32 damage); | |
protected: | |
uint32 m_spellId; | |
time_t m_respawnTime; // (secs) time of next respawn (or despawn if GO have owner()), | |
uint32 m_respawnDelayTime; // (secs) if 0 then current GO state no dependent from timer | |
LootState m_lootState; | |
bool m_spawnedByDefault; | |
+ int32 m_actualHealth; // current health state | |
time_t m_cooldownTime; // used as internal reaction delay time store (not state change reaction). | |
// For traps this: spell casting cooldown, for doors/buttons: reset time. | |
std::list<uint32> m_SkillupList; | |
diff --git a/src/game/GridNotifiers.cpp b/src/game/GridNotifiers.cpp | |
index da6aa90..d0d360d 100644 | |
--- a/src/game/GridNotifiers.cpp | |
+++ b/src/game/GridNotifiers.cpp | |
@@ -92,7 +92,12 @@ VisibleNotifier::Notify() | |
{ | |
// target aura duration for caster show only if target exist at caster client | |
if ((*vItr) != &player && (*vItr)->isType(TYPEMASK_UNIT)) | |
+ { | |
player.SendAurasForTarget((Unit*)(*vItr)); | |
+ WorldPacket data; | |
+ ((Unit*)(*vItr))->BuildHeartBeatMsg(&data); | |
+ player.GetSession()->SendPacket(&data); | |
+ } | |
// non finished movements show to player | |
if ((*vItr)->GetTypeId()==TYPEID_UNIT && ((Creature*)(*vItr))->isAlive()) | |
diff --git a/src/game/Group.h b/src/game/Group.h | |
index ea8d737..eef86a7 100644 | |
--- a/src/game/Group.h | |
+++ b/src/game/Group.h | |
@@ -115,7 +115,8 @@ enum GroupUpdateFlags | |
GROUP_UPDATE_FLAG_PET_AURAS = 0x00040000, // uint64 mask, for each bit set uint32 spellid + uint8 unk, pet auras... | |
GROUP_UPDATE_FLAG_VEHICLE_SEAT = 0x00080000, // uint32 vehicle_seat_id (index from VehicleSeat.dbc) | |
GROUP_UPDATE_PET = 0x0007FC00, // all pet flags | |
- GROUP_UPDATE_FULL = 0x0007FFFF, // all known flags | |
+ GROUP_UPDATE_VEHICLE = 0x000FFC00, // all vehicle flags | |
+ GROUP_UPDATE_FULL = 0x000FFFFF, // all known flags | |
}; | |
#define GROUP_UPDATE_FLAGS_COUNT 20 | |
diff --git a/src/game/GroupHandler.cpp b/src/game/GroupHandler.cpp | |
index d73b233..46f7897 100644 | |
--- a/src/game/GroupHandler.cpp | |
+++ b/src/game/GroupHandler.cpp | |
@@ -28,6 +28,7 @@ | |
#include "Group.h" | |
#include "SocialMgr.h" | |
#include "Util.h" | |
+#include "Vehicle.h" | |
/* differeces from off: | |
-you can uninvite yourself - is is useful | |
@@ -711,7 +712,7 @@ void WorldSession::BuildPartyMemberStatsChangedPacket(Player *player, WorldPacke | |
} | |
} | |
- Pet *pet = player->GetPet(); | |
+ Unit *pet = player->GetCharmOrPet(); | |
if (mask & GROUP_UPDATE_FLAG_PET_GUID) | |
{ | |
if(pet) | |
@@ -794,6 +795,11 @@ void WorldSession::BuildPartyMemberStatsChangedPacket(Player *player, WorldPacke | |
else | |
*data << uint64(0); | |
} | |
+ | |
+ if (mask & GROUP_UPDATE_FLAG_VEHICLE_SEAT) | |
+ { | |
+ *data << (uint32) player->m_movementInfo.GetTransportDBCSeat(); | |
+ } | |
} | |
/*this procedure handles clients CMSG_REQUEST_PARTY_MEMBER_STATS request*/ | |
@@ -815,7 +821,7 @@ void WorldSession::HandleRequestPartyMemberStatsOpcode( WorldPacket &recv_data ) | |
return; | |
} | |
- Pet *pet = player->GetPet(); | |
+ Unit *pet = player->GetCharmOrPet(); | |
WorldPacket data(SMSG_PARTY_MEMBER_STATS_FULL, 4+2+2+2+1+2*6+8+1+8); | |
data << uint8(0); // only for SMSG_PARTY_MEMBER_STATS_FULL, probably arena/bg related | |
@@ -823,7 +829,7 @@ void WorldSession::HandleRequestPartyMemberStatsOpcode( WorldPacket &recv_data ) | |
uint32 mask1 = 0x00040BFF; // common mask, real flags used 0x000040BFF | |
if(pet) | |
- mask1 = 0x7FFFFFFF; // for hunters and other classes with pets | |
+ mask1 = 0xFFFFFFFF; // for hunters and other classes with pets | |
Powers powerType = player->getPowerType(); | |
data << uint32(mask1); // group update mask | |
@@ -877,6 +883,7 @@ void WorldSession::HandleRequestPartyMemberStatsOpcode( WorldPacket &recv_data ) | |
} | |
} | |
data.put<uint64>(petMaskPos, petauramask); // GROUP_UPDATE_FLAG_PET_AURAS | |
+ data << (uint32) player->m_movementInfo.GetTransportDBCSeat(); | |
} | |
else | |
{ | |
diff --git a/src/game/Level3.cpp b/src/game/Level3.cpp | |
index d3bcbb8..e4a1142 100644 | |
--- a/src/game/Level3.cpp | |
+++ b/src/game/Level3.cpp | |
@@ -74,6 +74,9 @@ bool ChatHandler::HandleReloadAllCommand(const char*) | |
HandleReloadReservedNameCommand(""); | |
HandleReloadMangosStringCommand(""); | |
HandleReloadGameTeleCommand(""); | |
+ | |
+ HandleReloadVehicleDataCommand(""); | |
+ HandleReloadVehicleSeatDataCommand(""); | |
return true; | |
} | |
@@ -891,6 +894,22 @@ bool ChatHandler::HandleReloadMailLevelRewardCommand(const char* /*arg*/) | |
return true; | |
} | |
+bool ChatHandler::HandleReloadVehicleDataCommand(const char*) | |
+{ | |
+ sLog.outString( "Re-Loading `vehicle_data` Table!" ); | |
+ sObjectMgr.LoadVehicleData(); | |
+ SendGlobalSysMessage("DB table `vehicle_data` reloaded."); | |
+ return true; | |
+} | |
+ | |
+bool ChatHandler::HandleReloadVehicleSeatDataCommand(const char*) | |
+{ | |
+ sLog.outString( "Re-Loading `vehicle_seat_data` Table!" ); | |
+ sObjectMgr.LoadVehicleSeatData(); | |
+ SendGlobalSysMessage("DB table `vehicle_seat_data` reloaded."); | |
+ return true; | |
+} | |
+ | |
bool ChatHandler::HandleLoadScriptsCommand(const char* args) | |
{ | |
if(!LoadScriptingModule(args)) return true; | |
diff --git a/src/game/Map.h b/src/game/Map.h | |
index c798c61..f28acb4 100644 | |
--- a/src/game/Map.h | |
+++ b/src/game/Map.h | |
@@ -38,7 +38,6 @@ | |
#include <bitset> | |
#include <list> | |
-class Creature; | |
class Unit; | |
class WorldPacket; | |
class InstanceData; | |
diff --git a/src/game/MiscHandler.cpp b/src/game/MiscHandler.cpp | |
index b4ddc71..643ee61 100644 | |
--- a/src/game/MiscHandler.cpp | |
+++ b/src/game/MiscHandler.cpp | |
@@ -267,6 +267,7 @@ void WorldSession::HandleLogoutRequestOpcode( WorldPacket & /*recv_data*/ ) | |
//Can not logout if... | |
if( GetPlayer()->isInCombat() || //...is in combat | |
GetPlayer()->duel || //...is in Duel | |
+ GetPlayer()->GetVehicleGUID() || //...is in vehicle | |
//...is jumping ...is falling | |
GetPlayer()->m_movementInfo.HasMovementFlag(MovementFlags(MOVEFLAG_FALLING | MOVEFLAG_FALLINGFAR))) | |
{ | |
diff --git a/src/game/MovementHandler.cpp b/src/game/MovementHandler.cpp | |
index c637664..b3f98d2 100644 | |
--- a/src/game/MovementHandler.cpp | |
+++ b/src/game/MovementHandler.cpp | |
@@ -248,7 +248,7 @@ void WorldSession::HandleMovementOpcodes( WorldPacket & recv_data ) | |
} | |
/* handle special cases */ | |
- if (movementInfo.HasMovementFlag(MOVEFLAG_ONTRANSPORT)) | |
+ if (movementInfo.HasMovementFlag(MOVEFLAG_ONTRANSPORT) && !mover->GetVehicleGUID()) | |
{ | |
// transports size limited | |
// (also received at zeppelin/lift leave by some reason with t_* as absolute in continent coordinates, can be safely skipped) | |
@@ -296,6 +296,17 @@ void WorldSession::HandleMovementOpcodes( WorldPacket & recv_data ) | |
// now client not include swimming flag in case jumping under water | |
plMover->SetInWater( !plMover->IsInWater() || plMover->GetBaseMap()->IsUnderWater(movementInfo.GetPos()->x, movementInfo.GetPos()->y, movementInfo.GetPos()->z) ); | |
} | |
+ if (movementInfo.HasMovementFlag(MOVEFLAG_SWIMMING)) | |
+ { | |
+ if(mover->GetTypeId() == TYPEID_UNIT) | |
+ { | |
+ if(((Creature*)mover)->isVehicle() && !((Creature*)mover)->canSwim()) | |
+ { | |
+ // NOTE : we should enter evade mode here, but... | |
+ ((Vehicle*)mover)->SetSpawnDuration(1); | |
+ } | |
+ } | |
+ } | |
/*----------------------*/ | |
@@ -354,7 +365,11 @@ void WorldSession::HandleMovementOpcodes( WorldPacket & recv_data ) | |
else // creature charmed | |
{ | |
if(mover->IsInWorld()) | |
+ { | |
mover->GetMap()->CreatureRelocation((Creature*)mover, movementInfo.GetPos()->x, movementInfo.GetPos()->y, movementInfo.GetPos()->z, movementInfo.GetPos()->o); | |
+ if(((Creature*)mover)->isVehicle()) | |
+ ((Vehicle*)mover)->RellocatePassengers(mover->GetMap()); | |
+ } | |
} | |
} | |
@@ -480,18 +495,124 @@ void WorldSession::HandleDismissControlledVehicle(WorldPacket &recv_data) | |
recv_data >> guid.ReadAsPacked(); | |
recv_data >> mi; | |
- uint64 vehicleGUID = _player->GetCharmGUID(); | |
+ uint64 vehicleGUID = _player->GetVehicleGUID(); | |
+ | |
+ if(!vehicleGUID) // something wrong here... | |
+ return; | |
+ | |
+ _player->m_movementInfo = mi; | |
+ | |
+ if(Vehicle *vehicle = ObjectAccessor::GetVehicle(vehicleGUID)) | |
+ { | |
+ if(vehicle->GetVehicleFlags() & VF_DESPAWN_AT_LEAVE) | |
+ vehicle->Dismiss(); | |
+ else | |
+ _player->ExitVehicle(); | |
+ } | |
+} | |
+ | |
+void WorldSession::HandleRequestVehicleExit(WorldPacket &recv_data) | |
+{ | |
+ sLog.outDebug("WORLD: Recvd CMSG_REQUEST_VEHICLE_EXIT"); | |
+ recv_data.hexlike(); | |
+ | |
+ uint64 vehicleGUID = _player->GetVehicleGUID(); | |
+ | |
+ if(!vehicleGUID) // something wrong here... | |
+ return; | |
+ | |
+ if(Vehicle *vehicle = ObjectAccessor::GetVehicle(vehicleGUID)) | |
+ { | |
+ _player->ExitVehicle(); | |
+ } | |
+} | |
+ | |
+void WorldSession::HandleRequestVehicleSwitchSeat(WorldPacket &recv_data) | |
+{ | |
+ sLog.outDebug("WORLD: Recvd CMSG_REQUEST_VEHICLE_SWITCH_SEAT"); | |
+ recv_data.hexlike(); | |
+ | |
+ uint64 vehicleGUID = _player->GetVehicleGUID(); | |
+ | |
+ if(!vehicleGUID) // something wrong here... | |
+ return; | |
+ | |
+ if(Vehicle *vehicle = ObjectAccessor::GetVehicle(vehicleGUID)) | |
+ { | |
+ ObjectGuid guid; | |
+ recv_data >> guid.ReadAsPacked(); | |
+ | |
+ int8 seatId = 0; | |
+ recv_data >> seatId; | |
+ | |
+ if(!guid.IsEmpty()) | |
+ { | |
+ if(vehicleGUID != guid.GetRawValue()) | |
+ { | |
+ if(Vehicle *veh = ObjectAccessor::GetVehicle(guid.GetRawValue())) | |
+ { | |
+ if(!_player->IsWithinDistInMap(veh, 10)) | |
+ return; | |
+ | |
+ if(Vehicle *v = veh->FindFreeSeat(&seatId, false)) | |
+ { | |
+ vehicle->RemovePassenger(_player); | |
+ _player->EnterVehicle(v, seatId, false); | |
+ } | |
+ } | |
+ return; | |
+ } | |
+ } | |
+ if(Vehicle *v = vehicle->FindFreeSeat(&seatId, false)) | |
+ { | |
+ vehicle->RemovePassenger(_player); | |
+ _player->EnterVehicle(v, seatId, false); | |
+ } | |
+ } | |
+} | |
+ | |
+void WorldSession::HandleChangeSeatsOnControlledVehicle(WorldPacket &recv_data) | |
+{ | |
+ sLog.outDebug("WORLD: Recvd CMSG_CHANGE_SEATS_ON_CONTROLLED_VEHICLE"); | |
+ recv_data.hexlike(); | |
+ | |
+ uint64 vehicleGUID = _player->GetVehicleGUID(); | |
if(!vehicleGUID) // something wrong here... | |
return; | |
+ if(recv_data.GetOpcode() == CMSG_REQUEST_VEHICLE_PREV_SEAT) | |
+ { | |
+ _player->ChangeSeat(-1, false); | |
+ return; | |
+ } | |
+ else if(recv_data.GetOpcode() == CMSG_REQUEST_VEHICLE_NEXT_SEAT) | |
+ { | |
+ _player->ChangeSeat(-1, true); | |
+ return; | |
+ } | |
+ | |
+ ObjectGuid guid, guid2; | |
+ recv_data >> guid.ReadAsPacked(); | |
+ | |
+ MovementInfo mi; | |
+ recv_data >> mi; | |
_player->m_movementInfo = mi; | |
- // using charm guid, because we don't have vehicle guid... | |
- if(Vehicle *vehicle = _player->GetMap()->GetVehicle(vehicleGUID)) | |
+ recv_data >> guid2.ReadAsPacked(); //guid of vehicle or of vehicle in target seat | |
+ | |
+ int8 seatId; | |
+ recv_data >> seatId; | |
+ | |
+ if(guid.GetRawValue() == guid2.GetRawValue()) | |
+ _player->ChangeSeat(seatId, false); | |
+ else if(Vehicle *vehicle = ObjectAccessor::GetVehicle(guid2.GetRawValue())) | |
{ | |
- // Aura::HandleAuraControlVehicle will call Player::ExitVehicle | |
- vehicle->RemoveSpellsCausingAura(SPELL_AURA_CONTROL_VEHICLE); | |
+ if(vehicle->HasEmptySeat(seatId)) | |
+ { | |
+ _player->ExitVehicle(); | |
+ _player->EnterVehicle(vehicle, seatId); | |
+ } | |
} | |
} | |
@@ -554,4 +675,4 @@ void WorldSession::HandleSummonResponseOpcode(WorldPacket& recv_data) | |
recv_data >> agree; | |
_player->SummonIfPossible(agree); | |
-} | |
+} | |
\ No newline at end of file | |
diff --git a/src/game/Object.cpp b/src/game/Object.cpp | |
index 8386721..32a60fd 100644 | |
--- a/src/game/Object.cpp | |
+++ b/src/game/Object.cpp | |
@@ -289,6 +289,9 @@ void Object::BuildMovementUpdate(ByteBuffer * data, uint16 updateFlags) const | |
} | |
} | |
} | |
+ if(unit->GetVehicleGUID()) | |
+ unit->m_movementInfo.AddMovementFlag(MOVEFLAG_ONTRANSPORT); | |
+ | |
} | |
break; | |
case TYPEID_PLAYER: | |
@@ -303,6 +306,8 @@ void Object::BuildMovementUpdate(ByteBuffer * data, uint16 updateFlags) const | |
// remove unknown, unused etc flags for now | |
player->m_movementInfo.RemoveMovementFlag(MOVEFLAG_SPLINE_ENABLED); | |
+ if(((Unit*)this)->GetVehicleGUID()) | |
+ player->m_movementInfo.AddMovementFlag(MOVEFLAG_ONTRANSPORT); | |
if(player->isInFlight()) | |
{ | |
ASSERT(player->GetMotionMaster()->GetCurrentMovementGeneratorType() == FLIGHT_MOTION_TYPE); | |
@@ -1113,7 +1118,11 @@ void WorldObject::Relocate(float x, float y, float z, float orientation) | |
m_orientation = orientation; | |
if(isType(TYPEMASK_UNIT)) | |
+ { | |
((Unit*)this)->m_movementInfo.ChangePosition(x, y, z, orientation); | |
+ if(((Creature*)this)->isVehicle() && IsInWorld()) | |
+ ((Vehicle*)this)->RellocatePassengers(GetMap()); | |
+ } | |
} | |
void WorldObject::Relocate(float x, float y, float z) | |
@@ -1123,7 +1132,11 @@ void WorldObject::Relocate(float x, float y, float z) | |
m_positionZ = z; | |
if(isType(TYPEMASK_UNIT)) | |
+ { | |
((Unit*)this)->m_movementInfo.ChangePosition(x, y, z, GetOrientation()); | |
+ if(((Creature*)this)->isVehicle() && IsInWorld()) | |
+ ((Vehicle*)this)->RellocatePassengers(GetMap()); | |
+ } | |
} | |
uint32 WorldObject::GetZoneId() const | |
@@ -1665,6 +1678,42 @@ Creature* WorldObject::SummonCreature(uint32 id, float x, float y, float z, floa | |
return pCreature; | |
} | |
+Vehicle* WorldObject::SummonVehicle(uint32 id, float x, float y, float z, float ang, uint32 vehicleId) | |
+{ | |
+ Vehicle *v = new Vehicle; | |
+ | |
+ Map *map = GetMap(); | |
+ uint32 team = 0; | |
+ if (GetTypeId()==TYPEID_PLAYER) | |
+ team = ((Player*)this)->GetTeam(); | |
+ | |
+ if(!v->Create(sObjectMgr.GenerateLowGuid(HIGHGUID_VEHICLE), map, GetPhaseMask(), id, vehicleId, team)) | |
+ { | |
+ delete v; | |
+ return NULL; | |
+ } | |
+ | |
+ if (x == 0.0f && y == 0.0f && z == 0.0f) | |
+ GetClosePoint(x, y, z, v->GetObjectSize()); | |
+ | |
+ v->Relocate(x, y, z, ang); | |
+ | |
+ if(!v->IsPositionValid()) | |
+ { | |
+ sLog.outError("ERROR: Vehicle (guidlow %d, entry %d) not created. Suggested coordinates isn't valid (X: %f Y: %f)", | |
+ v->GetGUIDLow(), v->GetEntry(), v->GetPositionX(), v->GetPositionY()); | |
+ delete v; | |
+ return NULL; | |
+ } | |
+ map->Add((Creature*)v); | |
+ v->AIM_Initialize(); | |
+ | |
+ if(GetTypeId()==TYPEID_UNIT && ((Creature*)this)->AI()) | |
+ ((Creature*)this)->AI()->JustSummoned((Creature*)v); | |
+ | |
+ return v; | |
+} | |
+ | |
namespace MaNGOS | |
{ | |
class NearUsedPosDo | |
diff --git a/src/game/Object.h b/src/game/Object.h | |
index c900e4d..ac1aa7d 100644 | |
--- a/src/game/Object.h | |
+++ b/src/game/Object.h | |
@@ -71,6 +71,7 @@ class Unit; | |
class Map; | |
class UpdateMask; | |
class InstanceData; | |
+class Vehicle; | |
typedef UNORDERED_MAP<Player*, UpdateData> UpdateDataMapType; | |
@@ -490,6 +491,9 @@ class MANGOS_DLL_SPEC WorldObject : public Object | |
bool isActiveObject() const { return m_isActiveObject || m_viewPoint.hasViewers(); } | |
ViewPoint& GetViewPoint() { return m_viewPoint; } | |
+ | |
+ Vehicle* SummonVehicle(uint32 id, float x, float y, float z, float ang, uint32 vehicleId = NULL); | |
+ | |
protected: | |
explicit WorldObject(); | |
diff --git a/src/game/ObjectAccessor.cpp b/src/game/ObjectAccessor.cpp | |
index 2d39db4..0ecd27b 100644 | |
--- a/src/game/ObjectAccessor.cpp | |
+++ b/src/game/ObjectAccessor.cpp | |
@@ -54,6 +54,21 @@ ObjectAccessor::~ObjectAccessor() | |
} | |
} | |
+Creature* | |
+ObjectAccessor::GetCreatureOrPetOrVehicle(WorldObject const &u, ObjectGuid guid) | |
+{ | |
+ if(guid.IsPlayer() || !u.IsInWorld()) | |
+ return NULL; | |
+ | |
+ if(guid.IsPet()) | |
+ return u.GetMap()->GetPet(guid); | |
+ | |
+ if(guid.IsVehicle()) | |
+ return u.GetMap()->GetVehicle(guid); | |
+ | |
+ return u.GetMap()->GetCreature(guid); | |
+} | |
+ | |
Unit* | |
ObjectAccessor::GetUnit(WorldObject const &u, ObjectGuid guid) | |
{ | |
@@ -63,10 +78,7 @@ ObjectAccessor::GetUnit(WorldObject const &u, ObjectGuid guid) | |
if(guid.IsPlayer()) | |
return FindPlayer(guid); | |
- if (!u.IsInWorld()) | |
- return NULL; | |
- | |
- return u.GetMap()->GetCreatureOrPetOrVehicle(guid); | |
+ return GetCreatureOrPetOrVehicle(u, guid); | |
} | |
Corpse* ObjectAccessor::GetCorpseInMap(ObjectGuid guid, uint32 mapid) | |
diff --git a/src/game/ObjectAccessor.h b/src/game/ObjectAccessor.h | |
index 3caed16..8061ed2 100644 | |
--- a/src/game/ObjectAccessor.h | |
+++ b/src/game/ObjectAccessor.h | |
@@ -39,6 +39,7 @@ | |
class Creature; | |
class Unit; | |
class GameObject; | |
+class Vehicle; | |
class WorldObject; | |
class Map; | |
@@ -99,12 +100,20 @@ class MANGOS_DLL_DECL ObjectAccessor : public MaNGOS::Singleton<ObjectAccessor, | |
// global (obj used for map only location local guid objects (pets currently) | |
static Unit* GetUnitInWorld(WorldObject const& obj, ObjectGuid guid); | |
- // FIXME: map local object with global search | |
+ // map local object with global search | |
static Creature* GetCreatureInWorld(ObjectGuid guid) { return FindHelper<Creature>(guid); } | |
static GameObject* GetGameObjectInWorld(ObjectGuid guid) { return FindHelper<GameObject>(guid); } | |
+ static Pet* GetGameObjectInWorld(uint64 guid, Pet* /*fake*/) { return FindHelper<Pet>(guid); } | |
+ static Vehicle* GetGameObjectInWorld(uint64 guid, Vehicle* /*fake*/) { return FindHelper<Vehicle>(guid); } | |
// possible local search for specific object map | |
static Unit* GetUnit(WorldObject const &, ObjectGuid guid); | |
+ static Creature* GetCreatureOrPetOrVehicle(WorldObject const &, ObjectGuid guid); | |
+ //static Player* GetPlayer(Unit const &, uint64 guid) { return FindPlayer(guid); } | |
+ //static Corpse* GetCorpse(WorldObject const &u, uint64 guid); | |
+ //static Pet* GetPet(uint64 guid) { return GetObjectInWorld(guid, (Pet*)NULL); } | |
+ static Vehicle* GetVehicle(uint64 guid) { return GetGameObjectInWorld(guid, (Vehicle*)NULL); } | |
+ //static Player* FindPlayer(uint64); | |
// Player access | |
static Player* FindPlayer(ObjectGuid guid); | |
@@ -176,6 +185,9 @@ inline Unit* ObjectAccessor::GetUnitInWorld(WorldObject const& obj, ObjectGuid g | |
if (guid.IsPet()) | |
return obj.IsInWorld() ? obj.GetMap()->GetPet(guid) : NULL; | |
+ if (guid.IsVehicle()) | |
+ return obj.IsInWorld() ? ((Unit*)obj.GetMap()->GetVehicle(guid)) : NULL; | |
+ | |
return GetCreatureInWorld(guid); | |
} | |
diff --git a/src/game/ObjectMgr.cpp b/src/game/ObjectMgr.cpp | |
index 2aa9bb1..b6b3899 100644 | |
--- a/src/game/ObjectMgr.cpp | |
+++ b/src/game/ObjectMgr.cpp | |
@@ -834,6 +834,93 @@ void ObjectMgr::ConvertCreatureAddonAuras(CreatureDataAddon* addon, char const* | |
endAura.effect_idx = EFFECT_INDEX_0; | |
} | |
+void ObjectMgr::ConvertCreatureAddonPassengers(CreatureDataAddon* addon, char const* table, char const* guidEntryStr) | |
+{ | |
+ // Now add the passengers, format "creature_entry/guid seatindex creature_entry/guid seatindex..." | |
+ char *p,*s; | |
+ std::vector<int> val; | |
+ s=p=(char*)reinterpret_cast<char const*>(addon->passengers); | |
+ if(p) | |
+ { | |
+ while (p[0]!=0) | |
+ { | |
+ ++p; | |
+ if (p[0]==' ') | |
+ { | |
+ val.push_back(atoi(s)); | |
+ s=++p; | |
+ } | |
+ } | |
+ if (p!=s) | |
+ val.push_back(atoi(s)); | |
+ | |
+ // free char* loaded memory | |
+ delete[] (char*)reinterpret_cast<char const*>(addon->passengers); | |
+ | |
+ // wrong list | |
+ if (val.size()%2) | |
+ { | |
+ addon->auras = NULL; | |
+ sLog.outErrorDb("Creature (%s: %u) has wrong `passengers` data in `%s`.",guidEntryStr,addon->guidOrEntry,table); | |
+ return; | |
+ } | |
+ } | |
+ | |
+ // empty list | |
+ if(val.empty()) | |
+ { | |
+ addon->passengers = NULL; | |
+ return; | |
+ } | |
+ | |
+ // replace by new structures array | |
+ const_cast<CreatureDataAddonPassengers*&>(addon->passengers) = new CreatureDataAddonPassengers[val.size()/2+1]; | |
+ | |
+ int i=0; | |
+ for(int j=0;j<val.size()/2;++j) | |
+ { | |
+ CreatureDataAddonPassengers& cPas = const_cast<CreatureDataAddonPassengers&>(addon->passengers[i]); | |
+ if(guidEntryStr == "Entry") | |
+ cPas.entry = (uint32)val[2*j+0]; | |
+ else | |
+ cPas.guid = (uint32)val[2*j+0]; | |
+ cPas.seat_idx = (int8)val[2*j+1]; | |
+ if ( cPas.seat_idx > 7 ) | |
+ { | |
+ sLog.outErrorDb("Creature (%s: %u) has wrong seat %u for creature %u in `passengers` field in `%s`.",guidEntryStr,addon->guidOrEntry,cPas.seat_idx,cPas.entry,table); | |
+ continue; | |
+ } | |
+ if(cPas.entry == 0 && cPas.guid == 0) | |
+ { | |
+ sLog.outErrorDb("Creature (%s: %u) has NULL creature entry/guid in `passengers` field in `%s`.",guidEntryStr,addon->guidOrEntry,table); | |
+ continue; | |
+ } | |
+ if(cPas.entry > 0) | |
+ { | |
+ if(!sCreatureStorage.LookupEntry<CreatureInfo>(cPas.entry)) | |
+ { | |
+ sLog.outErrorDb("Creature (%s: %u) has wrong creature entry/guid %u `passengers` field in `%s`.",guidEntryStr,addon->guidOrEntry,cPas.entry,table); | |
+ continue; | |
+ } | |
+ } | |
+ else | |
+ { | |
+ if(mCreatureDataMap.find(cPas.guid)==mCreatureDataMap.end()) | |
+ { | |
+ sLog.outErrorDb("Creature (%s: %u) has wrong creature entry/guid %u `passengers` field in `%s`.",guidEntryStr,addon->guidOrEntry,cPas.guid,table); | |
+ continue; | |
+ } | |
+ } | |
+ ++i; | |
+ } | |
+ | |
+ // fill terminator element (after last added) | |
+ CreatureDataAddonPassengers& endPassenger = const_cast<CreatureDataAddonPassengers&>(addon->passengers[i]); | |
+ endPassenger.entry = 0; | |
+ endPassenger.guid = 0; | |
+ endPassenger.seat_idx = -1; | |
+} | |
+ | |
void ObjectMgr::LoadCreatureAddons(SQLStorage& creatureaddons, char const* entryName, char const* comment) | |
{ | |
creatureaddons.Load(); | |
@@ -870,6 +957,7 @@ void ObjectMgr::LoadCreatureAddons(SQLStorage& creatureaddons, char const* entry | |
} | |
ConvertCreatureAddonAuras(const_cast<CreatureDataAddon*>(addon), creatureaddons.GetTableName(), entryName); | |
+ ConvertCreatureAddonPassengers(const_cast<CreatureDataAddon*>(addon), creatureaddons.GetTableName(), entryName); | |
} | |
} | |
@@ -5905,6 +5993,8 @@ uint32 ObjectMgr::GenerateLowGuid(HighGuid guidhigh) | |
return m_ItemGuids.Generate(); | |
case HIGHGUID_UNIT: | |
return m_CreatureGuids.Generate(); | |
+ case HIGHGUID_VEHICLE: | |
+ return m_VehicleGuids.Generate(); | |
case HIGHGUID_PLAYER: | |
return m_CharGuids.Generate(); | |
case HIGHGUID_GAMEOBJECT: | |
@@ -8704,6 +8794,126 @@ CreatureInfo const* GetCreatureTemplateStore(uint32 entry) | |
return sCreatureStorage.LookupEntry<CreatureInfo>(entry); | |
} | |
+void ObjectMgr::LoadVehicleData() | |
+{ | |
+ mVehicleData.clear(); | |
+ | |
+ QueryResult *result = WorldDatabase.Query("SELECT entry, flags, Spell1, Spell2, Spell3, Spell4, Spell5, Spell6, Spell7, Spell8, Spell9, Spell10, req_aura FROM vehicle_data"); | |
+ if(!result) | |
+ { | |
+ barGoLink bar( 1 ); | |
+ bar.step(); | |
+ | |
+ sLog.outString(); | |
+ sLog.outString( ">> Loaded 0 vehicle data" ); | |
+ sLog.outErrorDb("`vehicle_data` table is empty!"); | |
+ return; | |
+ } | |
+ | |
+ uint32 count = 0; | |
+ | |
+ barGoLink bar( result->GetRowCount() ); | |
+ do | |
+ { | |
+ bar.step(); | |
+ | |
+ Field* fields = result->Fetch(); | |
+ | |
+ VehicleDataStructure VDS; | |
+ // NOTE : we can use spellid or creature id | |
+ uint32 v_entry = fields[0].GetUInt32(); | |
+ VDS.v_flags = fields[1].GetUInt32(); | |
+ for(uint8 j = 0; j < MAX_VEHICLE_SPELLS; j++) | |
+ { | |
+ VDS.v_spells[j] = fields[j+2].GetUInt32(); | |
+ } | |
+ VDS.req_aura = fields[12].GetUInt32(); | |
+ | |
+ VehicleEntry const *vehicleInfo = sVehicleStore.LookupEntry(v_entry); | |
+ if(!vehicleInfo) | |
+ { | |
+ sLog.outErrorDb("Vehicle id %u listed in `vehicle_data` does not exist",v_entry); | |
+ continue; | |
+ } | |
+ for(uint8 j = 0; j < MAX_VEHICLE_SPELLS; j++) | |
+ { | |
+ if(VDS.v_spells[j]) | |
+ { | |
+ SpellEntry const* j_spell = sSpellStore.LookupEntry(VDS.v_spells[j]); | |
+ if(!j_spell) | |
+ { | |
+ sLog.outErrorDb("Spell %u listed in `vehicle_data` does not exist, skipped",VDS.v_spells[j]); | |
+ VDS.v_spells[j] = 0; | |
+ } | |
+ } | |
+ } | |
+ if(VDS.req_aura) | |
+ { | |
+ SpellEntry const* i_spell = sSpellStore.LookupEntry(VDS.req_aura); | |
+ if(!i_spell) | |
+ { | |
+ sLog.outErrorDb("Spell %u listed in `vehicle_data` does not exist, skipped",VDS.req_aura); | |
+ VDS.req_aura = 0; | |
+ } | |
+ } | |
+ | |
+ mVehicleData[v_entry] = VDS; | |
+ ++count; | |
+ } | |
+ while (result->NextRow()); | |
+ | |
+ delete result; | |
+ | |
+ sLog.outString(); | |
+ sLog.outString( ">> Loaded %u vehicle data", count ); | |
+} | |
+ | |
+void ObjectMgr::LoadVehicleSeatData() | |
+{ | |
+ mVehicleSeatData.clear(); | |
+ | |
+ QueryResult *result = WorldDatabase.Query("SELECT seat,flags FROM vehicle_seat_data"); | |
+ | |
+ if( !result ) | |
+ { | |
+ barGoLink bar( 1 ); | |
+ | |
+ bar.step(); | |
+ | |
+ sLog.outString(); | |
+ sLog.outString( ">> Loaded 0 vehicle seat data" ); | |
+ sLog.outErrorDb("`vehicle_seat_data` table is empty!"); | |
+ return; | |
+ } | |
+ uint32 count = 0; | |
+ | |
+ barGoLink bar( result->GetRowCount() ); | |
+ do | |
+ { | |
+ bar.step(); | |
+ | |
+ Field *fields = result->Fetch(); | |
+ uint32 entry = fields[0].GetUInt32(); | |
+ uint32 flag = fields[1].GetUInt32(); | |
+ | |
+ VehicleSeatEntry const *vsInfo = sVehicleSeatStore.LookupEntry(entry); | |
+ if(!vsInfo) | |
+ { | |
+ sLog.outErrorDb("Vehicle seat %u listed in `vehicle_seat_data` does not exist",entry); | |
+ continue; | |
+ } | |
+ | |
+ mVehicleSeatData[entry] = flag; | |
+ ++count; | |
+ } | |
+ while (result->NextRow()); | |
+ | |
+ delete result; | |
+ | |
+ sLog.outString(); | |
+ sLog.outString( ">> Loaded %u vehicle seat data", count ); | |
+} | |
+ | |
Quest const* GetQuestTemplateStore(uint32 entry) | |
{ | |
return sObjectMgr.GetQuestTemplate(entry); | |
diff --git a/src/game/ObjectMgr.h b/src/game/ObjectMgr.h | |
index 78b79b9..579221d 100644 | |
--- a/src/game/ObjectMgr.h | |
+++ b/src/game/ObjectMgr.h | |
@@ -419,6 +419,8 @@ extern LanguageDesc lang_description[LANGUAGES_COUNT]; | |
MANGOS_DLL_SPEC LanguageDesc const* GetLanguageDescByID(uint32 lang); | |
class PlayerDumpReader; | |
+// vehicle system | |
+#define MAX_VEHICLE_SPELLS 6 | |
template<typename T> | |
class IdGenerator | |
@@ -438,6 +440,16 @@ class IdGenerator | |
T m_nextGuid; | |
}; | |
+struct VehicleDataStructure | |
+{ | |
+ uint32 v_flags; // vehicle flags, see enum CustomVehicleFLags | |
+ uint32 v_spells[MAX_VEHICLE_SPELLS]; // spells | |
+ uint32 req_aura; // requieres aura on player to enter (eg. in wintergrasp) | |
+}; | |
+ | |
+typedef UNORDERED_MAP<uint32, VehicleDataStructure> VehicleDataMap; | |
+typedef std::map<uint32,uint32> VehicleSeatDataMap; | |
+ | |
class ObjectMgr | |
{ | |
friend class PlayerDumpReader; | |
@@ -702,6 +714,9 @@ class ObjectMgr | |
void LoadVendors(); | |
void LoadTrainerSpell(); | |
+ void LoadVehicleData(); | |
+ void LoadVehicleSeatData(); | |
+ | |
std::string GeneratePetName(uint32 entry); | |
uint32 GetBaseXP(uint32 level) const; | |
uint32 GetXPForLevel(uint32 level) const; | |
@@ -950,6 +965,24 @@ class ObjectMgr | |
int GetOrNewIndexForLocale(LocaleConstant loc); | |
+ VehicleDataMap mVehicleData; | |
+ VehicleSeatDataMap mVehicleSeatData; | |
+ | |
+ uint32 GetSeatFlags(uint32 seatid) | |
+ { | |
+ VehicleSeatDataMap::iterator i = mVehicleSeatData.find(seatid); | |
+ if(i == mVehicleSeatData.end()) | |
+ return NULL; | |
+ else | |
+ return i->second; | |
+ } | |
+ VehicleDataStructure const* GetVehicleData(uint32 entry) const | |
+ { | |
+ VehicleDataMap::const_iterator itr = mVehicleData.find(entry); | |
+ if(itr==mVehicleData.end()) return NULL; | |
+ return &itr->second; | |
+ } | |
+ | |
SpellClickInfoMapBounds GetSpellClickInfoMapBounds(uint32 creature_id) const | |
{ | |
return SpellClickInfoMapBounds(mSpellClickInfoMap.lower_bound(creature_id),mSpellClickInfoMap.upper_bound(creature_id)); | |
@@ -987,6 +1020,7 @@ class ObjectMgr | |
ObjectGuidGenerator<HIGHGUID_ITEM> m_ItemGuids; | |
ObjectGuidGenerator<HIGHGUID_GAMEOBJECT> m_GameobjectGuids; | |
ObjectGuidGenerator<HIGHGUID_CORPSE> m_CorpseGuids; | |
+ ObjectGuidGenerator<HIGHGUID_VEHICLE> m_VehicleGuids; | |
QuestMap mQuestTemplates; | |
@@ -1040,6 +1074,7 @@ class ObjectMgr | |
void CheckScriptTexts(ScriptMapMap const& scripts,std::set<int32>& ids); | |
void LoadCreatureAddons(SQLStorage& creatureaddons, char const* entryName, char const* comment); | |
void ConvertCreatureAddonAuras(CreatureDataAddon* addon, char const* table, char const* guidEntryStr); | |
+ void ConvertCreatureAddonPassengers(CreatureDataAddon* addon, char const* table, char const* guidEntryStr); | |
void LoadQuestRelationsHelper(QuestRelations& map,char const* table); | |
MailLevelRewardMap m_mailLevelRewardMap; | |
diff --git a/src/game/Opcodes.cpp b/src/game/Opcodes.cpp | |
index 6c26ded..41ceeb1 100644 | |
--- a/src/game/Opcodes.cpp | |
+++ b/src/game/Opcodes.cpp | |
@@ -1168,10 +1168,10 @@ OpcodeHandler opcodeTable[NUM_MSG_TYPES] = | |
/*0x473*/ { "CMSG_CHAR_CUSTOMIZE", STATUS_AUTHED, &WorldSession::HandleCharCustomize }, | |
/*0x474*/ { "SMSG_CHAR_CUSTOMIZE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, | |
/*0x475*/ { "SMSG_PET_RENAMEABLE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, | |
- /*0x476*/ { "CMSG_REQUEST_VEHICLE_EXIT", STATUS_NEVER, &WorldSession::Handle_NULL }, | |
- /*0x477*/ { "CMSG_REQUEST_VEHICLE_PREV_SEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, | |
- /*0x478*/ { "CMSG_REQUEST_VEHICLE_NEXT_SEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, | |
- /*0x479*/ { "CMSG_REQUEST_VEHICLE_SWITCH_SEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, | |
+ /*0x476*/ { "CMSG_REQUEST_VEHICLE_EXIT", STATUS_LOGGEDIN, &WorldSession::HandleRequestVehicleExit }, | |
+ /*0x477*/ { "CMSG_REQUEST_VEHICLE_PREV_SEAT", STATUS_LOGGEDIN, &WorldSession::HandleChangeSeatsOnControlledVehicle}, | |
+ /*0x478*/ { "CMSG_REQUEST_VEHICLE_NEXT_SEAT", STATUS_LOGGEDIN, &WorldSession::HandleChangeSeatsOnControlledVehicle}, | |
+ /*0x479*/ { "CMSG_REQUEST_VEHICLE_SWITCH_SEAT", STATUS_LOGGEDIN, &WorldSession::HandleRequestVehicleSwitchSeat }, | |
/*0x47A*/ { "CMSG_PET_LEARN_TALENT", STATUS_LOGGEDIN, &WorldSession::HandlePetLearnTalent }, | |
/*0x47B*/ { "CMSG_PET_UNLEARN_TALENTS", STATUS_NEVER, &WorldSession::Handle_NULL }, | |
/*0x47C*/ { "SMSG_SET_PHASE_SHIFT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, | |
@@ -1205,7 +1205,7 @@ OpcodeHandler opcodeTable[NUM_MSG_TYPES] = | |
/*0x498*/ { "SMSG_SERVER_FIRST_ACHIEVEMENT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, | |
/*0x499*/ { "SMSG_PET_LEARNED_SPELL", STATUS_NEVER, &WorldSession::Handle_ServerSide }, | |
/*0x49A*/ { "SMSG_PET_REMOVED_SPELL", STATUS_NEVER, &WorldSession::Handle_ServerSide }, | |
- /*0x49B*/ { "CMSG_CHANGE_SEATS_ON_CONTROLLED_VEHICLE", STATUS_NEVER, &WorldSession::Handle_NULL }, | |
+ /*0x49B*/ { "CMSG_CHANGE_SEATS_ON_CONTROLLED_VEHICLE", STATUS_LOGGEDIN, &WorldSession::HandleChangeSeatsOnControlledVehicle}, | |
/*0x49C*/ { "CMSG_HEARTH_AND_RESURRECT", STATUS_LOGGEDIN, &WorldSession::HandleHearthandResurrect }, | |
/*0x49D*/ { "SMSG_ON_CANCEL_EXPECTED_RIDE_VEHICLE_AURA", STATUS_NEVER, &WorldSession::Handle_ServerSide }, | |
/*0x49E*/ { "SMSG_CRITERIA_DELETED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, | |
diff --git a/src/game/Pet.cpp b/src/game/Pet.cpp | |
index 45339c5..52c41d3 100644 | |
--- a/src/game/Pet.cpp | |
+++ b/src/game/Pet.cpp | |
@@ -39,7 +39,7 @@ char const* petTypeSuffix[MAX_PET_TYPE] = | |
Pet::Pet(PetType type) : | |
Creature(CREATURE_SUBTYPE_PET), m_removed(false), m_petType(type), m_happinessTimer(7500), m_duration(0), m_resetTalentsCost(0), | |
-m_bonusdamage(0), m_resetTalentsTime(0), m_usedTalentCount(0), m_auraUpdateMask(0), m_loading(false), | |
+m_bonusdamage(0), m_resetTalentsTime(0), m_usedTalentCount(0), m_loading(false), | |
m_declinedname(NULL), m_petModeFlags(PET_MODE_DEFAULT) | |
{ | |
m_name = "Pet"; | |
diff --git a/src/game/Pet.h b/src/game/Pet.h | |
index efc9ecd..5d7417a 100644 | |
--- a/src/game/Pet.h | |
+++ b/src/game/Pet.h | |
@@ -236,10 +236,6 @@ class Pet : public Creature | |
time_t m_resetTalentsTime; | |
uint32 m_usedTalentCount; | |
- const uint64& GetAuraUpdateMask() const { return m_auraUpdateMask; } | |
- void SetAuraUpdateMask(uint8 slot) { m_auraUpdateMask |= (uint64(1) << slot); } | |
- void ResetAuraUpdateMask() { m_auraUpdateMask = 0; } | |
- | |
// overwrite Creature function for name localization back to WorldObject version without localization | |
const char* GetNameForLocaleIdx(int32 locale_idx) const { return WorldObject::GetNameForLocaleIdx(locale_idx); } | |
@@ -251,7 +247,6 @@ class Pet : public Creature | |
PetType m_petType; | |
int32 m_duration; // time until unsummon (used mostly for summoned guardians and not used for controlled pets) | |
int32 m_bonusdamage; | |
- uint64 m_auraUpdateMask; | |
bool m_loading; | |
DeclinedName *m_declinedname; | |
diff --git a/src/game/PetHandler.cpp b/src/game/PetHandler.cpp | |
index 57356b3..1a855da 100644 | |
--- a/src/game/PetHandler.cpp | |
+++ b/src/game/PetHandler.cpp | |
@@ -286,7 +286,7 @@ void WorldSession::HandlePetNameQuery( WorldPacket & recv_data ) | |
void WorldSession::SendPetNameQuery( uint64 petguid, uint32 petnumber) | |
{ | |
- Creature* pet = _player->GetMap()->GetCreatureOrPetOrVehicle(petguid); | |
+ Creature* pet = ObjectAccessor::GetCreatureOrPetOrVehicle(*_player, petguid); | |
if(!pet || !pet->GetCharmInfo() || pet->GetCharmInfo()->GetPetNumber() != petnumber) | |
return; | |
@@ -318,7 +318,12 @@ void WorldSession::HandlePetSetAction( WorldPacket & recv_data ) | |
recv_data >> petguid; | |
- Creature* pet = _player->GetMap()->GetCreatureOrPetOrVehicle(petguid); | |
+ // FIXME: charmed case | |
+ //Pet* pet = ObjectAccessor::Instance().GetPet(petguid); | |
+ if(ObjectAccessor::FindPlayer(petguid)) | |
+ return; | |
+ | |
+ Creature* pet = ObjectAccessor::GetCreatureOrPetOrVehicle(*_player, petguid); | |
if(!pet || (pet != _player->GetPet() && pet != _player->GetCharm())) | |
{ | |
@@ -506,7 +511,8 @@ void WorldSession::HandlePetAbandon( WorldPacket & recv_data ) | |
return; | |
// pet/charmed | |
- if (Creature* pet = _player->GetMap()->GetCreatureOrPetOrVehicle(guid)) | |
+ Creature* pet = ObjectAccessor::GetCreatureOrPetOrVehicle(*_player, guid); | |
+ if(pet) | |
{ | |
if(pet->isPet()) | |
{ | |
@@ -560,29 +566,32 @@ void WorldSession::HandlePetSpellAutocastOpcode( WorldPacket& recvPacket ) | |
uint8 state; //1 for on, 0 for off | |
recvPacket >> guid >> spellid >> state; | |
- if(!_player->GetPet() && !_player->GetCharm()) | |
+ if (!_player->GetPet() && !_player->GetCharm()) | |
return; | |
- Creature* pet = _player->GetMap()->GetCreatureOrPetOrVehicle(guid); | |
+ if(ObjectAccessor::FindPlayer(guid)) | |
+ return; | |
- if(!pet || (pet != _player->GetPet() && pet != _player->GetCharm())) | |
+ Creature* pet=ObjectAccessor::GetCreatureOrPetOrVehicle(*_player,guid); | |
+ | |
+ if (!pet || (pet != _player->GetPet() && pet != _player->GetCharm())) | |
{ | |
sLog.outError( "HandlePetSpellAutocastOpcode.Pet %u isn't pet of player %s .", uint32(GUID_LOPART(guid)),GetPlayer()->GetName() ); | |
return; | |
} | |
// do not add not learned spells/ passive spells | |
- if(!pet->HasSpell(spellid) || IsPassiveSpell(spellid)) | |
+ if (!pet->HasSpell(spellid) || IsPassiveSpell(spellid)) | |
return; | |
CharmInfo *charmInfo = pet->GetCharmInfo(); | |
- if(!charmInfo) | |
+ if (!charmInfo) | |
{ | |
sLog.outError("WorldSession::HandlePetSpellAutocastOpcod: object (GUID: %u TypeId: %u) is considered pet-like but doesn't have a charminfo!", pet->GetGUIDLow(), pet->GetTypeId()); | |
return; | |
} | |
- if(pet->isCharmed()) | |
+ if (pet->isCharmed()) | |
//state can be used as boolean | |
pet->GetCharmInfo()->ToggleCreatureAutocast(spellid, state); | |
else | |
@@ -594,6 +603,23 @@ void WorldSession::HandlePetSpellAutocastOpcode( WorldPacket& recvPacket ) | |
void WorldSession::HandlePetCastSpellOpcode( WorldPacket& recvPacket ) | |
{ | |
DETAIL_LOG("WORLD: CMSG_PET_CAST_SPELL"); | |
+ recvPacket.hexlike(); | |
+ recvPacket.print_storage(); | |
+ | |
+ //2 - 0 - 0 - 43 - 129 - 0 - 80 - 241 | - 42 - 211 - 253 - 0 | - 0 | - 2 |- 96 - 0 - 0 - 0 | - 0 - 26 | |
+ //- 164 - 59 - 196 - 174 - 98 - 131 | - 194 - 182 - 171 - 218| - 67 - 0 - 48 - 93| - 0 - 196 - 32 | |
+ //- 177| - 242 - 193 - 22 - 110 - 224 - 67 - 203 - 166 | - 68 - 61 - 133 - 1| - 240 - 66 - 1 - 183 | | |
+ //- 0 - 0 - 0 - 217| - 2 - 43 - 129 - 80 - 241 - 0 - 10 - 0 - 0 - 0 - 0 - 76 - 109 - 175 - 0 | |
+ //- 238 - 115 - 58 - 196 - 20 - 110 - 121 - 194 - 187 - 107 - 217 - 67 - 32 - 44 - 27 - 62 - 217 | |
+ //- 1 - 36 - 129 - 80 - 241 - 0 - 0 - 160 - 64 - 0 - 0 - 160 - 64 - 0 - 0 - 160 - 64 - 192 - 233 | |
+ //- 172 - 62 - 4 - 0 - 0 - 0 - 7 - 230 - 0 - 0 - 0 - | |
+ | |
+ //5 - 0 - 0 - 43 - 129 - 0 - 80 - 241 | - 85 - 211 - 253 - 0 | - 0 | - 2 | - 96 - 0 - 0 - 0 | - 0 - 69 - 60 - 61 | |
+ //- 196 - 171 - 248 - 107| - 194 - 8 - 236 - 218 | - 67 - 0 - 177 - 11 | - 46 - 196 - 89 - 16 | - 14 - 195 | |
+ //- 5 - 38 - 231 - 67 - 23 - 221 | - 110 - 62 - 15 - 3 | - 240 - 66 -| 1 - 183 | - 0 - 0 - 0 - 217 | - 5 - 43 | |
+ //- 129 - 80 - 241 - 0 - 10 - 0 - 0 - 0 - 0 - 233 - 41 - 203 - 0 - 106 - 207 - 59 - 196 - 179 - 173 - 83 | |
+ //- 194 - 8 - 108 - 217 - 67 - 127 - 153 - 170 - 64 - 217 - 4 - 36 - 129 - 80 - 241 - 0 - 0 - 160 - 64 | |
+ //- 0 - 0 - 160 - 64 - 0 - 0 - 160 - 64 - 7 - 77 - 175 - 64 - 4 - 0 - 0 - 0 - 7 - 195 - 0 - 0 - 0 - | |
uint64 guid; | |
uint32 spellid; | |
@@ -607,7 +633,10 @@ void WorldSession::HandlePetCastSpellOpcode( WorldPacket& recvPacket ) | |
if (!_player->GetPet() && !_player->GetCharm()) | |
return; | |
- Creature* pet = _player->GetMap()->GetCreatureOrPetOrVehicle(guid); | |
+ if (GUID_HIPART(guid) == HIGHGUID_PLAYER) | |
+ return; | |
+ | |
+ Creature* pet = ObjectAccessor::GetCreatureOrPetOrVehicle(*_player,guid); | |
if (!pet || (pet != _player->GetPet() && pet!= _player->GetCharm())) | |
{ | |
diff --git a/src/game/Player.cpp b/src/game/Player.cpp | |
index 4b71715..4f96537 100644 | |
--- a/src/game/Player.cpp | |
+++ b/src/game/Player.cpp | |
@@ -465,7 +465,6 @@ Player::Player (WorldSession *session): Unit(), m_achievementMgr(this), m_reputa | |
// group is initialized in the reference constructor | |
SetGroupInvite(NULL); | |
m_groupUpdateMask = 0; | |
- m_auraUpdateMask = 0; | |
duel = NULL; | |
@@ -1755,6 +1754,7 @@ bool Player::TeleportTo(uint32 mapid, float x, float y, float z, float orientati | |
m_transport = NULL; | |
m_movementInfo.ClearTransportData(); | |
} | |
+ ExitVehicle(); | |
// The player was ported to another map and looses the duel immediately. | |
// We have to perform this check before the teleport, otherwise the | |
@@ -2237,7 +2237,7 @@ Creature* Player::GetNPCIfCanInteractWith(ObjectGuid guid, uint32 npcflagmask) | |
return NULL; | |
// exist (we need look pets also for some interaction (quest/etc) | |
- Creature *unit = GetMap()->GetCreatureOrPetOrVehicle(guid); | |
+ Creature *unit = ObjectAccessor::GetCreatureOrPetOrVehicle(*this,guid); | |
if (!unit) | |
return NULL; | |
@@ -8454,6 +8454,41 @@ void Player::SendInitWorldStates(uint32 zoneid, uint32 areaid) | |
break; | |
case 3703: // Shattrath City | |
break; | |
+ 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; | |
default: | |
FillInitialWorldState(data,count, 0x914, 0x0); // 7 | |
FillInitialWorldState(data,count, 0x913, 0x0); // 8 | |
@@ -13064,7 +13099,8 @@ void Player::PrepareQuestMenu( uint64 guid ) | |
QuestRelations* pObjectQIR; | |
// pets also can have quests | |
- if (Creature *pCreature = GetMap()->GetCreatureOrPetOrVehicle(guid)) | |
+ Creature *pCreature = ObjectAccessor::GetCreatureOrPetOrVehicle(*this, guid); | |
+ if( pCreature ) | |
{ | |
pObject = (Object*)pCreature; | |
pObjectQR = &sObjectMgr.mCreatureQuestRelations; | |
@@ -13158,7 +13194,8 @@ void Player::SendPreparedQuest(uint64 guid) | |
std::string title = ""; | |
// need pet case for some quests | |
- if (Creature *pCreature = GetMap()->GetCreatureOrPetOrVehicle(guid)) | |
+ Creature *pCreature = ObjectAccessor::GetCreatureOrPetOrVehicle(*this,guid); | |
+ if (pCreature) | |
{ | |
uint32 textid = GetGossipTextId(pCreature); | |
@@ -13231,7 +13268,8 @@ Quest const * Player::GetNextQuest( uint64 guid, Quest const *pQuest ) | |
QuestRelations* pObjectQR; | |
QuestRelations* pObjectQIR; | |
- if (Creature *pCreature = GetMap()->GetCreatureOrPetOrVehicle(guid)) | |
+ Creature *pCreature = ObjectAccessor::GetCreatureOrPetOrVehicle(*this,guid); | |
+ if( pCreature ) | |
{ | |
pObject = (Object*)pCreature; | |
pObjectQR = &sObjectMgr.mCreatureQuestRelations; | |
@@ -18183,7 +18221,12 @@ void Player::HandleStealthedUnitsDetection() | |
// target aura duration for caster show only if target exist at caster client | |
// send data at target visibility change (adding to client) | |
if((*i)!=this && (*i)->isType(TYPEMASK_UNIT)) | |
+ { | |
SendAurasForTarget(*i); | |
+ WorldPacket data; | |
+ (*i)->BuildHeartBeatMsg(&data); | |
+ GetSession()->SendPacket(&data); | |
+ } | |
} | |
} | |
else | |
@@ -18218,7 +18261,7 @@ bool Player::ActivateTaxiPathTo(std::vector<uint32> const& nodes, Creature* npc | |
if(npc) | |
{ | |
// not let cheating with start flight mounted | |
- if(IsMounted()) | |
+ if(IsMounted() || GetVehicleGUID()) | |
{ | |
WorldPacket data(SMSG_ACTIVATETAXIREPLY, 4); | |
data << uint32(ERR_TAXIPLAYERALREADYMOUNTED); | |
@@ -18247,6 +18290,7 @@ bool Player::ActivateTaxiPathTo(std::vector<uint32> const& nodes, Creature* npc | |
else | |
{ | |
RemoveSpellsCausingAura(SPELL_AURA_MOUNTED); | |
+ ExitVehicle(); | |
if( m_ShapeShiftFormSpellId && m_form != FORM_BATTLESTANCE && m_form != FORM_BERSERKERSTANCE && m_form != FORM_DEFENSIVESTANCE && m_form != FORM_SHADOW ) | |
RemoveAurasDueToSpell(m_ShapeShiftFormSpellId); | |
@@ -19366,7 +19410,12 @@ void Player::UpdateVisibilityOf(WorldObject const* viewPoint, WorldObject* targe | |
// target aura duration for caster show only if target exist at caster client | |
// send data at target visibility change (adding to client) | |
if(target!=this && target->isType(TYPEMASK_UNIT)) | |
+ { | |
SendAurasForTarget((Unit*)target); | |
+ WorldPacket data; | |
+ ((Unit*)target)->BuildHeartBeatMsg(&data); | |
+ GetSession()->SendPacket(&data); | |
+ } | |
if(target->GetTypeId()==TYPEID_UNIT && ((Creature*)target)->isAlive()) | |
((Creature*)target)->SendMonsterMoveWithSpeedToCurrentDestination(this); | |
@@ -19431,13 +19480,22 @@ void Player::InitPrimaryProfessions() | |
void Player::SendComboPoints() | |
{ | |
Unit *combotarget = ObjectAccessor::GetUnit(*this, m_comboTarget); | |
- if (combotarget) | |
- { | |
- WorldPacket data(SMSG_UPDATE_COMBO_POINTS, combotarget->GetPackGUID().size()+1); | |
- data << combotarget->GetPackGUID(); | |
- data << uint8(m_comboPoints); | |
- GetSession()->SendPacket(&data); | |
- } | |
+ if (!combotarget) | |
+ return; | |
+ | |
+ WorldPacket data; | |
+ if(!GetVehicleGUID()) | |
+ data.Initialize(SMSG_UPDATE_COMBO_POINTS, combotarget->GetPackGUID().size()+1); | |
+ else{ | |
+ if(Unit *vehicle = ObjectAccessor::GetUnit(*this, GetVehicleGUID())) | |
+ { | |
+ data.Initialize(SMSG_PET_UPDATE_COMBO_POINTS, vehicle->GetPackGUID().size()+combotarget->GetPackGUID().size()+1); | |
+ data << vehicle->GetPackGUID(); | |
+ }else return; | |
+ } | |
+ data << combotarget->GetPackGUID(); | |
+ data << uint8(m_comboPoints); | |
+ GetSession()->SendPacket(&data); | |
} | |
void Player::AddComboPoints(Unit* target, int8 count) | |
@@ -19560,6 +19618,13 @@ void Player::SendInitialPacketsBeforeAddToMap() | |
void Player::SendInitialPacketsAfterAddToMap() | |
{ | |
+ if(getClass() == CLASS_DEATH_KNIGHT) | |
+ ResyncRunes(MAX_RUNES); | |
+ | |
+ WorldPacket data0(SMSG_SET_PHASE_SHIFT, 4); | |
+ data0 << uint32(GetPhaseMask()); | |
+ GetSession()->SendPacket(&data0); | |
+ | |
// update zone | |
uint32 newzone, newarea; | |
GetZoneAndAreaId(newzone,newarea); | |
@@ -19598,6 +19663,14 @@ void Player::SendInitialPacketsAfterAddToMap() | |
SendMessageToSet(&data2,true); | |
} | |
+ if(GetVehicleGUID()) | |
+ { | |
+ WorldPacket data3(SMSG_FORCE_MOVE_ROOT, 10); | |
+ data3 << GetPackGUID(); | |
+ data3 << (uint32)((m_movementInfo.GetVehicleSeatFlags() & SF_CAN_CAST) ? 2 : 0); | |
+ SendMessageToSet(&data3,true); | |
+ } | |
+ | |
SendAurasForTarget(this); | |
SendEnchantmentDurations(); // must be after add to map | |
SendItemDurations(); // must be after add to map | |
@@ -19612,7 +19685,7 @@ void Player::SendUpdateToOutOfRangeGroupMembers() | |
m_groupUpdateMask = GROUP_UPDATE_FLAG_NONE; | |
m_auraUpdateMask = 0; | |
- if(Pet *pet = GetPet()) | |
+ if(Unit *pet = GetCharmOrPet()) | |
pet->ResetAuraUpdateMask(); | |
} | |
@@ -20057,7 +20130,7 @@ void Player::UpdateForQuestWorldObjects() | |
} | |
else if (itr->IsCreatureOrVehicle()) | |
{ | |
- Creature *obj = GetMap()->GetCreatureOrPetOrVehicle(*itr); | |
+ Creature *obj = ObjectAccessor::GetCreatureOrPetOrVehicle(*this, *itr); | |
if(!obj) | |
continue; | |
@@ -20329,8 +20402,8 @@ void Player::RewardSinglePlayerAtKill(Unit* pVictim) | |
// honor can be in PvP and !PvP (racial leader) cases | |
RewardHonor(pVictim,1); | |
- // xp and reputation only in !PvP case | |
- if(!PvP) | |
+ // xp and reputation only in !PvP case and not in vehicle | |
+ if(!PvP && !(GetVehicleGUID() && (m_movementInfo.GetVehicleFlags() & VF_GIVE_EXP))) | |
{ | |
RewardReputation(pVictim,1); | |
GiveXP(xp, pVictim); | |
@@ -20830,26 +20903,16 @@ void Player::ApplyGlyphs(bool apply) | |
ApplyGlyph(i,apply); | |
} | |
-void Player::EnterVehicle(Vehicle *vehicle) | |
+void Player::SendEnterVehicle(Vehicle *vehicle) | |
{ | |
- VehicleEntry const *ve = sVehicleStore.LookupEntry(vehicle->GetVehicleId()); | |
- if(!ve) | |
- return; | |
- | |
- VehicleSeatEntry const *veSeat = sVehicleSeatStore.LookupEntry(ve->m_seatID[0]); | |
- if(!veSeat) | |
- return; | |
- | |
- vehicle->SetCharmerGUID(GetGUID()); | |
- vehicle->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_SPELLCLICK); | |
- vehicle->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PLAYER_CONTROLLED); | |
- vehicle->setFaction(getFaction()); | |
- | |
- SetCharm(vehicle); // charm | |
- m_camera.SetView(vehicle); // set view | |
- | |
- SetClientControl(vehicle, 1); // redirect controls to vehicle | |
- SetMover(vehicle); | |
+ if(m_transport) // if we were on a transport, leave | |
+ { | |
+ m_transport->RemovePassenger(this); | |
+ m_transport = NULL; | |
+ } | |
+ // vehicle is our transport from now, if we get to zeppelin or boat | |
+ // with vehicle, ONLY my vehicle will be passenger on that transport | |
+ // player ----> vehicle ----> zeppelin | |
WorldPacket data(SMSG_ON_CANCEL_EXPECTED_RIDE_VEHICLE_AURA, 0); | |
GetSession()->SendPacket(&data); | |
@@ -20866,60 +20929,20 @@ void Player::EnterVehicle(Vehicle *vehicle) | |
data << vehicle->GetOrientation(); // o | |
// transport part, TODO: load/calculate seat offsets | |
data << uint64(vehicle->GetGUID()); // transport guid | |
- data << float(veSeat->m_attachmentOffsetX); // transport offsetX | |
- data << float(veSeat->m_attachmentOffsetY); // transport offsetY | |
- data << float(veSeat->m_attachmentOffsetZ); // transport offsetZ | |
- data << float(0); // transport orientation | |
+ data << float(m_movementInfo.GetTransportPos()->x); // transport offsetX | |
+ data << float(m_movementInfo.GetTransportPos()->y); // transport offsetY | |
+ data << float(m_movementInfo.GetTransportPos()->z); // transport offsetZ | |
+ data << float(m_movementInfo.GetTransportPos()->o); // transport orientation | |
data << uint32(getMSTime()); // transport time | |
data << uint8(0); // seat | |
// end of transport part | |
data << uint32(0); // fall time | |
GetSession()->SendPacket(&data); | |
- data.Initialize(SMSG_PET_SPELLS, 8+2+4+4+4*MAX_UNIT_ACTION_BAR_INDEX+1+1); | |
- data << uint64(vehicle->GetGUID()); | |
- data << uint16(0); | |
- data << uint32(0); | |
- data << uint32(0x00000101); | |
- | |
- for(uint32 i = 0; i < 10; ++i) | |
- data << uint16(0) << uint8(0) << uint8(i+8); | |
- | |
- data << uint8(0); | |
- data << uint8(0); | |
- GetSession()->SendPacket(&data); | |
-} | |
- | |
-void Player::ExitVehicle(Vehicle *vehicle) | |
-{ | |
- vehicle->SetCharmerGUID(0); | |
- vehicle->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_SPELLCLICK); | |
- vehicle->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PLAYER_CONTROLLED); | |
- vehicle->setFaction((GetTeam() == ALLIANCE) ? vehicle->GetCreatureInfo()->faction_A : vehicle->GetCreatureInfo()->faction_H); | |
- | |
- SetCharm(NULL); | |
- m_camera.ResetView(); | |
- | |
- SetClientControl(vehicle, 0); | |
- SetMover(NULL); | |
- | |
- WorldPacket data(MSG_MOVE_TELEPORT_ACK, 30); | |
- data << GetPackGUID(); | |
- data << uint32(0); // counter? | |
- data << uint32(MOVEFLAG_ROOT); // fly unk | |
- data << uint16(MOVEFLAG2_UNK4); // special flags | |
- data << uint32(getMSTime()); // time | |
- data << vehicle->GetPositionX(); // x | |
- data << vehicle->GetPositionY(); // y | |
- data << vehicle->GetPositionZ(); // z | |
- data << vehicle->GetOrientation(); // o | |
- data << uint32(0); // fall time | |
- GetSession()->SendPacket(&data); | |
- | |
- RemovePetActionBar(); | |
- | |
- // maybe called at dummy aura remove? | |
- // CastSpell(this, 45472, true); // Parachute | |
+ /*data.Initialize(SMSG_UNKNOWN_1191, 12); | |
+ data << uint64(GetGUID()); | |
+ data << uint64(vehicle->GetVehicleId()); // not sure | |
+ SendMessageToSet(&data, true);*/ | |
} | |
bool Player::isTotalImmune() | |
@@ -20984,7 +21007,8 @@ void Player::ConvertRune(uint8 index, RuneType newType) | |
void Player::ResyncRunes(uint8 count) | |
{ | |
- WorldPacket data(SMSG_RESYNC_RUNES, count * 2); | |
+ WorldPacket data(SMSG_RESYNC_RUNES, 4 + count * 2); | |
+ data << uint32(count + 1); | |
for(uint32 i = 0; i < count; ++i) | |
{ | |
data << uint8(GetCurrentRune(i)); // rune type | |
diff --git a/src/game/Player.h b/src/game/Player.h | |
index f7b0afa..e4a2da1 100644 | |
--- a/src/game/Player.h | |
+++ b/src/game/Player.h | |
@@ -2194,6 +2194,7 @@ class MANGOS_DLL_SPEC Player : public Unit | |
/*********************************************************/ | |
bool HasMovementFlag(MovementFlags f) const; // for script access to m_movementInfo.HasMovementFlag | |
void UpdateFallInformationIfNeed(MovementInfo const& minfo,uint16 opcode); | |
+ | |
void SetFallInformation(uint32 time, float z) | |
{ | |
m_lastFallTime = time; | |
@@ -2215,8 +2216,8 @@ class MANGOS_DLL_SPEC Player : public Unit | |
Unit* GetMover() const { return m_mover; } | |
bool IsSelfMover() const { return m_mover == this; }// normal case for player not controlling other unit | |
- void EnterVehicle(Vehicle *vehicle); | |
- void ExitVehicle(Vehicle *vehicle); | |
+ // vehicle system | |
+ void SendEnterVehicle(Vehicle *vehicle); | |
ObjectGuid const& GetFarSightGuid() const { return GetGuidValue(PLAYER_FARSIGHT); } | |
@@ -2319,8 +2320,6 @@ class MANGOS_DLL_SPEC Player : public Unit | |
uint8 GetSubGroup() const { return m_group.getSubGroup(); } | |
uint32 GetGroupUpdateFlag() const { return m_groupUpdateMask; } | |
void SetGroupUpdateFlag(uint32 flag) { m_groupUpdateMask |= flag; } | |
- const uint64& GetAuraUpdateMask() const { return m_auraUpdateMask; } | |
- void SetAuraUpdateMask(uint8 slot) { m_auraUpdateMask |= (uint64(1) << slot); } | |
Player* GetNextRandomRaidMember(float radius); | |
PartyResult CanUninviteFromGroup() const; | |
// BattleGround Group System | |
@@ -2571,7 +2570,6 @@ class MANGOS_DLL_SPEC Player : public Unit | |
GroupReference m_originalGroup; | |
Group *m_groupInvite; | |
uint32 m_groupUpdateMask; | |
- uint64 m_auraUpdateMask; | |
uint64 m_miniPet; | |
diff --git a/src/game/QuestHandler.cpp b/src/game/QuestHandler.cpp | |
index a0b7872..b8c9374 100644 | |
--- a/src/game/QuestHandler.cpp | |
+++ b/src/game/QuestHandler.cpp | |
@@ -659,9 +659,8 @@ void WorldSession::HandleQuestgiverStatusMultipleQuery(WorldPacket& /*recvPacket | |
if (itr->IsCreatureOrPet()) | |
{ | |
// need also pet quests case support | |
- Creature *questgiver = GetPlayer()->GetMap()->GetCreatureOrPetOrVehicle(*itr); | |
- | |
- if (!questgiver || questgiver->IsHostileTo(_player)) | |
+ Creature *questgiver = ObjectAccessor::GetCreatureOrPetOrVehicle(*GetPlayer(),*itr); | |
+ if(!questgiver || questgiver->IsHostileTo(_player)) | |
continue; | |
if (!questgiver->HasFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_QUESTGIVER)) | |
diff --git a/src/game/ReactorAI.cpp b/src/game/ReactorAI.cpp | |
index f39cd1a..fd52ee2 100644 | |
--- a/src/game/ReactorAI.cpp | |
+++ b/src/game/ReactorAI.cpp | |
@@ -116,6 +116,7 @@ ReactorAI::EnterEvadeMode() | |
DEBUG_FILTER_LOG(LOG_FILTER_AI_AND_MOVEGENSS, "Creature stopped attacking, victim %s [guid=%u]", victim->isAlive() ? "out run him" : "is dead", m_creature->GetGUIDLow()); | |
} | |
+ m_creature->ExitVehicle(); | |
m_creature->RemoveAllAuras(); | |
m_creature->DeleteThreatList(); | |
i_victimGuid = 0; | |
diff --git a/src/game/SharedDefines.h b/src/game/SharedDefines.h | |
index 3e25e4b..9e8715b 100644 | |
--- a/src/game/SharedDefines.h | |
+++ b/src/game/SharedDefines.h | |
@@ -2462,6 +2462,29 @@ enum DiminishingGroup | |
DIMINISHING_LIMITONLY | |
}; | |
+ | |
+/* NOTE : vehicles and seats has their own flags in DBC, | |
+but for now, they are too unknown for us, to use them */ | |
+enum CustomVehicleFLags | |
+{ | |
+ VF_CANT_MOVE = 0x0001, // vehicle cant move, only turn, maybe handle by some auras? | |
+ VF_FACTION = 0x0002, // vehicle retain its own faction | |
+ VF_DESPAWN_NPC = 0x0004, // vehicle will delete npc on spellclick | |
+ VF_DESPAWN_AT_LEAVE = 0x0008, // vehicle will be deleted when rider leaves | |
+ VF_CAN_BE_HEALED = 0x0010, // vehicle can be healed | |
+ VF_GIVE_EXP = 0x0020, // vehicle will give exp for killing enemies | |
+ VF_MOVEMENT = 0x0040, // vehicle will move on its own, not depending on rider, however rider can cast spells | |
+ VF_NON_SELECTABLE = 0x0080 // vehicle will be not selectable after rider enter | |
+ //VF_HAS_FUEL = 0x0100, // TODO : find out what energy type is fuel and implement this | |
+}; | |
+ | |
+enum CustomVehicleSeatFLags | |
+{ | |
+ SF_MAIN_RIDER = 0x0001, // the one who controlls vehicle, can also cast spells | |
+ SF_UNATTACKABLE = 0x0002, // hided inside, and unatackable until vehicle is destroyed | |
+ SF_CAN_CAST = 0x0004, // player/npc can rotate, and cast OWN spells | |
+ SF_UNACCESSIBLE = 0x0008 // player cant enter this seat by normal way (only by script) | |
+}; | |
enum ResponseCodes | |
{ | |
RESPONSE_SUCCESS = 0x00, | |
diff --git a/src/game/Spell.cpp b/src/game/Spell.cpp | |
index 9727b61..f40ee66 100644 | |
--- a/src/game/Spell.cpp | |
+++ b/src/game/Spell.cpp | |
@@ -120,7 +120,8 @@ SpellCastTargets::SpellCastTargets() | |
m_itemTargetGUID = 0; | |
m_itemTargetEntry = 0; | |
- m_srcX = m_srcY = m_srcZ = m_destX = m_destY = m_destZ = 0.0f; | |
+ m_srcX = m_srcY = m_srcZ = m_srcO = m_destX = m_destY = m_destZ = 0.0f; | |
+ m_elevation = m_speed = 0.0f; | |
m_strTarget = ""; | |
m_targetMask = 0; | |
} | |
@@ -257,6 +258,19 @@ void SpellCastTargets::read( ByteBuffer& data, Unit *caster ) | |
data >> m_destX >> m_destY >> m_destZ; | |
if(!MaNGOS::IsValidMapCoord(m_destX, m_destY, m_destZ)) | |
throw ByteBufferException(false, data.rpos(), 0, data.size()); | |
+ | |
+ if( m_targetMask & TARGET_FLAG_SOURCE_LOCATION ) | |
+ { | |
+ if(data.rpos() + 4 + 4 <= data.size()) | |
+ { | |
+ data >> m_elevation >> m_speed; | |
+ // TODO: should also read | |
+ m_srcO = caster->GetOrientation(); | |
+ //*data >> uint16 >> uint8 >> uint32 >> uint32; | |
+ //*data >> float >> float >> float >> float... | |
+ } | |
+ } | |
+ | |
} | |
if( m_targetMask & TARGET_FLAG_STRING ) | |
@@ -1596,9 +1610,11 @@ void Spell::SetTargetMap(SpellEffectIndex effIndex, uint32 targetMode, UnitList& | |
case TARGET_TOTEM_FIRE: | |
case TARGET_SELF: | |
case TARGET_SELF2: | |
- case TARGET_AREAEFFECT_CUSTOM_2: | |
+ { | |
+ // used for targeting gameobjects | |
targetUnitMap.push_back(m_caster); | |
break; | |
+ } | |
case TARGET_RANDOM_ENEMY_CHAIN_IN_AREA: | |
{ | |
m_targets.m_targetMask = 0; | |
@@ -1867,6 +1883,9 @@ void Spell::SetTargetMap(SpellEffectIndex effIndex, uint32 targetMode, UnitList& | |
break; | |
default: | |
FillAreaTargets(targetUnitMap, m_targets.m_destX, m_targets.m_destY, radius, PUSH_DEST_CENTER, SPELL_TARGETS_AOE_DAMAGE); | |
+ | |
+ // exclude caster (this can be important if this not original caster, for example vehicle) | |
+ targetUnitMap.remove(m_caster); | |
break; | |
} | |
break; | |
@@ -2361,7 +2380,13 @@ void Spell::SetTargetMap(SpellEffectIndex effIndex, uint32 targetMode, UnitList& | |
case TARGET_DYNAMIC_OBJECT_LEFT_SIDE: | |
case TARGET_DYNAMIC_OBJECT_RIGHT_SIDE: | |
{ | |
- if (!(m_targets.m_targetMask & TARGET_FLAG_DEST_LOCATION)) | |
+ //This should be targeting of destructible objects by vehicles (ram spells...) | |
+ if(m_spellInfo->EffectImplicitTargetB[effIndex] == TARGET_AREAEFFECT_CUSTOM_2) | |
+ { | |
+ //FIXME | |
+ break; | |
+ } | |
+ else if (!(m_targets.m_targetMask & TARGET_FLAG_DEST_LOCATION)) | |
{ | |
float angle = m_caster->GetOrientation(); | |
switch(targetMode) | |
@@ -3347,7 +3372,7 @@ void Spell::finish(bool ok) | |
m_caster->resetAttackTimer(RANGED_ATTACK);*/ | |
// Clear combo at finish state | |
- if(m_caster->GetTypeId() == TYPEID_PLAYER && NeedsComboPoints(m_spellInfo)) | |
+ if((m_caster->GetTypeId() == TYPEID_PLAYER || ((Creature*)m_caster)->isVehicle()) && NeedsComboPoints(m_spellInfo)) | |
{ | |
// Not drop combopoints if negative spell and if any miss on enemy exist | |
bool needDrop = true; | |
@@ -3366,7 +3391,12 @@ void Spell::finish(bool ok) | |
} | |
} | |
if (needDrop) | |
- ((Player*)m_caster)->ClearComboPoints(); | |
+ { | |
+ if(m_caster->GetTypeId() == TYPEID_PLAYER) | |
+ ((Player*)m_caster)->ClearComboPoints(); | |
+ else | |
+ ((Player*)m_caster->GetCharmer())->ClearComboPoints(); | |
+ } | |
} | |
// potions disabled by client, send event "not in combat" if need | |
@@ -4560,11 +4590,16 @@ SpellCastResult Spell::CheckCast(bool strict) | |
return locRes; | |
// not let players cast spells at mount (and let do it to creatures) | |
- if (m_caster->IsMounted() && m_caster->GetTypeId()==TYPEID_PLAYER && !m_IsTriggeredSpell && | |
+ if ((m_caster->IsMounted() || m_caster->GetVehicleGUID()) && m_caster->GetTypeId()==TYPEID_PLAYER && !m_IsTriggeredSpell && | |
!IsPassiveSpell(m_spellInfo) && !(m_spellInfo->Attributes & SPELL_ATTR_CASTABLE_WHILE_MOUNTED)) | |
{ | |
if (m_caster->isInFlight()) | |
return SPELL_FAILED_NOT_ON_TAXI; | |
+ else if(m_caster->GetVehicleGUID()) | |
+ { | |
+ if(!(m_caster->m_movementInfo.GetVehicleSeatFlags() & SF_CAN_CAST)) | |
+ return SPELL_FAILED_NOT_MOUNTED; | |
+ } | |
else | |
return SPELL_FAILED_NOT_MOUNTED; | |
} | |
@@ -5384,33 +5419,48 @@ SpellCastResult Spell::CheckPetCast(Unit* target) | |
if(!_target->isAlive()) | |
return SPELL_FAILED_BAD_TARGETS; | |
- if(IsPositiveSpell(m_spellInfo->Id)) | |
- { | |
- if(m_caster->IsHostileTo(_target)) | |
- return SPELL_FAILED_BAD_TARGETS; | |
- } | |
- else | |
- { | |
- bool duelvsplayertar = false; | |
- for(int j = 0; j < MAX_EFFECT_INDEX; ++j) | |
- { | |
- //TARGET_DUELVSPLAYER is positive AND negative | |
- duelvsplayertar |= (m_spellInfo->EffectImplicitTargetA[j] == TARGET_DUELVSPLAYER); | |
- } | |
- if(m_caster->IsFriendlyTo(target) && !duelvsplayertar) | |
- { | |
- return SPELL_FAILED_BAD_TARGETS; | |
- } | |
- } | |
+ if(!IsValidSingleTargetSpell(_target)) | |
+ return SPELL_FAILED_BAD_TARGETS; | |
} | |
//cooldown | |
if(((Creature*)m_caster)->HasSpellCooldown(m_spellInfo->Id)) | |
return SPELL_FAILED_NOT_READY; | |
} | |
+ // NOTE : this is done twice, also in spell->prepare(&(spell->m_targets)); | |
return CheckCast(true); | |
} | |
+bool Spell::IsValidSingleTargetEffect(Unit const* target, Targets type) const | |
+{ | |
+ switch(type) | |
+ { | |
+ case TARGET_CHAIN_DAMAGE: | |
+ return !m_caster->IsFriendlyTo(target); | |
+ case TARGET_SINGLE_FRIEND: | |
+ case TARGET_AREAEFFECT_PARTY: | |
+ return m_caster->IsFriendlyTo(target); | |
+ case TARGET_SINGLE_PARTY: | |
+ return m_caster != target && m_caster->IsInPartyWith(target); | |
+ case TARGET_SINGLE_FRIEND_2: | |
+ return m_caster->IsInRaidWith(target); | |
+ } | |
+ return true; | |
+} | |
+ | |
+bool Spell::IsValidSingleTargetSpell(Unit const* target) const | |
+{ | |
+ for(int i = 0; i < 3; ++i) | |
+ { | |
+ if(!IsValidSingleTargetEffect(target, Targets(m_spellInfo->EffectImplicitTargetA[i]))) | |
+ return false; | |
+ // Need to check B? | |
+ //if(!IsValidSingleTargetEffect(m_spellInfo->EffectImplicitTargetB[i], target) | |
+ // return false; | |
+ } | |
+ return true; | |
+} | |
+ | |
SpellCastResult Spell::CheckCasterAuras() const | |
{ | |
// Flag drop spells totally immuned to caster auras | |
diff --git a/src/game/Spell.h b/src/game/Spell.h | |
index 2db96b1..b80ad5f 100644 | |
--- a/src/game/Spell.h | |
+++ b/src/game/Spell.h | |
@@ -166,8 +166,9 @@ class SpellCastTargets | |
void Update(Unit* caster); | |
- float m_srcX, m_srcY, m_srcZ; | |
+ float m_srcX, m_srcY, m_srcZ, m_srcO; | |
float m_destX, m_destY, m_destZ; | |
+ float m_elevation, m_speed; | |
std::string m_strTarget; | |
uint32 m_targetMask; | |
@@ -342,6 +343,8 @@ class Spell | |
void EffectPlayMusic(SpellEffectIndex eff_idx); | |
void EffectSpecCount(SpellEffectIndex eff_idx); | |
void EffectActivateSpec(SpellEffectIndex eff_idx); | |
+ void EffectSummonVehicle(SpellEffectIndex eff_idx); | |
+ void EffectDamageBuilding(SpellEffectIndex eff_idx); | |
Spell( Unit* caster, SpellEntry const *info, bool triggered, ObjectGuid originalCasterGUID = ObjectGuid(), Spell** triggeringContainer = NULL ); | |
~Spell(); | |
@@ -357,6 +360,8 @@ class Spell | |
SpellCastResult CheckCast(bool strict); | |
SpellCastResult CheckPetCast(Unit* target); | |
+ bool IsValidSingleTargetEffect(Unit const* target, Targets type) const; | |
+ bool IsValidSingleTargetSpell(Unit const* target) const; | |
// handlers | |
void handle_immediate(); | |
diff --git a/src/game/SpellAuras.cpp b/src/game/SpellAuras.cpp | |
index 5ff4944..eae5df1 100644 | |
--- a/src/game/SpellAuras.cpp | |
+++ b/src/game/SpellAuras.cpp | |
@@ -3282,7 +3282,7 @@ void Aura::HandleModPossess(bool apply, bool Real) | |
{ | |
((Creature*)target)->AIM_Initialize(); | |
} | |
- else if(target->GetTypeId() == TYPEID_PLAYER) | |
+ else if(target->GetTypeId() == TYPEID_PLAYER && !target->GetVehicleGUID()) | |
{ | |
((Player*)target)->SetClientControl(target, 0); | |
} | |
@@ -3313,7 +3313,7 @@ void Aura::HandleModPossess(bool apply, bool Real) | |
target->SetCharmerGUID(0); | |
- if(target->GetTypeId() == TYPEID_PLAYER) | |
+ if(target->GetTypeId() == TYPEID_PLAYER && !target->GetVehicleGUID()) | |
{ | |
((Player*)target)->setFactionForRace(target->getRace()); | |
((Player*)target)->SetClientControl(target, 1); | |
@@ -3595,10 +3595,13 @@ void Aura::HandleAuraModStun(bool apply, bool Real) | |
target->SetStandState(UNIT_STAND_STATE_STAND);// in 1.5 client | |
} | |
- WorldPacket data(SMSG_FORCE_MOVE_ROOT, 8); | |
- data << target->GetPackGUID(); | |
- data << uint32(0); | |
- target->SendMessageToSet(&data, true); | |
+ if(!m_target->hasUnitState(UNIT_STAT_ON_VEHICLE)) | |
+ { | |
+ WorldPacket data(SMSG_FORCE_MOVE_ROOT, 8); | |
+ data << target->GetPackGUID(); | |
+ data << uint32(0); | |
+ target->SendMessageToSet(&data,true); | |
+ } | |
// Summon the Naj'entus Spine GameObject on target if spell is Impaling Spine | |
if(GetId() == 39837) | |
@@ -3648,7 +3651,7 @@ void Aura::HandleAuraModStun(bool apply, bool Real) | |
target->clearUnitState(UNIT_STAT_STUNNED); | |
target->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_STUNNED); | |
- if(!target->hasUnitState(UNIT_STAT_ROOT)) // prevent allow move if have also root effect | |
+ if(!target->hasUnitState(UNIT_STAT_ROOT | UNIT_STAT_ON_VEHICLE)) // prevent allow move if have also root effect | |
{ | |
if(target->getVictim() && target->isAlive()) | |
target->SetTargetGUID(target->getVictim()->GetGUID()); | |
@@ -3876,11 +3879,13 @@ void Aura::HandleAuraModRoot(bool apply, bool Real) | |
if(target->GetTypeId() == TYPEID_PLAYER) | |
{ | |
- WorldPacket data(SMSG_FORCE_MOVE_ROOT, 10); | |
- data << target->GetPackGUID(); | |
- data << (uint32)2; | |
- target->SendMessageToSet(&data, true); | |
- | |
+ if(!target->hasUnitState(UNIT_STAT_ON_VEHICLE)) | |
+ { | |
+ WorldPacket data(SMSG_FORCE_MOVE_ROOT, 10); | |
+ data << target->GetPackGUID(); | |
+ data << (uint32)2; | |
+ target->SendMessageToSet(&data,true); | |
+ } | |
//Clear unit movement flags | |
((Player*)target)->m_movementInfo.SetMovementFlags(MOVEFLAG_NONE); | |
} | |
@@ -3918,7 +3923,7 @@ void Aura::HandleAuraModRoot(bool apply, bool Real) | |
target->clearUnitState(UNIT_STAT_ROOT); | |
- if(!target->hasUnitState(UNIT_STAT_STUNNED)) // prevent allow move if have also stun effect | |
+ if(!target->hasUnitState(UNIT_STAT_STUNNED | UNIT_STAT_ON_VEHICLE)) // prevent allow move if have also stun effect | |
{ | |
if(target->getVictim() && target->isAlive()) | |
target->SetTargetGUID(target->getVictim()->GetGUID()); | |
@@ -3951,7 +3956,7 @@ void Aura::HandleAuraModSilence(bool apply, bool Real) | |
if(spell->m_spellInfo->PreventionType == SPELL_PREVENTION_TYPE_SILENCE) | |
// Stop spells on prepare or casting state | |
target->InterruptSpell(CurrentSpellTypes(i), false); | |
- } | |
+ } | |
else | |
{ | |
// Real remove called after current aura remove from lists, check if other similar auras active | |
@@ -7317,32 +7322,40 @@ void Aura::HandleArenaPreparation(bool apply, bool Real) | |
*/ | |
void Aura::HandleAuraControlVehicle(bool apply, bool Real) | |
{ | |
- if(!Real) | |
- return; | |
+ if(!Real) | |
+ return; | |
Unit* target = GetTarget(); | |
+ Unit* caster = GetCaster(); | |
if (target->GetTypeId() != TYPEID_UNIT || !((Creature*)target)->isVehicle()) | |
return; | |
Vehicle* vehicle = (Vehicle*)target; | |
- Unit *player = GetCaster(); | |
- if(!player || player->GetTypeId() != TYPEID_PLAYER) | |
+ if(!caster || !vehicle) | |
+ return; | |
+ | |
+ // this can happen due to wrong caster/target spell handling | |
+ // note : SPELL_AURA_CONTROL_VEHICLE can have EffectImplicitTargetA | |
+ // TARGET_SCRIPT, TARGET_DUELVSPLAYER.. etc | |
+ if(caster->GetGUID() == vehicle->GetGUID()) | |
return; | |
if (apply) | |
{ | |
- if(Pet *pet = player->GetPet()) | |
- pet->Remove(PET_SAVE_AS_CURRENT); | |
- ((Player*)player)->EnterVehicle(vehicle); | |
+ if(caster->GetTypeId() == TYPEID_PLAYER) | |
+ { | |
+ WorldPacket data(SMSG_ON_CANCEL_EXPECTED_RIDE_VEHICLE_AURA, 0); | |
+ ((Player*)caster)->GetSession()->SendPacket(&data); | |
+ } | |
+ // if we leave and enter again, this will refresh | |
+ int32 duration = GetSpellMaxDuration(GetSpellProto()); | |
+ if(duration > 0) | |
+ vehicle->SetSpawnDuration(duration); | |
} | |
else | |
{ | |
- SpellEntry const *spell = GetSpellProto(); | |
- | |
// some SPELL_AURA_CONTROL_VEHICLE auras have a dummy effect on the player - remove them | |
- player->RemoveAurasDueToSpell(spell->Id); | |
- | |
- ((Player*)player)->ExitVehicle(vehicle); | |
+ caster->RemoveAurasDueToSpell(GetId()); | |
} | |
} | |
diff --git a/src/game/SpellEffects.cpp b/src/game/SpellEffects.cpp | |
index 28ae6dc..a0c8613 100644 | |
--- a/src/game/SpellEffects.cpp | |
+++ b/src/game/SpellEffects.cpp | |
@@ -57,6 +57,7 @@ | |
#include "GridNotifiers.h" | |
#include "GridNotifiersImpl.h" | |
#include "CellImpl.h" | |
+#include "Vehicle.h" | |
pEffect SpellEffects[TOTAL_SPELL_EFFECTS]= | |
{ | |
@@ -147,9 +148,9 @@ pEffect SpellEffects[TOTAL_SPELL_EFFECTS]= | |
&Spell::EffectStuck, // 84 SPELL_EFFECT_STUCK | |
&Spell::EffectSummonPlayer, // 85 SPELL_EFFECT_SUMMON_PLAYER | |
&Spell::EffectActivateObject, // 86 SPELL_EFFECT_ACTIVATE_OBJECT | |
- &Spell::EffectNULL, // 87 SPELL_EFFECT_WMO_DAMAGE (57 spells in 3.3.2) | |
- &Spell::EffectNULL, // 88 SPELL_EFFECT_WMO_REPAIR (2 spells in 3.3.2) | |
- &Spell::EffectNULL, // 89 SPELL_EFFECT_WMO_CHANGE (7 spells in 3.3.2) | |
+ &Spell::EffectDamageBuilding, // 87 SPELL_EFFECT_WMO_DAMAGE | |
+ &Spell::EffectUnused, // 88 SPELL_EFFECT_WMO_REPAIR | |
+ &Spell::EffectUnused, // 89 SPELL_EFFECT_WMO_CHANGE | |
&Spell::EffectKillCreditPersonal, // 90 SPELL_EFFECT_KILL_CREDIT Kill credit but only for single person | |
&Spell::EffectUnused, // 91 SPELL_EFFECT_THREAT_ALL one spell: zzOLDBrainwash | |
&Spell::EffectEnchantHeldItem, // 92 SPELL_EFFECT_ENCHANT_HELD_ITEM | |
@@ -3862,7 +3863,7 @@ void Spell::EffectSummonType(SpellEffectIndex eff_idx) | |
case SUMMON_PROP_TYPE_SIEGE_VEH: | |
case SUMMON_PROP_TYPE_DRAKE_VEH: | |
// TODO | |
- // EffectSummonVehicle(i); | |
+ EffectSummonVehicle(eff_idx); | |
break; | |
default: | |
sLog.outError("EffectSummonType: Unhandled summon type %u", summon_prop->Type); | |
@@ -3891,7 +3892,7 @@ void Spell::EffectSummonType(SpellEffectIndex eff_idx) | |
case SUMMON_PROP_GROUP_VEHICLE: | |
{ | |
// TODO | |
- // EffectSummonVehicle(i); | |
+ EffectSummonVehicle(eff_idx); | |
break; | |
} | |
default: | |
@@ -3899,7 +3900,6 @@ void Spell::EffectSummonType(SpellEffectIndex eff_idx) | |
break; | |
} | |
} | |
- | |
void Spell::DoSummon(SpellEffectIndex eff_idx) | |
{ | |
if (m_caster->GetPetGUID()) | |
@@ -6519,13 +6519,15 @@ void Spell::EffectAddComboPoints(SpellEffectIndex /*eff_idx*/) | |
if(!unitTarget) | |
return; | |
- if(m_caster->GetTypeId() != TYPEID_PLAYER) | |
- return; | |
- | |
if(damage <= 0) | |
return; | |
- ((Player*)m_caster)->AddComboPoints(unitTarget, damage); | |
+ if(m_caster->GetTypeId() != TYPEID_PLAYER) | |
+ { | |
+ if(((Creature*)m_caster)->isVehicle()) | |
+ ((Player*)m_caster->GetCharmer())->AddComboPoints(unitTarget, damage); | |
+ }else | |
+ ((Player*)m_caster)->AddComboPoints(unitTarget, damage); | |
} | |
void Spell::EffectDuel(SpellEffectIndex eff_idx) | |
@@ -7789,6 +7791,54 @@ void Spell::EffectRenamePet(SpellEffectIndex /*eff_idx*/) | |
unitTarget->RemoveByteFlag(UNIT_FIELD_BYTES_2, 2, UNIT_CAN_BE_RENAMED); | |
} | |
+void Spell::EffectSummonVehicle(SpellEffectIndex eff_idx) | |
+{ | |
+ uint32 creature_entry = m_spellInfo->EffectMiscValue[eff_idx]; | |
+ if(!creature_entry) | |
+ return; | |
+ | |
+ float px, py, pz; | |
+ // If dest location if present | |
+ if (m_targets.m_targetMask & TARGET_FLAG_DEST_LOCATION) | |
+ { | |
+ // Summon unit in dest location | |
+ px = m_targets.m_destX; | |
+ py = m_targets.m_destY; | |
+ pz = m_targets.m_destZ; | |
+ } | |
+ // Summon if dest location not present near caster | |
+ else | |
+ m_caster->GetClosePoint(px,py,pz,3.0f); | |
+ | |
+ Vehicle *v = m_caster->SummonVehicle(creature_entry, px, py, pz, m_caster->GetOrientation()); | |
+ if(!v) | |
+ return; | |
+ | |
+ v->SetUInt32Value(UNIT_CREATED_BY_SPELL, m_spellInfo->Id); | |
+ v->SetCreatorGUID(m_caster->GetGUID()); | |
+ | |
+ if(damage) | |
+ { | |
+ m_caster->CastSpell(v, damage, true); | |
+ m_caster->EnterVehicle(v, 0); | |
+ } | |
+ int32 duration = GetSpellMaxDuration(m_spellInfo); | |
+ if(duration > 0) | |
+ v->SetSpawnDuration(duration); | |
+} | |
+ | |
+void Spell::EffectDamageBuilding(SpellEffectIndex eff_idx) | |
+{ | |
+ if(!gameObjTarget) | |
+ return; | |
+ | |
+ if(gameObjTarget->GetGoType() != GAMEOBJECT_TYPE_DESTRUCTIBLE_BUILDING) | |
+ return; | |
+ | |
+ // NOTE : this can be increased by scaling stat system in vehicles | |
+ gameObjTarget->DealSiegeDamage(damage); | |
+} | |
+ | |
void Spell::EffectPlayMusic(SpellEffectIndex eff_idx) | |
{ | |
if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER) | |
diff --git a/src/game/SpellHandler.cpp b/src/game/SpellHandler.cpp | |
index 41adfd3..ef7cda3 100644 | |
--- a/src/game/SpellHandler.cpp | |
+++ b/src/game/SpellHandler.cpp | |
@@ -27,6 +27,7 @@ | |
#include "Spell.h" | |
#include "ScriptCalls.h" | |
#include "Totem.h" | |
+#include "Vehicle.h" | |
#include "SpellAuras.h" | |
void WorldSession::HandleUseItemOpcode(WorldPacket& recvPacket) | |
@@ -320,6 +321,11 @@ void WorldSession::HandleCastSpellOpcode(WorldPacket& recvPacket) | |
DEBUG_LOG("WORLD: got cast spell packet, spellId - %u, cast_count: %u, unk_flags %u, data length = %i", | |
spellId, cast_count, unk_flags, (uint32)recvPacket.size()); | |
+ // vehicle spells are handled by CMSG_PET_CAST_SPELL, | |
+ // but player is still able to cast own spells | |
+ if(_player->GetCharmGUID() && _player->GetCharmGUID() == _player->GetVehicleGUID()) | |
+ mover = _player; | |
+ | |
SpellEntry const *spellInfo = sSpellStore.LookupEntry(spellId ); | |
if(!spellInfo) | |
@@ -486,7 +492,7 @@ void WorldSession::HandlePetCancelAuraOpcode( WorldPacket& recvPacket) | |
return; | |
} | |
- Creature* pet = GetPlayer()->GetMap()->GetCreatureOrPetOrVehicle(guid); | |
+ Creature* pet=ObjectAccessor::GetCreatureOrPetOrVehicle(*_player,guid); | |
if(!pet) | |
{ | |
@@ -574,19 +580,67 @@ void WorldSession::HandleSpellClick( WorldPacket & recv_data ) | |
if (_player->isInCombat()) // client prevent click and set different icon at combat state | |
return; | |
- Creature *unit = _player->GetMap()->GetCreatureOrPetOrVehicle(guid); | |
+ Creature *unit = ObjectAccessor::GetCreatureOrPetOrVehicle(*_player, guid); | |
if (!unit || unit->isInCombat()) // client prevent click and set different icon at combat state | |
return; | |
- SpellClickInfoMapBounds clickPair = sObjectMgr.GetSpellClickInfoMapBounds(unit->GetEntry()); | |
- for(SpellClickInfoMap::const_iterator itr = clickPair.first; itr != clickPair.second; ++itr) | |
+ if(!_player->IsWithinDistInMap(unit, 10)) | |
+ return; | |
+ | |
+ // cheater? | |
+ if(!unit->HasFlag(UNIT_NPC_FLAGS,UNIT_NPC_FLAG_SPELLCLICK)) | |
+ return; | |
+ | |
+ uint32 vehicleId = 0; | |
+ CreatureDataAddon const *cainfo = unit->GetCreatureAddon(); | |
+ if(cainfo) | |
+ vehicleId = cainfo->vehicle_id; | |
+ | |
+ // handled other (hacky) way to avoid overwriting auras | |
+ if(vehicleId || unit->isVehicle()) | |
+ { | |
+ if(!unit->isAlive()) | |
+ return; | |
+ | |
+ if(_player->GetVehicleGUID()) | |
+ return; | |
+ | |
+ // create vehicle if no one present and kill the original creature to avoid double, triple etc spawns | |
+ if(!unit->isVehicle()) | |
+ { | |
+ Vehicle *v = _player->SummonVehicle(unit->GetEntry(), unit->GetPositionX(), unit->GetPositionY(), unit->GetPositionZ(), unit->GetOrientation(), vehicleId); | |
+ if(!v) | |
+ return; | |
+ | |
+ if(v->GetVehicleFlags() & VF_DESPAWN_NPC) | |
+ { | |
+ v->SetSpawnDuration(unit->GetRespawnDelay()*IN_MILLISECONDS); | |
+ unit->setDeathState(JUST_DIED); | |
+ unit->RemoveCorpse(); | |
+ unit->SetHealth(0); | |
+ } | |
+ unit = v; | |
+ } | |
+ | |
+ if(((Vehicle*)unit)->GetVehicleData()) | |
+ if(uint32 r_aura = ((Vehicle*)unit)->GetVehicleData()->req_aura) | |
+ if(!_player->HasAura(r_aura)) | |
+ return; | |
+ | |
+ _player->EnterVehicle((Vehicle*)unit, 0); | |
+ } | |
+ else | |
{ | |
- if (itr->second.IsFitToRequirements(_player)) | |
+ SpellClickInfoMapBounds clickPair = sObjectMgr.GetSpellClickInfoMapBounds(unit->GetEntry()); | |
+ for(SpellClickInfoMap::const_iterator itr = clickPair.first; itr != clickPair.second; ++itr) | |
{ | |
- Unit *caster = (itr->second.castFlags & 0x1) ? (Unit*)_player : (Unit*)unit; | |
- Unit *target = (itr->second.castFlags & 0x2) ? (Unit*)_player : (Unit*)unit; | |
+ if (itr->second.IsFitToRequirements(_player)) | |
+ { | |
+ Unit *caster = (itr->second.castFlags & 0x1) ? (Unit*)_player : (Unit*)unit; | |
+ Unit *target = (itr->second.castFlags & 0x2) ? (Unit*)_player : (Unit*)unit; | |
- caster->CastSpell(target, itr->second.spellId, true); | |
+ caster->CastSpell(target, itr->second.spellId, true); | |
+ } | |
} | |
} | |
} | |
diff --git a/src/game/Unit.cpp b/src/game/Unit.cpp | |
index 3bb2b78..ec13a6f 100644 | |
--- a/src/game/Unit.cpp | |
+++ b/src/game/Unit.cpp | |
@@ -46,6 +46,7 @@ | |
#include "CellImpl.h" | |
#include "Path.h" | |
#include "Traveller.h" | |
+#include "Vehicle.h" | |
#include "VMapFactory.h" | |
#include "MovementGenerator.h" | |
@@ -242,6 +243,9 @@ Unit::Unit() | |
// remove aurastates allowing special moves | |
for(int i=0; i < MAX_REACTIVE; ++i) | |
m_reactiveTimer[i] = 0; | |
+ | |
+ m_auraUpdateMask = 0; | |
+ m_vehicleGUID = 0; | |
} | |
Unit::~Unit() | |
@@ -411,20 +415,9 @@ void Unit::SendMonsterMoveWithSpeed(float x, float y, float z, uint32 transitTim | |
void Unit::BuildHeartBeatMsg(WorldPacket *data) const | |
{ | |
- MovementFlags move_flags = GetTypeId()==TYPEID_PLAYER | |
- ? ((Player const*)this)->m_movementInfo.GetMovementFlags() | |
- : MOVEFLAG_NONE; | |
- | |
- data->Initialize(MSG_MOVE_HEARTBEAT, 32); | |
+ data->Initialize(MSG_MOVE_HEARTBEAT); | |
*data << GetPackGUID(); | |
- *data << uint32(move_flags); // movement flags | |
- *data << uint16(0); // 2.3.0 | |
- *data << uint32(getMSTime()); // time | |
- *data << float(GetPositionX()); | |
- *data << float(GetPositionY()); | |
- *data << float(GetPositionZ()); | |
- *data << float(GetOrientation()); | |
- *data << uint32(0); | |
+ ((Unit*)this)->m_movementInfo.Write(*data); | |
} | |
void Unit::resetAttackTimer(WeaponAttackType type) | |
@@ -5097,15 +5090,10 @@ void Unit::setPowerType(Powers new_powertype) | |
if(((Player*)this)->GetGroup()) | |
((Player*)this)->SetGroupUpdateFlag(GROUP_UPDATE_FLAG_POWER_TYPE); | |
} | |
- else if(((Creature*)this)->isPet()) | |
+ else if(Unit* owner = GetCharmerOrOwner()) | |
{ | |
- Pet *pet = ((Pet*)this); | |
- if(pet->isControlled()) | |
- { | |
- Unit *owner = GetOwner(); | |
- if(owner && (owner->GetTypeId() == TYPEID_PLAYER) && ((Player*)owner)->GetGroup()) | |
- ((Player*)owner)->SetGroupUpdateFlag(GROUP_UPDATE_FLAG_PET_POWER_TYPE); | |
- } | |
+ if((owner->GetTypeId() == TYPEID_PLAYER) && ((Player*)owner)->GetGroup()) | |
+ ((Player*)owner)->SetGroupUpdateFlag(GROUP_UPDATE_FLAG_PET_POWER_TYPE); | |
} | |
switch(new_powertype) | |
@@ -5262,6 +5250,38 @@ bool Unit::IsHostileTo(Unit const* unit) const | |
return tester_faction->IsHostileTo(*target_faction); | |
} | |
+bool Unit::IsInPartyWith(Unit const *unit) const | |
+{ | |
+ if(this == unit) | |
+ return true; | |
+ | |
+ const Unit *u1 = GetCharmerOrOwnerOrSelf(); | |
+ const Unit *u2 = unit->GetCharmerOrOwnerOrSelf(); | |
+ if(u1 == u2) | |
+ return true; | |
+ | |
+ if(u1->GetTypeId() == TYPEID_PLAYER && u2->GetTypeId() == TYPEID_PLAYER) | |
+ return ((Player*)u1)->IsInSameGroupWith((Player*)u2); | |
+ else | |
+ return false; | |
+} | |
+ | |
+bool Unit::IsInRaidWith(Unit const *unit) const | |
+{ | |
+ if(this == unit) | |
+ return true; | |
+ | |
+ const Unit *u1 = GetCharmerOrOwnerOrSelf(); | |
+ const Unit *u2 = unit->GetCharmerOrOwnerOrSelf(); | |
+ if(u1 == u2) | |
+ return true; | |
+ | |
+ if(u1->GetTypeId() == TYPEID_PLAYER && u2->GetTypeId() == TYPEID_PLAYER) | |
+ return ((Player*)u1)->IsInSameRaidWith((Player*)u2); | |
+ else | |
+ return false; | |
+} | |
+ | |
bool Unit::IsFriendlyTo(Unit const* unit) const | |
{ | |
// always friendly to self | |
@@ -5413,6 +5433,14 @@ bool Unit::Attack(Unit *victim, bool meleeAttack) | |
if(GetTypeId()==TYPEID_PLAYER && IsMounted()) | |
return false; | |
+ // player (also npc?) cannot attack on vehicle | |
+ if(GetTypeId()==TYPEID_PLAYER && GetVehicleGUID()) | |
+ return false; | |
+ | |
+ // player (also npc?) cannot attack on vehicle | |
+ if(GetTypeId()==TYPEID_UNIT && ((Creature*)this)->isVehicle() && GetCharmerGUID()) | |
+ return false; | |
+ | |
// nobody can attack GM in GM-mode | |
if(victim->GetTypeId()==TYPEID_PLAYER) | |
{ | |
@@ -7974,6 +8002,11 @@ void Unit::UpdateSpeed(UnitMoveType mtype, bool forced, float ratio) | |
} | |
float bonus = non_stack_bonus > stack_bonus ? non_stack_bonus : stack_bonus; | |
+ | |
+ //apply creature's base speed | |
+ if(GetTypeId() == TYPEID_UNIT) | |
+ bonus *= ((Creature*)this)->GetBaseSpeed(); | |
+ | |
// now we ready for speed calculation | |
float speed = main_speed_mod ? bonus*(100.0f + main_speed_mod)/100.0f : bonus; | |
@@ -8170,6 +8203,7 @@ void Unit::setDeathState(DeathState s) | |
if (s == JUST_DIED) | |
{ | |
+ ExitVehicle(); | |
RemoveAllAurasOnDeath(); | |
RemoveGuardians(); | |
UnsummonAllTotems(); | |
@@ -8395,7 +8429,8 @@ bool Unit::SelectHostileTarget() | |
} | |
// enter in evade mode in other case | |
- ((Creature*)this)->AI()->EnterEvadeMode(); | |
+ if(!((Creature*)this)->isVehicle()) | |
+ ((Creature*)this)->AI()->EnterEvadeMode(); | |
return false; | |
} | |
@@ -8406,7 +8441,14 @@ bool Unit::SelectHostileTarget() | |
int32 Unit::CalculateSpellDamage(Unit const* target, SpellEntry const* spellProto, SpellEffectIndex effect_index, int32 const* effBasePoints) | |
{ | |
- Player* unitPlayer = (GetTypeId() == TYPEID_PLAYER) ? (Player*)this : NULL; | |
+ Player* unitPlayer; | |
+ | |
+ if(GetTypeId() == TYPEID_PLAYER) | |
+ unitPlayer = (Player*)this; | |
+ else if(((Creature*)this)->isVehicle()) | |
+ unitPlayer = (Player*)GetCharmer(); | |
+ else | |
+ unitPlayer = NULL; | |
uint8 comboPoints = unitPlayer ? unitPlayer->GetComboPoints() : 0; | |
@@ -8471,7 +8513,14 @@ int32 Unit::CalculateSpellDamage(Unit const* target, SpellEntry const* spellProt | |
int32 Unit::CalculateSpellDuration(SpellEntry const* spellProto, SpellEffectIndex effect_index, Unit const* target) | |
{ | |
- Player* unitPlayer = (GetTypeId() == TYPEID_PLAYER) ? (Player*)this : NULL; | |
+ Player* unitPlayer; | |
+ | |
+ if(GetTypeId() == TYPEID_PLAYER) | |
+ unitPlayer = (Player*)this; | |
+ else if(((Creature*)this)->isVehicle()) | |
+ unitPlayer = (Player*)GetCharmer(); | |
+ else | |
+ unitPlayer = NULL; | |
uint8 comboPoints = unitPlayer ? unitPlayer->GetComboPoints() : 0; | |
@@ -8881,15 +8930,10 @@ void Unit::SetHealth(uint32 val) | |
if(((Player*)this)->GetGroup()) | |
((Player*)this)->SetGroupUpdateFlag(GROUP_UPDATE_FLAG_CUR_HP); | |
} | |
- else if(((Creature*)this)->isPet()) | |
+ else if(Unit* owner = GetCharmerOrOwner()) | |
{ | |
- Pet *pet = ((Pet*)this); | |
- if(pet->isControlled()) | |
- { | |
- Unit *owner = GetOwner(); | |
- if(owner && (owner->GetTypeId() == TYPEID_PLAYER) && ((Player*)owner)->GetGroup()) | |
- ((Player*)owner)->SetGroupUpdateFlag(GROUP_UPDATE_FLAG_PET_CUR_HP); | |
- } | |
+ if((owner->GetTypeId() == TYPEID_PLAYER) && ((Player*)owner)->GetGroup()) | |
+ ((Player*)owner)->SetGroupUpdateFlag(GROUP_UPDATE_FLAG_PET_CUR_HP); | |
} | |
} | |
@@ -8904,15 +8948,10 @@ void Unit::SetMaxHealth(uint32 val) | |
if(((Player*)this)->GetGroup()) | |
((Player*)this)->SetGroupUpdateFlag(GROUP_UPDATE_FLAG_MAX_HP); | |
} | |
- else if(((Creature*)this)->isPet()) | |
+ else if(Unit* owner = GetCharmerOrOwner()) | |
{ | |
- Pet *pet = ((Pet*)this); | |
- if(pet->isControlled()) | |
- { | |
- Unit *owner = GetOwner(); | |
- if(owner && (owner->GetTypeId() == TYPEID_PLAYER) && ((Player*)owner)->GetGroup()) | |
- ((Player*)owner)->SetGroupUpdateFlag(GROUP_UPDATE_FLAG_PET_MAX_HP); | |
- } | |
+ if((owner->GetTypeId() == TYPEID_PLAYER) && ((Player*)owner)->GetGroup()) | |
+ ((Player*)owner)->SetGroupUpdateFlag(GROUP_UPDATE_FLAG_PET_MAX_HP); | |
} | |
if(val < health) | |
@@ -8948,20 +8987,19 @@ void Unit::SetPower(Powers power, uint32 val) | |
if(((Player*)this)->GetGroup()) | |
((Player*)this)->SetGroupUpdateFlag(GROUP_UPDATE_FLAG_CUR_POWER); | |
} | |
- else if(((Creature*)this)->isPet()) | |
+ else if(Unit* owner = GetCharmerOrOwner()) | |
{ | |
- Pet *pet = ((Pet*)this); | |
- if(pet->isControlled()) | |
- { | |
- Unit *owner = GetOwner(); | |
- if(owner && (owner->GetTypeId() == TYPEID_PLAYER) && ((Player*)owner)->GetGroup()) | |
- ((Player*)owner)->SetGroupUpdateFlag(GROUP_UPDATE_FLAG_PET_CUR_POWER); | |
- } | |
+ if((owner->GetTypeId() == TYPEID_PLAYER) && ((Player*)owner)->GetGroup()) | |
+ ((Player*)owner)->SetGroupUpdateFlag(GROUP_UPDATE_FLAG_PET_CUR_POWER); | |
- // Update the pet's character sheet with happiness damage bonus | |
- if(pet->getPetType() == HUNTER_PET && power == POWER_HAPPINESS) | |
+ if(((Creature*)this)->isPet()) | |
{ | |
- pet->UpdateDamagePhysical(BASE_ATTACK); | |
+ Pet *pet = ((Pet*)this); | |
+ // Update the pet's character sheet with happiness damage bonus | |
+ if(pet->getPetType() == HUNTER_PET && power == POWER_HAPPINESS) | |
+ { | |
+ pet->UpdateDamagePhysical(BASE_ATTACK); | |
+ } | |
} | |
} | |
} | |
@@ -8977,15 +9015,10 @@ void Unit::SetMaxPower(Powers power, uint32 val) | |
if(((Player*)this)->GetGroup()) | |
((Player*)this)->SetGroupUpdateFlag(GROUP_UPDATE_FLAG_MAX_POWER); | |
} | |
- else if(((Creature*)this)->isPet()) | |
+ else if(Unit* owner = GetCharmerOrOwner()) | |
{ | |
- Pet *pet = ((Pet*)this); | |
- if(pet->isControlled()) | |
- { | |
- Unit *owner = GetOwner(); | |
- if(owner && (owner->GetTypeId() == TYPEID_PLAYER) && ((Player*)owner)->GetGroup()) | |
- ((Player*)owner)->SetGroupUpdateFlag(GROUP_UPDATE_FLAG_PET_MAX_POWER); | |
- } | |
+ if((owner->GetTypeId() == TYPEID_PLAYER) && ((Player*)owner)->GetGroup()) | |
+ ((Player*)owner)->SetGroupUpdateFlag(GROUP_UPDATE_FLAG_PET_MAX_POWER); | |
} | |
if(val < cur_power) | |
@@ -9002,15 +9035,10 @@ void Unit::ApplyPowerMod(Powers power, uint32 val, bool apply) | |
if(((Player*)this)->GetGroup()) | |
((Player*)this)->SetGroupUpdateFlag(GROUP_UPDATE_FLAG_CUR_POWER); | |
} | |
- else if(((Creature*)this)->isPet()) | |
+ else if(Unit* owner = GetCharmerOrOwner()) | |
{ | |
- Pet *pet = ((Pet*)this); | |
- if(pet->isControlled()) | |
- { | |
- Unit *owner = GetOwner(); | |
- if(owner && (owner->GetTypeId() == TYPEID_PLAYER) && ((Player*)owner)->GetGroup()) | |
- ((Player*)owner)->SetGroupUpdateFlag(GROUP_UPDATE_FLAG_PET_CUR_POWER); | |
- } | |
+ if((owner->GetTypeId() == TYPEID_PLAYER) && ((Player*)owner)->GetGroup()) | |
+ ((Player*)owner)->SetGroupUpdateFlag(GROUP_UPDATE_FLAG_PET_CUR_POWER); | |
} | |
} | |
@@ -9024,15 +9052,10 @@ void Unit::ApplyMaxPowerMod(Powers power, uint32 val, bool apply) | |
if(((Player*)this)->GetGroup()) | |
((Player*)this)->SetGroupUpdateFlag(GROUP_UPDATE_FLAG_MAX_POWER); | |
} | |
- else if(((Creature*)this)->isPet()) | |
+ else if(Unit* owner = GetCharmerOrOwner()) | |
{ | |
- Pet *pet = ((Pet*)this); | |
- if(pet->isControlled()) | |
- { | |
- Unit *owner = GetOwner(); | |
- if(owner && (owner->GetTypeId() == TYPEID_PLAYER) && ((Player*)owner)->GetGroup()) | |
- ((Player*)owner)->SetGroupUpdateFlag(GROUP_UPDATE_FLAG_PET_MAX_POWER); | |
- } | |
+ if((owner->GetTypeId() == TYPEID_PLAYER) && ((Player*)owner)->GetGroup()) | |
+ ((Player*)owner)->SetGroupUpdateFlag(GROUP_UPDATE_FLAG_PET_MAX_POWER); | |
} | |
} | |
@@ -9087,6 +9110,7 @@ void Unit::RemoveFromWorld() | |
void Unit::CleanupsBeforeDelete() | |
{ | |
+ ExitVehicle(); // make sure we always leave vehicle, otherwise it will crash | |
if(m_uint32Values) // only for fully created object | |
{ | |
InterruptNonMeleeSpells(true); | |
@@ -9662,8 +9686,12 @@ void Unit::SetFeared(bool apply, uint64 const& casterGUID, uint32 spellID, uint3 | |
} | |
} | |
- if (GetTypeId() == TYPEID_PLAYER) | |
+ if (GetTypeId() == TYPEID_PLAYER && !GetVehicleGUID()) | |
((Player*)this)->SetClientControl(this, !apply); | |
+ | |
+ if (Unit* owner = GetCharmer()) | |
+ if (owner->GetTypeId() == TYPEID_PLAYER) | |
+ ((Player*)owner)->SetClientControl(this, !apply); | |
} | |
void Unit::SetConfused(bool apply, uint64 const& casterGUID, uint32 spellID) | |
@@ -9692,8 +9720,12 @@ void Unit::SetConfused(bool apply, uint64 const& casterGUID, uint32 spellID) | |
} | |
} | |
- if(GetTypeId() == TYPEID_PLAYER) | |
+ if(GetTypeId() == TYPEID_PLAYER && !GetVehicleGUID()) | |
((Player*)this)->SetClientControl(this, !apply); | |
+ | |
+ if (Unit* owner = GetCharmer()) | |
+ if (owner->GetTypeId() == TYPEID_PLAYER) | |
+ ((Player*)owner)->SetClientControl(this, !apply); | |
} | |
void Unit::SetFeignDeath(bool apply, uint64 const& casterGUID, uint32 /*spellID*/) | |
@@ -9797,17 +9829,12 @@ void Unit::SetDisplayId(uint32 modelId) | |
{ | |
SetUInt32Value(UNIT_FIELD_DISPLAYID, modelId); | |
- UpdateModelData(); | |
+ UpdateModelData(); | |
- if(GetTypeId() == TYPEID_UNIT && ((Creature*)this)->isPet()) | |
- { | |
- Pet *pet = ((Pet*)this); | |
- if(!pet->isControlled()) | |
- return; | |
- Unit *owner = GetOwner(); | |
- if(owner && (owner->GetTypeId() == TYPEID_PLAYER) && ((Player*)owner)->GetGroup()) | |
+ if(Unit *owner = GetCharmerOrOwner()) | |
+ if((owner->GetTypeId() == TYPEID_PLAYER) && ((Player*)owner)->GetGroup()) | |
((Player*)owner)->SetGroupUpdateFlag(GROUP_UPDATE_FLAG_PET_MODEL_ID); | |
- } | |
+ | |
} | |
void Unit::UpdateModelData() | |
@@ -10009,16 +10036,14 @@ void Unit::UpdateAuraForGroup(uint8 slot) | |
player->SetAuraUpdateMask(slot); | |
} | |
} | |
- else if(GetTypeId() == TYPEID_UNIT && ((Creature*)this)->isPet()) | |
+ else if(GetTypeId() == TYPEID_UNIT) | |
{ | |
- Pet *pet = ((Pet*)this); | |
- if(pet->isControlled()) | |
+ if(Unit *owner = GetCharmerOrOwner()) | |
{ | |
- Unit *owner = GetOwner(); | |
- if(owner && (owner->GetTypeId() == TYPEID_PLAYER) && ((Player*)owner)->GetGroup()) | |
+ if((owner->GetTypeId() == TYPEID_PLAYER) && ((Player*)owner)->GetGroup()) | |
{ | |
((Player*)owner)->SetGroupUpdateFlag(GROUP_UPDATE_FLAG_PET_AURAS); | |
- pet->SetAuraUpdateMask(slot); | |
+ SetAuraUpdateMask(slot); | |
} | |
} | |
} | |
@@ -10187,6 +10212,7 @@ void Unit::NearTeleportTo( float x, float y, float z, float orientation, bool ca | |
((Player*)this)->TeleportTo(GetMapId(), x, y, z, orientation, TELE_TO_NOT_LEAVE_TRANSPORT | TELE_TO_NOT_LEAVE_COMBAT | TELE_TO_NOT_UNSUMMON_PET | (casting ? TELE_TO_SPELL : 0)); | |
else | |
{ | |
+ ExitVehicle(); | |
Creature* c = (Creature*)this; | |
// Creature relocation acts like instant movement generator, so current generator expects interrupt/reset calls to react properly | |
if (!c->GetMotionMaster()->empty()) | |
@@ -10258,6 +10284,123 @@ struct SetPvPHelper | |
bool state; | |
}; | |
+void Unit::ChangeSeat(int8 seatId, bool next) | |
+{ | |
+ Vehicle *m_vehicle = ObjectAccessor::GetVehicle(GetVehicleGUID()); | |
+ | |
+ if (!m_vehicle) | |
+ return; | |
+ | |
+ if (seatId < 0) | |
+ { | |
+ seatId = m_vehicle->GetNextEmptySeatNum(m_movementInfo.GetTransportSeat(), next); | |
+ if (seatId < 0) | |
+ return; | |
+ } | |
+ else if (seatId == m_movementInfo.GetTransportSeat() || !m_vehicle->HasEmptySeat(seatId)) | |
+ return; | |
+ | |
+ m_vehicle->RemovePassenger(this); | |
+ EnterVehicle(m_vehicle, seatId); | |
+} | |
+ | |
+void Unit::EnterVehicle(Vehicle *vehicle, int8 seat_id, bool force) | |
+{ | |
+ // dont allow multiple vehicles | |
+ ExitVehicle(); | |
+ | |
+ RemoveSpellsCausingAura(SPELL_AURA_MOUNTED); | |
+ // NOTE : shapeshift too? | |
+ | |
+ Vehicle *v = vehicle->FindFreeSeat(&seat_id, force); | |
+ if(!v) | |
+ return; | |
+ | |
+ VehicleEntry const *ve = sVehicleStore.LookupEntry(v->GetVehicleId()); | |
+ if(!ve) | |
+ return; | |
+ | |
+ VehicleSeatEntry const *veSeat = sVehicleSeatStore.LookupEntry(ve->m_seatID[seat_id]); | |
+ if(!veSeat) | |
+ return; | |
+ | |
+ m_movementInfo.SetTransportData(v->GetGUID(), | |
+ (veSeat->m_attachmentOffsetX + v->GetObjectSize()) * GetFloatValue(OBJECT_FIELD_SCALE_X), | |
+ (veSeat->m_attachmentOffsetY + v->GetObjectSize()) * GetFloatValue(OBJECT_FIELD_SCALE_X), | |
+ (veSeat->m_attachmentOffsetZ + v->GetObjectSize()) * GetFloatValue(OBJECT_FIELD_SCALE_X), | |
+ veSeat->m_passengerYaw, v->GetCreationTime(), seat_id, veSeat->m_ID, | |
+ sObjectMgr.GetSeatFlags(veSeat->m_ID), v->GetVehicleFlags()); | |
+ | |
+ m_movementInfo.AddMovementFlag(MOVEFLAG_ONTRANSPORT); | |
+ | |
+ addUnitState(UNIT_STAT_ON_VEHICLE); | |
+ InterruptNonMeleeSpells(false); | |
+ | |
+ if(Pet *pet = GetPet()) | |
+ pet->Remove(PET_SAVE_AS_CURRENT); | |
+ | |
+ if(GetTypeId() == TYPEID_PLAYER) | |
+ ((Player*)this)->SendEnterVehicle(v); | |
+ | |
+ WorldPacket data(SMSG_MONSTER_MOVE_TRANSPORT, 60); | |
+ data << GetPackGUID(); | |
+ data << v->GetPackGUID(); | |
+ data << uint8(seat_id); | |
+ data << uint8(0); // new in 3.1 | |
+ data << v->GetPositionX() << v->GetPositionY() << v->GetPositionZ(); | |
+ data << uint32(getMSTime()); | |
+ | |
+ data << uint8(4); // unknown | |
+ data << float(0); // facing angle | |
+ | |
+ data << uint32(SPLINEFLAG_UNKNOWN5); | |
+ | |
+ data << uint32(0); // Time in between points | |
+ data << uint32(1); // 1 single waypoint | |
+ data << m_movementInfo.GetTransportPos()->x; | |
+ data << m_movementInfo.GetTransportPos()->y; | |
+ data << m_movementInfo.GetTransportPos()->z; | |
+ SendMessageToSet(&data, true); | |
+ | |
+ v->AddPassenger(this, seat_id, force); | |
+} | |
+ | |
+void Unit::ExitVehicle() | |
+{ | |
+ if(uint64 vehicleGUID = GetVehicleGUID()) | |
+ { | |
+ float v_size = 0.0f; | |
+ if(Vehicle *vehicle = ObjectAccessor::GetVehicle(vehicleGUID)) | |
+ { | |
+ if(m_movementInfo.GetVehicleSeatFlags() & SF_MAIN_RIDER) | |
+ { | |
+ if(vehicle->GetVehicleFlags() & VF_DESPAWN_AT_LEAVE) | |
+ { | |
+ // will be deleted at next update | |
+ vehicle->SetSpawnDuration(1); | |
+ } | |
+ } | |
+ v_size = vehicle->GetObjectSize(); | |
+ vehicle->RemovePassenger(this); | |
+ } | |
+ SetVehicleGUID(0); | |
+ | |
+ clearUnitState(UNIT_STAT_ON_VEHICLE); | |
+ | |
+ if(GetTypeId() == TYPEID_PLAYER) | |
+ { | |
+ ((Player*)this)->ResummonPetTemporaryUnSummonedIfAny(); | |
+ ((Player*)this)->m_movementInfo.RemoveMovementFlag(MOVEFLAG_ROOT); | |
+ } | |
+ | |
+ float x = GetPositionX(); | |
+ float y = GetPositionY(); | |
+ float z = GetPositionZ() + 2.0f; | |
+ GetClosePoint(x, y, z, 2.0f + v_size); | |
+ SendMonsterMove(x, y, z, SPLINETYPE_NORMAL, SPLINEFLAG_WALKMODE, 0); | |
+ } | |
+} | |
+ | |
void Unit::SetPvP( bool state ) | |
{ | |
if(state) | |
@@ -10478,4 +10621,4 @@ SpellAuraHolder* Unit::GetSpellAuraHolder (uint32 spellid, uint64 casterGUID) | |
return iter->second; | |
return NULL; | |
-} | |
+} | |
\ No newline at end of file | |
diff --git a/src/game/Unit.h b/src/game/Unit.h | |
index 35c3767..86aedb6 100644 | |
--- a/src/game/Unit.h | |
+++ b/src/game/Unit.h | |
@@ -303,6 +303,7 @@ class Item; | |
class Pet; | |
class PetAura; | |
class Totem; | |
+class Vehicle; | |
struct SpellImmune | |
{ | |
@@ -440,24 +441,25 @@ enum UnitState | |
UNIT_STAT_FOLLOW_MOVE = 0x00010000, | |
UNIT_STAT_FLEEING = 0x00020000, // FleeMovementGenerator/TimedFleeingMovementGenerator active/onstack | |
UNIT_STAT_FLEEING_MOVE = 0x00040000, | |
+ UNIT_STAT_ON_VEHICLE = 0x00080000, | |
// masks (only for check) | |
// can't move currently | |
- UNIT_STAT_CAN_NOT_MOVE = UNIT_STAT_ROOT | UNIT_STAT_STUNNED | UNIT_STAT_DIED, | |
+ UNIT_STAT_CAN_NOT_MOVE = UNIT_STAT_ROOT | UNIT_STAT_STUNNED | UNIT_STAT_DIED | UNIT_STAT_ON_VEHICLE, | |
// stay by different reasons | |
UNIT_STAT_NOT_MOVE = UNIT_STAT_ROOT | UNIT_STAT_STUNNED | UNIT_STAT_DIED | | |
- UNIT_STAT_DISTRACTED, | |
+ UNIT_STAT_DISTRACTED | UNIT_STAT_ON_VEHICLE, | |
// stay or scripted movement for effect( = in player case you can't move by client command) | |
UNIT_STAT_NO_FREE_MOVE = UNIT_STAT_ROOT | UNIT_STAT_STUNNED | UNIT_STAT_DIED | | |
UNIT_STAT_IN_FLIGHT | | |
- UNIT_STAT_CONFUSED | UNIT_STAT_FLEEING, | |
+ UNIT_STAT_CONFUSED | UNIT_STAT_FLEEING | UNIT_STAT_ON_VEHICLE, | |
// not react at move in sight or other | |
UNIT_STAT_CAN_NOT_REACT = UNIT_STAT_STUNNED | UNIT_STAT_DIED | | |
- UNIT_STAT_CONFUSED | UNIT_STAT_FLEEING, | |
+ UNIT_STAT_CONFUSED | UNIT_STAT_FLEEING | UNIT_STAT_ON_VEHICLE, | |
// AI disabled by some reason | |
UNIT_STAT_LOST_CONTROL = UNIT_STAT_FLEEING | UNIT_STAT_CONTROLLED, | |
@@ -767,7 +769,7 @@ class MovementInfo | |
// Position manipulations | |
Position const *GetPos() const { return &pos; } | |
- void SetTransportData(ObjectGuid guid, float x, float y, float z, float o, uint32 time, int8 seat) | |
+ void SetTransportData(ObjectGuid guid, float x, float y, float z, float o, uint32 time, int8 seat, uint32 dbc_seat = 0, uint32 seat_flags = 0, uint32 vehicle_flags = 0) | |
{ | |
t_guid = guid; | |
t_pos.x = x; | |
@@ -776,6 +778,9 @@ class MovementInfo | |
t_pos.o = o; | |
t_time = time; | |
t_seat = seat; | |
+ t_dbc_seat = dbc_seat; | |
+ t_seat_flags = seat_flags; | |
+ t_vehicle_flags = vehicle_flags; | |
} | |
void ClearTransportData() | |
{ | |
@@ -786,11 +791,17 @@ class MovementInfo | |
t_pos.o = 0.0f; | |
t_time = 0; | |
t_seat = -1; | |
+ t_dbc_seat = 0; | |
+ t_seat_flags = 0; | |
+ t_vehicle_flags = 0; | |
} | |
ObjectGuid const& GetTransportGuid() const { return t_guid; } | |
Position const *GetTransportPos() const { return &t_pos; } | |
int8 GetTransportSeat() const { return t_seat; } | |
uint32 GetTransportTime() const { return t_time; } | |
+ uint32 GetTransportDBCSeat() const { return t_dbc_seat; } | |
+ uint32 GetVehicleSeatFlags() const { return t_seat_flags; } | |
+ uint32 GetVehicleFlags() const { return t_vehicle_flags; } | |
uint32 GetFallTime() const { return fallTime; } | |
void ChangePosition(float x, float y, float z, float o) { pos.x = x; pos.y = y; pos.z = z; pos.o = o; } | |
void UpdateTime(uint32 _time) { time = _time; } | |
@@ -807,6 +818,9 @@ class MovementInfo | |
uint32 t_time; | |
int8 t_seat; | |
uint32 t_time2; | |
+ uint32 t_dbc_seat; | |
+ uint32 t_seat_flags; | |
+ uint32 t_vehicle_flags; | |
// swimming and flying | |
float s_pitch; | |
// last fall time | |
@@ -1230,6 +1244,8 @@ class MANGOS_DLL_SPEC Unit : public WorldObject | |
bool IsHostileTo(Unit const* unit) const; | |
bool IsHostileToPlayers() const; | |
bool IsFriendlyTo(Unit const* unit) const; | |
+ bool IsInRaidWith(Unit const* unit) const; | |
+ bool IsInPartyWith(Unit const* unit) const; | |
bool IsNeutralToAll() const; | |
bool IsContestedGuard() const | |
{ | |
@@ -1365,6 +1381,10 @@ class MANGOS_DLL_SPEC Unit : public WorldObject | |
return m_spellAuraHolders.find(spellId) != m_spellAuraHolders.end(); | |
} | |
+ const uint64& GetAuraUpdateMask() const { return m_auraUpdateMask; } | |
+ void SetAuraUpdateMask(uint8 slot) { m_auraUpdateMask |= (uint64(1) << slot); } | |
+ void ResetAuraUpdateMask() { m_auraUpdateMask = 0; } | |
+ | |
bool virtual HasSpell(uint32 /*spellID*/) const { return false; } | |
bool HasStealthAura() const { return HasAuraType(SPELL_AURA_MOD_STEALTH); } | |
@@ -1465,12 +1485,13 @@ class MANGOS_DLL_SPEC Unit : public WorldObject | |
Unit* GetCharm() const; | |
void Uncharm(); | |
Unit* GetCharmerOrOwner() const { return GetCharmerGUID() ? GetCharmer() : GetOwner(); } | |
- Unit* GetCharmerOrOwnerOrSelf() | |
+ Unit* GetCharmOrPet() const { return GetCharmGUID() ? GetCharm() : (Unit*)GetPet(); } | |
+ Unit* GetCharmerOrOwnerOrSelf() const | |
{ | |
if(Unit* u = GetCharmerOrOwner()) | |
return u; | |
- return this; | |
+ return (Unit*)this; | |
} | |
bool IsCharmerOrOwnerPlayerOrPlayerItself() const; | |
Player* GetCharmerOrOwnerPlayerOrPlayerItself(); | |
@@ -1876,6 +1897,13 @@ class MANGOS_DLL_SPEC Unit : public WorldObject | |
// Movement info | |
MovementInfo m_movementInfo; | |
+ // vehicle system | |
+ void EnterVehicle(Vehicle *vehicle, int8 seat_id, bool force = false); | |
+ void ExitVehicle(); | |
+ uint64 GetVehicleGUID() { return m_vehicleGUID; } | |
+ void SetVehicleGUID(uint64 guid) { m_vehicleGUID = guid; } | |
+ void ChangeSeat(int8 seatId, bool next); | |
+ | |
protected: | |
explicit Unit (); | |
@@ -1924,6 +1952,8 @@ class MANGOS_DLL_SPEC Unit : public WorldObject | |
uint32 m_reactiveTimer[MAX_REACTIVE]; | |
uint32 m_regenTimer; | |
uint32 m_lastManaUseTimer; | |
+ uint64 m_auraUpdateMask; | |
+ uint64 m_vehicleGUID; | |
private: | |
void CleanupDeletedAuras(); | |
diff --git a/src/game/Vehicle.cpp b/src/game/Vehicle.cpp | |
index b92e542..a0df6ab 100644 | |
--- a/src/game/Vehicle.cpp | |
+++ b/src/game/Vehicle.cpp | |
@@ -18,12 +18,14 @@ | |
#include "Common.h" | |
#include "Log.h" | |
-#include "ObjectMgr.h" | |
#include "Vehicle.h" | |
#include "Unit.h" | |
#include "Util.h" | |
+#include "WorldPacket.h" | |
+#include "InstanceData.h" | |
-Vehicle::Vehicle() : Creature(CREATURE_SUBTYPE_VEHICLE), m_vehicleId(0) | |
+Vehicle::Vehicle() : Creature(CREATURE_SUBTYPE_VEHICLE), m_vehicleId(0), m_vehicleInfo(NULL), m_spawnduration(0), | |
+ despawn(false), m_creation_time(0), m_VehicleData(NULL) | |
{ | |
m_updateFlag = (UPDATEFLAG_LIVING | UPDATEFLAG_HAS_POSITION | UPDATEFLAG_VEHICLE); | |
} | |
@@ -51,45 +53,721 @@ void Vehicle::RemoveFromWorld() | |
Unit::RemoveFromWorld(); | |
} | |
+void Vehicle::Respawn() | |
+{ | |
+ Creature::Respawn(); | |
+ InstallAllAccessories(); | |
+} | |
+ | |
void Vehicle::setDeathState(DeathState s) // overwrite virtual Creature::setDeathState and Unit::setDeathState | |
{ | |
Creature::setDeathState(s); | |
+ if(s == JUST_DIED) | |
+ { | |
+ if(GetVehicleFlags() & VF_DESPAWN_NPC) | |
+ Dismiss(); | |
+ else | |
+ RemoveAllPassengers(); | |
+ } | |
} | |
void Vehicle::Update(uint32 diff) | |
{ | |
Creature::Update(diff); | |
+ | |
+ if(despawn) | |
+ { | |
+ m_spawnduration -= diff; | |
+ if(m_spawnduration < 0) | |
+ Dismiss(); | |
+ despawn = false; | |
+ } | |
+ | |
+ if(m_regenTimer <= diff) | |
+ { | |
+ RegeneratePower(getPowerType()); | |
+ m_regenTimer = 4000; | |
+ } | |
+ else | |
+ m_regenTimer -= diff; | |
} | |
-bool Vehicle::Create(uint32 guidlow, Map *map, uint32 Entry, uint32 vehicleId, uint32 team) | |
+void Vehicle::RegeneratePower(Powers power) | |
+{ | |
+ uint32 curValue = GetPower(power); | |
+ uint32 maxValue = GetMaxPower(power); | |
+ | |
+ if (curValue >= maxValue) | |
+ return; | |
+ | |
+ float addvalue = 0.0f; | |
+ | |
+ // hack: needs more research of power type from the dbc. | |
+ // It must contains some info about vehicles like Salvaged Chopper. | |
+ if(m_vehicleInfo->m_powerType == POWER_TYPE_PYRITE) | |
+ return; | |
+ | |
+ addvalue = 20.0f; | |
+ | |
+ ModifyPower(power, (int32)addvalue); | |
+} | |
+ | |
+bool Vehicle::Create(uint32 guidlow, Map *map, uint32 phaseMask, uint32 Entry, uint32 vehicleId, uint32 team, const CreatureData *data) | |
{ | |
SetMap(map); | |
+ SetPhaseMask(phaseMask,false); | |
+ | |
+ CreatureInfo const *cinfo = sObjectMgr.GetCreatureTemplate(Entry); | |
+ if(!cinfo) | |
+ { | |
+ sLog.outErrorDb("Creature entry %u does not exist.", Entry); | |
+ return false; | |
+ } | |
Object::_Create(guidlow, Entry, HIGHGUID_VEHICLE); | |
- if(!InitEntry(Entry, team)) | |
+ if(!UpdateEntry(Entry, team, data)) | |
return false; | |
- m_defaultMovementType = IDLE_MOTION_TYPE; | |
+ if(!vehicleId) | |
+ { | |
+ CreatureDataAddon const *cainfo = GetCreatureAddon(); | |
+ if(!cainfo) | |
+ return false; | |
+ vehicleId = cainfo->vehicle_id; | |
+ } | |
+ if(!SetVehicleId(vehicleId)) | |
+ return false; | |
- AIM_Initialize(); | |
+ LoadCreaturesAddon(); | |
- SetVehicleId(vehicleId); | |
+ m_regenHealth = false; | |
+ m_creation_time = getMSTime(); | |
- SetUInt32Value(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_SPELLCLICK); | |
SetFloatValue(UNIT_FIELD_HOVERHEIGHT, 1.0f); | |
+ //RemoveMonsterMoveFlag(MONSTER_MOVE_WALK); | |
+ | |
+ //Notify the map's instance data. | |
+ //Only works if you create the object in it, not if it is moves to that map. | |
+ //Normally non-players do not teleport to other maps. | |
+ if(map->IsDungeon() && ((InstanceMap*)map)->GetInstanceData()) | |
+ { | |
+ ((InstanceMap*)map)->GetInstanceData()->OnCreatureCreate(this); | |
+ } | |
+ | |
+ if(m_vehicleInfo->m_powerType == POWER_TYPE_STEAM) | |
+ { | |
+ setPowerType(POWER_ENERGY); | |
+ SetMaxPower(POWER_ENERGY, 100); | |
+ SetPower(POWER_ENERGY, 100); | |
+ } | |
+ else if(m_vehicleInfo->m_powerType == POWER_TYPE_PYRITE) | |
+ { | |
+ setPowerType(POWER_ENERGY); | |
+ SetMaxPower(POWER_ENERGY, 50); | |
+ SetPower(POWER_ENERGY, 50); | |
+ } | |
+ else | |
+ { | |
+ for (uint32 i = 0; i < MAX_VEHICLE_SPELLS; ++i) | |
+ { | |
+ if(!GetVehicleData()->v_spells[i]) | |
+ continue; | |
+ SpellEntry const *spellInfo = sSpellStore.LookupEntry(GetVehicleData()->v_spells[i]); | |
+ if(!spellInfo) | |
+ continue; | |
- CreatureInfo const *ci = GetCreatureInfo(); | |
- setFaction(team == ALLIANCE ? ci->faction_A : ci->faction_H); | |
+ if(spellInfo->powerType == POWER_MANA) | |
+ break; | |
- SelectLevel(ci); | |
+ if(spellInfo->powerType == POWER_ENERGY) | |
+ { | |
+ setPowerType(POWER_ENERGY); | |
+ SetMaxPower(POWER_ENERGY, 100); | |
+ SetPower(POWER_ENERGY, 100); | |
+ break; | |
+ } | |
+ } | |
+ } | |
+ SetHealth(GetMaxHealth()); | |
+ InstallAllAccessories(); | |
return true; | |
} | |
+bool Vehicle::SetVehicleId(uint32 vehicleid) | |
+{ | |
+ VehicleEntry const *vehicleInfo = sVehicleStore.LookupEntry(vehicleid); | |
+ if(!vehicleInfo) | |
+ return false; | |
+ | |
+ m_vehicleId = vehicleid; | |
+ m_vehicleInfo = vehicleInfo; | |
+ | |
+ // can be NULL | |
+ VehicleDataStructure const *VDStructure = sObjectMgr.GetVehicleData(vehicleid); | |
+ if(VDStructure) | |
+ m_VehicleData = VDStructure; | |
+ | |
+ InitSeats(); | |
+ EmptySeatsCountChanged(); | |
+ return true; | |
+} | |
+ | |
+void Vehicle::InitSeats() | |
+{ | |
+ m_Seats.clear(); | |
+ | |
+ for(uint32 i = 0; i < MAX_SEAT; ++i) | |
+ { | |
+ uint32 seatId = m_vehicleInfo->m_seatID[i]; | |
+ if(seatId) | |
+ { | |
+ if(VehicleSeatEntry const *veSeat = sVehicleSeatStore.LookupEntry(seatId)) | |
+ { | |
+ VehicleSeat newseat; | |
+ newseat.seatInfo = veSeat; | |
+ newseat.passenger = NULL; | |
+ newseat.flags = SEAT_FREE; | |
+ newseat.vs_flags = sObjectMgr.GetSeatFlags(seatId); | |
+ m_Seats[i] = newseat; | |
+ } | |
+ } | |
+ } | |
+ // NOTE : there can be vehicles without seats (eg. 180) - probably some TEST vehicles | |
+} | |
+void Vehicle::ChangeSeatFlag(uint8 seat, uint8 flag) | |
+{ | |
+ SeatMap::iterator i_seat = m_Seats.find(seat); | |
+ // this should never happen | |
+ if(i_seat == m_Seats.end()) | |
+ return; | |
+ | |
+ if(i_seat->second.flags != flag) | |
+ { | |
+ i_seat->second.flags = flag; | |
+ EmptySeatsCountChanged(); | |
+ } | |
+} | |
+Vehicle* Vehicle::FindFreeSeat(int8 *seatid, bool force) | |
+{ | |
+ SeatMap::const_iterator i_seat = m_Seats.find(*seatid); | |
+ if(i_seat == m_Seats.end()) | |
+ return GetFirstEmptySeat(seatid, force); | |
+ if((i_seat->second.flags & (SEAT_FULL | SEAT_VEHICLE_FULL)) || (!force && (i_seat->second.vs_flags & SF_UNACCESSIBLE))) | |
+ return GetNextEmptySeat(seatid, true, force); | |
+ if(i_seat->second.flags & SEAT_VEHICLE_FREE) | |
+ { | |
+ // this should never be NULL | |
+ if(Vehicle *v = (Vehicle*)i_seat->second.passenger) | |
+ return v->FindFreeSeat(seatid, force); | |
+ return NULL; | |
+ } | |
+ return this; | |
+} | |
+ | |
+Vehicle* Vehicle::GetFirstEmptySeat(int8 *seatId, bool force) | |
+{ | |
+ for(SeatMap::iterator itr = m_Seats.begin(); itr != m_Seats.end(); ++itr) | |
+ { | |
+ if(itr->second.flags & SEAT_FREE) | |
+ { | |
+ if(!force && (itr->second.vs_flags & SF_UNACCESSIBLE)) | |
+ continue; | |
+ | |
+ *seatId = itr->first; | |
+ return this; | |
+ } | |
+ else if(itr->second.flags & SEAT_VEHICLE_FREE) | |
+ { | |
+ *seatId = itr->first; | |
+ if(Vehicle *v = (Vehicle*)itr->second.passenger) | |
+ return v->FindFreeSeat(seatId, force); | |
+ } | |
+ } | |
+ | |
+ return NULL; | |
+} | |
+ | |
+Vehicle* Vehicle::GetNextEmptySeat(int8 *seatId, bool next, bool force) | |
+{ | |
+ SeatMap::const_iterator i_seat = m_Seats.find(*seatId); | |
+ if(i_seat == m_Seats.end()) return GetFirstEmptySeat(seatId, force); | |
+ | |
+ while((i_seat->second.flags & (SEAT_FULL | SEAT_VEHICLE_FULL)) || (!force && (i_seat->second.vs_flags & SF_UNACCESSIBLE))) | |
+ { | |
+ if(next) | |
+ { | |
+ ++i_seat; | |
+ if(i_seat == m_Seats.end()) | |
+ i_seat = m_Seats.begin(); | |
+ } | |
+ else | |
+ { | |
+ if(i_seat == m_Seats.begin()) | |
+ i_seat = m_Seats.end(); | |
+ --i_seat; | |
+ } | |
+ if(i_seat->first == *seatId) | |
+ return NULL; | |
+ } | |
+ *seatId = i_seat->first; | |
+ if(i_seat->second.flags & SEAT_VEHICLE_FREE) | |
+ { | |
+ if(Vehicle *v = (Vehicle*)i_seat->second.passenger) | |
+ return v->FindFreeSeat(seatId, force); | |
+ return NULL; | |
+ } | |
+ | |
+ return this; | |
+} | |
+ | |
+int8 Vehicle::GetEmptySeatsCount(bool force) | |
+{ | |
+ int8 count = 0; | |
+ for(SeatMap::iterator itr = m_Seats.begin(); itr != m_Seats.end(); ++itr) | |
+ { | |
+ if(itr->second.flags & (SEAT_FREE | SEAT_VEHICLE_FREE)) | |
+ { | |
+ if(!force && (itr->second.vs_flags & SF_UNACCESSIBLE)) | |
+ continue; | |
+ | |
+ count++; | |
+ } | |
+ } | |
+ | |
+ return count; | |
+} | |
+int8 Vehicle::GetNextEmptySeatNum(int8 seatId, bool next) const | |
+{ | |
+ SeatMap::const_iterator seat = m_Seats.find(seatId); | |
+ if(seat == m_Seats.end()) return -1; | |
+ while(seat->second.passenger || !seat->second.seatInfo->IsUsable()) | |
+ { | |
+ if(next) | |
+ { | |
+ ++seat; | |
+ if(seat == m_Seats.end()) | |
+ seat = m_Seats.begin(); | |
+ } | |
+ else | |
+ { | |
+ if(seat == m_Seats.begin()) | |
+ seat = m_Seats.end(); | |
+ --seat; | |
+ } | |
+ if(seat->first == seatId) | |
+ return -1; // no available seat | |
+ } | |
+ return seat->first; | |
+} | |
+ | |
+bool Vehicle::HasEmptySeat(int8 seatId) const | |
+{ | |
+ SeatMap::const_iterator seat = m_Seats.find(seatId); | |
+ if(seat == m_Seats.end()) return false; | |
+ return !seat->second.passenger; | |
+} | |
+ | |
+void Vehicle::EmptySeatsCountChanged() | |
+{ | |
+ uint8 m_count = GetTotalSeatsCount(); | |
+ uint8 p_count = GetEmptySeatsCount(false); | |
+ uint8 u_count = GetEmptySeatsCount(true); | |
+ | |
+ // seats accesibles by players | |
+ if(p_count > 0) | |
+ SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_SPELLCLICK); | |
+ else | |
+ RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_SPELLCLICK); | |
+ | |
+ if(u_count == m_count) | |
+ { | |
+ RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PLAYER_CONTROLLED); | |
+ } | |
+ else | |
+ SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PLAYER_CONTROLLED); | |
+ | |
+ if(uint64 vehicleGUID = GetVehicleGUID()) | |
+ { | |
+ if(Vehicle *vehicle = ObjectAccessor::GetVehicle(vehicleGUID)) | |
+ { | |
+ if(u_count > 0) | |
+ vehicle->ChangeSeatFlag(m_movementInfo.GetTransportSeat(), SEAT_VEHICLE_FREE); | |
+ else | |
+ vehicle->ChangeSeatFlag(m_movementInfo.GetTransportSeat(), SEAT_VEHICLE_FULL); | |
+ } | |
+ } | |
+} | |
+ | |
+ | |
+ | |
void Vehicle::Dismiss() | |
{ | |
+ RemoveAllPassengers(); | |
SendObjectDeSpawnAnim(GetGUID()); | |
CombatStop(); | |
AddObjectToRemoveList(); | |
} | |
+ | |
+void Vehicle::RellocatePassengers(Map *map) | |
+{ | |
+ for(SeatMap::iterator itr = m_Seats.begin(); itr != m_Seats.end(); ++itr) | |
+ { | |
+ if(itr->second.flags & SEAT_FULL) | |
+ { | |
+ // passenger cant be NULL here | |
+ Unit *passengers = itr->second.passenger; | |
+ assert(passengers); | |
+ | |
+ float xx = GetPositionX() + passengers->m_movementInfo.GetTransportPos()->x; | |
+ float yy = GetPositionY() + passengers->m_movementInfo.GetTransportPos()->y; | |
+ float zz = GetPositionZ() + passengers->m_movementInfo.GetTransportPos()->z; | |
+ //float oo = passengers->m_SeatData.Orientation; | |
+ // this is not correct, we should recalculate | |
+ // actual rotation depending on vehicle | |
+ float oo = passengers->GetOrientation(); | |
+ | |
+ if(passengers->GetTypeId() == TYPEID_PLAYER) | |
+ ((Player*)passengers)->SetPosition(xx, yy, zz, oo); | |
+ else | |
+ map->CreatureRelocation((Creature*)passengers, xx, yy, zz, oo); | |
+ } | |
+ else if(itr->second.flags & (SEAT_VEHICLE_FULL | SEAT_VEHICLE_FREE)) | |
+ { | |
+ // passenger cant be NULL here | |
+ Unit *passengers = itr->second.passenger; | |
+ assert(passengers); | |
+ | |
+ float xx = GetPositionX() + passengers->m_movementInfo.GetTransportPos()->x; | |
+ float yy = GetPositionY() + passengers->m_movementInfo.GetTransportPos()->y; | |
+ float zz = GetPositionZ() + passengers->m_movementInfo.GetTransportPos()->z; | |
+ //float oo = passengers->m_SeatData.Orientation; | |
+ // this is not correct, we should recalculate | |
+ // actual rotation depending on vehicle | |
+ float oo = passengers->GetOrientation(); | |
+ | |
+ map->CreatureRelocation((Creature*)passengers, xx, yy, zz, oo); | |
+ } | |
+ } | |
+} | |
+ | |
+void Vehicle::AddPassenger(Unit *unit, int8 seatId, bool force) | |
+{ | |
+ SeatMap::iterator seat; | |
+ seat = m_Seats.find(seatId); | |
+ | |
+ // this should never happen | |
+ if(seat == m_Seats.end()) | |
+ return; | |
+ | |
+ unit->SetVehicleGUID(GetGUID()); | |
+ unit->m_movementInfo.AddMovementFlag(MOVEFLAG_ONTRANSPORT); | |
+ unit->m_movementInfo.AddMovementFlag(MOVEFLAG_ROOT); | |
+ | |
+ seat->second.passenger = unit; | |
+ if(unit->GetTypeId() == TYPEID_UNIT && ((Creature*)unit)->isVehicle()) | |
+ { | |
+ if(((Vehicle*)unit)->GetEmptySeatsCount(true) == 0) | |
+ seat->second.flags = SEAT_VEHICLE_FULL; | |
+ else | |
+ seat->second.flags = SEAT_VEHICLE_FREE; | |
+ } | |
+ else | |
+ { | |
+ seat->second.flags = SEAT_FULL; | |
+ } | |
+ | |
+ if(unit->GetTypeId() == TYPEID_PLAYER) | |
+ { | |
+ WorldPacket data0(SMSG_FORCE_MOVE_ROOT, 10); | |
+ data0 << unit->GetPackGUID(); | |
+ data0 << (uint32)((seat->second.vs_flags & SF_CAN_CAST) ? 2 : 0); | |
+ unit->SendMessageToSet(&data0,true); | |
+ } | |
+ | |
+ if(unit->GetTypeId() == TYPEID_PLAYER) | |
+ { | |
+ uint8 allowMove = 1; | |
+ if(GetVehicleFlags() & VF_MOVEMENT) | |
+ allowMove = 0; | |
+ ((Player*)unit)->SetMover(this); | |
+ ((Player*)unit)->SetClientControl(this, 1); | |
+ ((Player*)unit)->GetCamera().SetView(this); | |
+ } | |
+ | |
+ if(seat->second.vs_flags & SF_MAIN_RIDER) | |
+ { | |
+ if(!(GetVehicleFlags() & VF_MOVEMENT)) | |
+ { | |
+ GetMotionMaster()->Clear(false); | |
+ GetMotionMaster()->MoveIdle(); | |
+ SetCharmerGUID(unit->GetGUID()); | |
+ unit->SetUInt64Value(UNIT_FIELD_CHARM, GetGUID()); | |
+ if(canFly() || HasAuraType(SPELL_AURA_FLY) || HasAuraType(SPELL_AURA_MOD_FLIGHT_SPEED)) | |
+ { | |
+ WorldPacket data3(SMSG_MOVE_SET_CAN_FLY, 12); | |
+ data3<< GetPackGUID(); | |
+ data3 << (uint32)(0); | |
+ SendMessageToSet(&data3,false); | |
+ } | |
+ } | |
+ | |
+ SpellClickInfoMapBounds clickPair = sObjectMgr.GetSpellClickInfoMapBounds(GetEntry()); | |
+ for(SpellClickInfoMap::const_iterator itr = clickPair.first; itr != clickPair.second; ++itr) | |
+ { | |
+ if (unit->GetTypeId() == TYPEID_UNIT || itr->second.IsFitToRequirements((Player*)unit)) | |
+ { | |
+ Unit *caster = (itr->second.castFlags & 0x1) ? unit : this; | |
+ Unit *target = (itr->second.castFlags & 0x2) ? unit : this; | |
+ | |
+ caster->CastSpell(target, itr->second.spellId, true); | |
+ } | |
+ } | |
+ if(unit->GetTypeId() == TYPEID_PLAYER) | |
+ { | |
+ // it should be added only on rider enter? | |
+ if(((Player*)unit)->GetGroup()) | |
+ ((Player*)unit)->SetGroupUpdateFlag(GROUP_UPDATE_VEHICLE); | |
+ | |
+ BuildVehicleActionBar((Player*)unit); | |
+ } | |
+ | |
+ if(!(GetVehicleFlags() & VF_FACTION)) | |
+ setFaction(unit->getFaction()); | |
+ | |
+ if(GetVehicleFlags() & VF_CANT_MOVE) | |
+ { | |
+ WorldPacket data2(SMSG_FORCE_MOVE_ROOT, 10); | |
+ data2<< GetPackGUID(); | |
+ data2 << (uint32)(2); | |
+ SendMessageToSet(&data2,false); | |
+ } | |
+ | |
+ if(GetVehicleFlags() & VF_NON_SELECTABLE) | |
+ SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); | |
+ } | |
+ if(seat->second.vs_flags & SF_UNATTACKABLE) | |
+ unit->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); | |
+ | |
+ EmptySeatsCountChanged(); | |
+} | |
+ | |
+void Vehicle::RemovePassenger(Unit *unit) | |
+{ | |
+ SeatMap::iterator seat; | |
+ for(seat = m_Seats.begin(); seat != m_Seats.end(); ++seat) | |
+ { | |
+ if((seat->second.flags & (SEAT_FULL | SEAT_VEHICLE_FREE | SEAT_VEHICLE_FULL)) && seat->second.passenger == unit) | |
+ { | |
+ unit->SetVehicleGUID(0); | |
+ if(unit->GetTypeId() == TYPEID_PLAYER) | |
+ { | |
+ ((Player*)unit)->SetMover(unit); | |
+ ((Player*)unit)->SetClientControl(unit, 1); | |
+ ((Player*)unit)->GetCamera().SetView(unit); | |
+ } | |
+ | |
+ if(seat->second.vs_flags & SF_MAIN_RIDER) | |
+ { | |
+ RemoveSpellsCausingAura(SPELL_AURA_CONTROL_VEHICLE); | |
+ if(unit->GetTypeId() == TYPEID_PLAYER) | |
+ { | |
+ ((Player*)unit)->RemovePetActionBar(); | |
+ | |
+ if(((Player*)unit)->GetGroup()) | |
+ ((Player*)unit)->SetGroupUpdateFlag(GROUP_UPDATE_VEHICLE); | |
+ } | |
+ unit->SetCharm(NULL); | |
+ SetCharmerGUID(NULL); | |
+ setFaction(GetCreatureInfo()->faction_A); | |
+ } | |
+ if(GetVehicleFlags() & VF_NON_SELECTABLE) | |
+ RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); | |
+ if(seat->second.vs_flags & SF_UNATTACKABLE) | |
+ unit->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); | |
+ // restore player control | |
+ if(unit->GetTypeId() == TYPEID_PLAYER) | |
+ { | |
+ if(seat->second.vs_flags & SF_CAN_CAST) | |
+ { | |
+ WorldPacket data0(SMSG_FORCE_MOVE_UNROOT, 10); | |
+ data0 << unit->GetPackGUID(); | |
+ data0 << (uint32)(2); // can rotate | |
+ unit->SendMessageToSet(&data0,true); | |
+ } | |
+ else | |
+ { | |
+ WorldPacket data1(SMSG_FORCE_MOVE_UNROOT, 10); | |
+ data1 << unit->GetPackGUID(); | |
+ data1 << (uint32)(0); // cannot rotate | |
+ unit->SendMessageToSet(&data1,true); | |
+ } | |
+ } | |
+ unit->m_movementInfo.RemoveMovementFlag(MOVEFLAG_ONTRANSPORT); | |
+ unit->m_movementInfo.RemoveMovementFlag(MOVEFLAG_ROOT); | |
+ unit->m_movementInfo.ClearTransportData(); | |
+ | |
+ seat->second.passenger = NULL; | |
+ seat->second.flags = SEAT_FREE; | |
+ EmptySeatsCountChanged(); | |
+ break; | |
+ } | |
+ } | |
+} | |
+ | |
+void Vehicle::RemoveAllPassengers() | |
+{ | |
+ for(SeatMap::iterator itr = m_Seats.begin(); itr != m_Seats.end(); ++itr) | |
+ { | |
+ if(itr->second.flags & SEAT_FULL) | |
+ { | |
+ if(Unit *passenger = itr->second.passenger) // this cant be NULL, but.. | |
+ passenger->ExitVehicle(); | |
+ } | |
+ else if(itr->second.flags & (SEAT_VEHICLE_FULL | SEAT_VEHICLE_FREE)) | |
+ { | |
+ if(Unit *passenger = itr->second.passenger) // this cant be NULL, but.. | |
+ { | |
+ passenger->ExitVehicle(); | |
+ ((Vehicle*)passenger)->Dismiss(); | |
+ } | |
+ } | |
+ } | |
+ // make sure everything is cleared | |
+ InitSeats(); | |
+} | |
+ | |
+bool Vehicle::HasSpell(uint32 spell) const | |
+{ | |
+ if(!m_VehicleData) | |
+ return false; | |
+ | |
+ for(uint8 j = 0; j < MAX_VEHICLE_SPELLS; j++) | |
+ { | |
+ if(m_VehicleData->v_spells[j] == spell) | |
+ return true; | |
+ } | |
+ | |
+ return false; | |
+} | |
+ | |
+void Vehicle::BuildVehicleActionBar(Player *plr) const | |
+{ | |
+ WorldPacket data(SMSG_PET_SPELLS, 8+2+4+4+4*10+1+1); | |
+ data << uint64(GetGUID()); | |
+ data << uint16(0x00000000); // creature family, not used in vehicles | |
+ data << uint32(0x00000000); // unk | |
+ data << uint32(0x00000101); // react state | |
+ | |
+ for(uint32 i = 0; i <= MAX_VEHICLE_SPELLS; ++i) | |
+ { | |
+ data << uint16(m_VehicleData ? m_VehicleData->v_spells[i] : NULL) << uint8(0) << uint8(i+8); | |
+ } | |
+ | |
+ data << uint8(0); //aditional spells in spellbook, not used in vehicles | |
+ | |
+ uint8 cooldownsCount = m_CreatureSpellCooldowns.size() + m_CreatureCategoryCooldowns.size(); | |
+ data << uint8(cooldownsCount); | |
+ time_t curTime = time(NULL); | |
+ | |
+ for(CreatureSpellCooldowns::const_iterator itr = m_CreatureSpellCooldowns.begin(); itr != m_CreatureSpellCooldowns.end(); ++itr) | |
+ { | |
+ time_t cooldown = (itr->second > curTime) ? (itr->second - curTime) * IN_MILLISECONDS : 0; | |
+ | |
+ data << uint32(itr->first); // spellid | |
+ data << uint16(0); // spell category? | |
+ data << uint32(cooldown); // cooldown | |
+ data << uint32(0); // category cooldown | |
+ } | |
+ | |
+ for(CreatureSpellCooldowns::const_iterator itr = m_CreatureCategoryCooldowns.begin(); itr != m_CreatureCategoryCooldowns.end(); ++itr) | |
+ { | |
+ time_t cooldown = (itr->second > curTime) ? (itr->second - curTime) * IN_MILLISECONDS : 0; | |
+ | |
+ data << uint32(itr->first); // spellid | |
+ data << uint16(0); // spell category? | |
+ data << uint32(0); // cooldown | |
+ data << uint32(cooldown); // category cooldown | |
+ } | |
+ | |
+ plr->GetSession()->SendPacket(&data); | |
+ | |
+ data.Initialize(SMSG_PET_GUIDS, 12); | |
+ data << uint32(1); // count | |
+ data << uint64(GetGUID()); | |
+ plr->GetSession()->SendPacket(&data); | |
+} | |
+void Vehicle::InstallAllAccessories() | |
+{ | |
+ if(!GetMap()) | |
+ return; | |
+ | |
+ CreatureDataAddon const *cainfo = GetCreatureAddon(); | |
+ if(!cainfo || !cainfo->passengers) | |
+ return; | |
+ for (CreatureDataAddonPassengers const* cPassanger = cainfo->passengers; cPassanger->seat_idx != -1; ++cPassanger) | |
+ { | |
+ // Continue if seat already taken | |
+ if(GetPassenger(cPassanger->seat_idx)) | |
+ continue; | |
+ | |
+ uint32 guid = 0; | |
+ bool isVehicle = false; | |
+ // Set guid and check whatever it is | |
+ if(cPassanger->guid != 0) | |
+ guid = cPassanger->guid; | |
+ else | |
+ { | |
+ CreatureDataAddon const* passAddon; | |
+ passAddon = ObjectMgr::GetCreatureTemplateAddon(cPassanger->entry); | |
+ if(passAddon && passAddon->vehicle_id != 0) | |
+ isVehicle = true; | |
+ else | |
+ guid = sObjectMgr.GenerateLowGuid(HIGHGUID_UNIT); | |
+ } | |
+ // Create it | |
+ Creature *pPassenger = new Creature; | |
+ if(!isVehicle) | |
+ { | |
+ uint32 entry = cPassanger->entry; | |
+ if(entry == 0) | |
+ { | |
+ CreatureData const* data = sObjectMgr.GetCreatureData(guid); | |
+ if(!data) | |
+ continue; | |
+ entry = data->id; | |
+ } | |
+ | |
+ if(!pPassenger->Create(guid, GetMap(), GetPhaseMask(), entry, 0)) | |
+ continue; | |
+ pPassenger->LoadFromDB(guid, GetMap()); | |
+ pPassenger->Relocate(GetPositionX(), GetPositionY(), GetPositionZ()); | |
+ GetMap()->Add(pPassenger); | |
+ pPassenger->AIM_Initialize(); | |
+ } | |
+ else | |
+ pPassenger = (Creature*)SummonVehicle(cPassanger->entry, GetPositionX(), GetPositionY(), GetPositionZ(), 0); | |
+ // Enter vehicle... | |
+ pPassenger->EnterVehicle(this, cPassanger->seat_idx, true); | |
+ // ...and send update. Without this, client wont show this new creature/vehicle... | |
+ WorldPacket data; | |
+ pPassenger->BuildHeartBeatMsg(&data); | |
+ pPassenger->SendMessageToSet(&data, false); | |
+ } | |
+} | |
+ | |
+Unit *Vehicle::GetPassenger(int8 seatId) const | |
+{ | |
+ SeatMap::const_iterator seat = m_Seats.find(seatId); | |
+ if(seat == m_Seats.end()) return NULL; | |
+ return seat->second.passenger; | |
+} | |
+void Vehicle::Die() | |
+{ | |
+ for (SeatMap::iterator itr = m_Seats.begin(); itr != m_Seats.end(); ++itr) | |
+ if(Unit *passenger = itr->second.passenger) | |
+ if(((Creature*)passenger)->isVehicle()) | |
+ ((Vehicle*)passenger)->Dismiss(); | |
+ RemoveAllPassengers(); | |
+} | |
\ No newline at end of file | |
diff --git a/src/game/Vehicle.h b/src/game/Vehicle.h | |
index 4233db6..7252bad 100644 | |
--- a/src/game/Vehicle.h | |
+++ b/src/game/Vehicle.h | |
@@ -22,6 +22,34 @@ | |
#include "ObjectGuid.h" | |
#include "Creature.h" | |
#include "Unit.h" | |
+#include "ObjectMgr.h" | |
+ | |
+struct VehicleSeat | |
+{ | |
+ VehicleSeatEntry const *seatInfo; | |
+ Unit* passenger; | |
+ uint8 flags; | |
+ uint32 vs_flags; | |
+}; | |
+ | |
+enum VehicleSeatFlags | |
+{ | |
+ SEAT_FREE = 0x01, // free seat | |
+ SEAT_FULL = 0x02, // seat occupied by player/creature | |
+ // special cases | |
+ SEAT_VEHICLE_FREE = 0x04, // seat occupied by vehicle, but that vehicle is free | |
+ SEAT_VEHICLE_FULL = 0x08 // seat occupied by vehicle and that vehicle is full too | |
+}; | |
+ | |
+enum PowerType | |
+{ | |
+ POWER_TYPE_PYRITE = 41, | |
+ POWER_TYPE_STEAM = 61 | |
+}; | |
+ | |
+#define MAX_SEAT 8 | |
+ | |
+typedef std::map<int8, VehicleSeat> SeatMap; | |
class Vehicle : public Creature | |
{ | |
@@ -32,18 +60,57 @@ class Vehicle : public Creature | |
void AddToWorld(); | |
void RemoveFromWorld(); | |
- bool Create (uint32 guidlow, Map *map, uint32 Entry, uint32 vehicleId, uint32 team); | |
+ void Die(); | |
+ bool Create (uint32 guidlow, Map *map, uint32 phaseMask, uint32 Entry, uint32 vehicleId, uint32 team, const CreatureData *data = NULL); | |
+ void Respawn(); | |
void setDeathState(DeathState s); // overwrite virtual Creature::setDeathState and Unit::setDeathState | |
void Update(uint32 diff); // overwrite virtual Creature::Update and Unit::Update | |
+ void RegeneratePower(Powers power); | |
+ | |
uint32 GetVehicleId() { return m_vehicleId; } | |
- void SetVehicleId(uint32 vehicleid) { m_vehicleId = vehicleid; } | |
+ bool SetVehicleId(uint32 vehicleid); | |
+ | |
+ void InitSeats(); | |
+ | |
+ void ChangeSeatFlag(uint8 seat, uint8 flag); | |
+ Vehicle* FindFreeSeat(int8 *seatid, bool force = true); | |
+ Vehicle* GetNextEmptySeat(int8 *seatId, bool next = true, bool force = true); | |
+ Vehicle* GetFirstEmptySeat(int8 *seatId, bool force = true); | |
+ int8 GetEmptySeatsCount(bool force = true); | |
+ void EmptySeatsCountChanged(); | |
+ int8 GetTotalSeatsCount() { return m_Seats.size(); } | |
+ bool HasEmptySeat(int8 seatId) const; | |
+ int8 GetNextEmptySeatNum(int8 seatId, bool next) const; | |
void Dismiss(); | |
+ void RellocatePassengers(Map *map); | |
+ void AddPassenger(Unit *unit, int8 seatId, bool force = true); | |
+ void RemovePassenger(Unit *unit); | |
+ void RemoveAllPassengers(); | |
+ | |
+ bool HasSpell(uint32 spell) const; | |
+ void SetSpawnDuration(int32 duration) | |
+ { | |
+ duration < 1 ? despawn = false : despawn = true; | |
+ m_spawnduration = duration; | |
+ } | |
+ VehicleDataStructure const* GetVehicleData() { return m_VehicleData; } | |
+ uint32 GetVehicleFlags() { return m_VehicleData ? m_VehicleData->v_flags : NULL; } | |
+ uint32 GetCreationTime() { return m_creation_time; } | |
+ void BuildVehicleActionBar(Player *plr) const; | |
+ void InstallAllAccessories(); | |
+ Unit *GetPassenger(int8 seatId) const; | |
protected: | |
uint32 m_vehicleId; | |
+ VehicleEntry const *m_vehicleInfo; | |
+ VehicleDataStructure const *m_VehicleData; | |
+ uint32 m_creation_time; | |
+ SeatMap m_Seats; | |
+ bool despawn; | |
+ int32 m_spawnduration; | |
private: | |
void SaveToDB(uint32, uint8) // overwrited of Creature::SaveToDB - don't must be called | |
diff --git a/src/game/World.cpp b/src/game/World.cpp | |
index 5c87bcc..67c4a93 100644 | |
--- a/src/game/World.cpp | |
+++ b/src/game/World.cpp | |
@@ -1220,6 +1220,11 @@ void World::SetInitialWorldSettings() | |
sLog.outString( "Loading Scripts text locales..." ); // must be after Load*Scripts calls | |
sObjectMgr.LoadDbScriptStrings(); | |
+ sLog.outString( "Loading VehicleData..." ); | |
+ sObjectMgr.LoadVehicleData(); | |
+ sLog.outString( "Loading VehicleSeatData..." ); | |
+ sObjectMgr.LoadVehicleSeatData(); | |
+ | |
sLog.outString( "Loading CreatureEventAI Texts..."); | |
sEventAIMgr.LoadCreatureEventAI_Texts(false); // false, will checked in LoadCreatureEventAI_Scripts | |
diff --git a/src/game/WorldSession.h b/src/game/WorldSession.h | |
index af857e2..e3bc43b 100644 | |
--- a/src/game/WorldSession.h | |
+++ b/src/game/WorldSession.h | |
@@ -425,6 +425,9 @@ class MANGOS_DLL_SPEC WorldSession | |
void HandleSetActiveMoverOpcode(WorldPacket &recv_data); | |
void HandleMoveNotActiveMover(WorldPacket &recv_data); | |
void HandleDismissControlledVehicle(WorldPacket &recv_data); | |
+ void HandleRequestVehicleExit(WorldPacket &recv_data); | |
+ void HandleRequestVehicleSwitchSeat(WorldPacket &recv_data); | |
+ void HandleChangeSeatsOnControlledVehicle(WorldPacket &recv_data); | |
void HandleMoveTimeSkippedOpcode(WorldPacket &recv_data); | |
void HandleRequestRaidInfoOpcode( WorldPacket & recv_data ); | |
diff --git a/src/game/debugcmds.cpp b/src/game/debugcmds.cpp | |
index 9ea6958..a01de1c 100644 | |
--- a/src/game/debugcmds.cpp | |
+++ b/src/game/debugcmds.cpp | |
@@ -636,7 +636,8 @@ bool ChatHandler::HandleDebugSpawnVehicle(const char* args) | |
Vehicle *v = new Vehicle; | |
Map *map = m_session->GetPlayer()->GetMap(); | |
- if (!v->Create(map->GenerateLocalLowGuid(HIGHGUID_VEHICLE), map, entry, id, m_session->GetPlayer()->GetTeam())) | |
+ | |
+ if (!v->Create(sObjectMgr.GenerateLowGuid(HIGHGUID_VEHICLE), map, m_session->GetPlayer()->GetPhaseMaskForSpawn(), entry, id, m_session->GetPlayer()->GetTeam())) | |
{ | |
delete v; | |
return false; | |
@@ -656,6 +657,7 @@ bool ChatHandler::HandleDebugSpawnVehicle(const char* args) | |
} | |
map->Add((Creature*)v); | |
+ v->AIM_Initialize(); | |
return true; | |
} | |
diff --git a/src/shared/Database/SQLStorage.cpp b/src/shared/Database/SQLStorage.cpp | |
index c7644f2..64c4391 100644 | |
--- a/src/shared/Database/SQLStorage.cpp | |
+++ b/src/shared/Database/SQLStorage.cpp | |
@@ -27,9 +27,9 @@ extern DatabaseMysql WorldDatabase; | |
const char CreatureInfosrcfmt[]="iiiiiiiiiisssiiiiiiiiiiifffiffiifiiiiiiiiiiffiiiiiiiiiiiiiiiiiiisiiffliiiiiiiliiis"; | |
const char CreatureInfodstfmt[]="iiiiiiiiiisssiiiiiiiiiiifffiffiifiiiiiiiiiiffiiiiiiiiiiiiiiiiiiisiiffliiiiiiiliiii"; | |
-const char CreatureDataAddonInfofmt[]="iiiiiis"; | |
+const char CreatureDataAddonInfofmt[]="iiiiiiiss"; | |
const char CreatureModelfmt[]="iffbi"; | |
-const char CreatureInfoAddonInfofmt[]="iiiiiis"; | |
+const char CreatureInfoAddonInfofmt[]="iiiiiiiss"; | |
const char EquipmentInfofmt[]="iiii"; | |
const char GameObjectInfosrcfmt[]="iiissssiifiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiis"; | |
const char GameObjectInfodstfmt[]="iiissssiifiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii"; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment