· 8 years ago · May 23, 2018, 07:32 AM
1diff --git a/sql/v01_vehicle_data.sql b/sql/v01_vehicle_data.sql
2new file mode 100644
3index 0000000..74dc665
4--- /dev/null
5+++ b/sql/v01_vehicle_data.sql
6@@ -0,0 +1,21 @@
7+--
8+-- Table structure for table `vehicle_data`
9+--
10+
11+DROP TABLE IF EXISTS `vehicle_data`;
12+CREATE TABLE `vehicle_data` (
13+ `entry` mediumint(5) unsigned NOT NULL,
14+ `flags` mediumint(8) unsigned NOT NULL default '0',
15+ `Spell1` mediumint(8) unsigned NOT NULL default '0',
16+ `Spell2` mediumint(8) unsigned NOT NULL default '0',
17+ `Spell3` mediumint(8) unsigned NOT NULL default '0',
18+ `Spell4` mediumint(8) unsigned NOT NULL default '0',
19+ `Spell5` mediumint(8) unsigned NOT NULL default '0',
20+ `Spell6` mediumint(8) unsigned NOT NULL default '0',
21+ `Spell7` mediumint(8) unsigned NOT NULL default '0',
22+ `Spell8` mediumint(8) unsigned NOT NULL default '0',
23+ `Spell9` mediumint(8) unsigned NOT NULL default '0',
24+ `Spell10` mediumint(8) unsigned NOT NULL default '0',
25+ `req_aura` mediumint(8) unsigned NOT NULL default '0',
26+ PRIMARY KEY (`entry`)
27+) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=FIXED COMMENT='Vehicle System';
28\ No newline at end of file
29diff --git a/sql/v02_vehicle_seat_data.sql b/sql/v02_vehicle_seat_data.sql
30new file mode 100644
31index 0000000..5c3a390
32--- /dev/null
33+++ b/sql/v02_vehicle_seat_data.sql
34@@ -0,0 +1,10 @@
35+--
36+-- Table structure for table `vehicle_seat_data`
37+--
38+
39+DROP TABLE IF EXISTS `vehicle_seat_data`;
40+CREATE TABLE `vehicle_seat_data` (
41+ `seat` mediumint(5) unsigned NOT NULL,
42+ `flags` mediumint(8) unsigned NOT NULL default '0',
43+ PRIMARY KEY (`seat`)
44+) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=FIXED COMMENT='Vehicle Seat System';
45\ No newline at end of file
46diff --git a/sql/v03_creature_addon_tables.sql b/sql/v03_creature_addon_tables.sql
47new file mode 100644
48index 0000000..7240ed4
49--- /dev/null
50+++ b/sql/v03_creature_addon_tables.sql
51@@ -0,0 +1,7 @@
52+ALTER TABLE creature_addon
53+ ADD COLUMN vehicle_id smallint(5) unsigned NOT NULL default '0' AFTER moveflags,
54+ ADD COLUMN passengers text AFTER vehicle_id;
55+
56+ALTER TABLE creature_template_addon
57+ ADD COLUMN vehicle_id smallint(5) unsigned NOT NULL default '0' AFTER moveflags,
58+ ADD COLUMN passengers text AFTER vehicle_id;
59\ No newline at end of file
60diff --git a/sql/v10_vehicle_test_data.sql b/sql/v10_vehicle_test_data.sql
61new file mode 100644
62index 0000000..e6aeecc
63--- /dev/null
64+++ b/sql/v10_vehicle_test_data.sql
65@@ -0,0 +1,553 @@
66+INSERT INTO `vehicle_data` VALUES
67+('106', '4', '50896', '0', '50652', '0', '0', '0', '0', '0', '0', '0', '0'),
68+('116', '5', '51362', '51421', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
69+('117', '4', '50652', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
70+('156', '24', '53114', '0', '53110', '0', '0', '0', '0', '0', '0', '0', '0'),
71+('200', '30', '52362', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
72+('210', '166', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
73+('1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
74+('6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
75+('7', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
76+('8', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
77+('14', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
78+('16', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
79+('17', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
80+('21', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
81+('22', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
82+('23', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
83+('24', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
84+('25', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
85+('26', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
86+('27', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
87+('28', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
88+('29', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
89+('30', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
90+('31', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
91+('32', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
92+('33', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
93+('34', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
94+('35', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
95+('36', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
96+('37', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
97+('38', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
98+('39', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
99+('40', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
100+('41', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
101+('42', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
102+('43', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
103+('44', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
104+('46', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
105+('47', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
106+('48', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
107+('49', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
108+('50', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
109+('51', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
110+('52', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
111+('53', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
112+('54', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
113+('55', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
114+('56', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
115+('57', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
116+('58', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
117+('59', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
118+('60', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
119+('61', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
120+('62', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
121+('64', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
122+('65', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
123+('69', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
124+('70', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
125+('71', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
126+('72', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
127+('74', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
128+('75', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
129+('76', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
130+('77', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
131+('79', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
132+('80', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
133+('81', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
134+('86', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
135+('87', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
136+('88', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
137+('89', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
138+('90', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
139+('91', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
140+('92', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
141+('93', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
142+('97', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
143+('99', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
144+('100', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
145+('102', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
146+('104', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
147+('105', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
148+('107', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
149+('108', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
150+('109', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
151+('110', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
152+('111', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
153+('112', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
154+('113', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
155+('114', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
156+('115', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
157+('118', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
158+('120', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
159+('121', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
160+('122', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
161+('124', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
162+('125', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
163+('126', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
164+('127', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
165+('128', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
166+('129', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
167+('130', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
168+('131', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
169+('132', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
170+('134', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
171+('137', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
172+('138', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
173+('139', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
174+('142', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
175+('143', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
176+('145', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
177+('146', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
178+('147', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
179+('148', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
180+('149', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
181+('150', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
182+('152', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
183+('153', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
184+('154', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
185+('158', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
186+('160', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
187+('162', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
188+('163', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
189+('164', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
190+('165', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
191+('166', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
192+('167', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
193+('168', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
194+('169', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
195+('171', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
196+('173', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
197+('174', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
198+('175', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
199+('176', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
200+('177', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
201+('178', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
202+('179', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
203+('180', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
204+('181', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
205+('182', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
206+('183', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
207+('186', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
208+('188', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
209+('189', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
210+('190', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
211+('191', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
212+('192', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
213+('193', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
214+('194', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
215+('196', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
216+('197', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
217+('198', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
218+('199', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
219+('201', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
220+('202', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
221+('203', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
222+('204', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
223+('205', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
224+('206', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
225+('207', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
226+('208', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
227+('209', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
228+('211', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
229+('212', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
230+('213', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
231+('214', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
232+('215', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
233+('216', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
234+('217', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
235+('218', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
236+('219', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
237+('220', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
238+('221', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
239+('222', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
240+('223', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
241+('224', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
242+('225', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
243+('226', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
244+('227', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
245+('228', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
246+('229', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
247+('230', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
248+('231', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
249+('232', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
250+('233', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
251+('234', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
252+('236', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
253+('237', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
254+('238', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
255+('240', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
256+('241', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
257+('242', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
258+('243', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
259+('244', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
260+('245', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
261+('246', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
262+('247', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
263+('248', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
264+('249', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
265+('250', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
266+('252', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
267+('253', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
268+('254', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
269+('255', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
270+('256', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
271+('257', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
272+('258', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
273+('259', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
274+('260', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
275+('261', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
276+('262', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
277+('263', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
278+('264', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
279+('265', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
280+('266', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
281+('267', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
282+('268', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
283+('269', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
284+('270', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
285+('271', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
286+('272', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
287+('273', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
288+('274', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
289+('275', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
290+('276', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
291+('277', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
292+('278', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
293+('279', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
294+('280', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
295+('281', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
296+('282', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
297+('283', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
298+('284', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
299+('285', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
300+('286', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
301+('287', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
302+('288', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
303+('289', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
304+('290', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
305+('291', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
306+('292', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
307+('293', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
308+('294', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
309+('295', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
310+('296', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
311+('297', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
312+('298', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
313+('299', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
314+('300', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
315+('301', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
316+('302', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
317+('303', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
318+('304', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
319+('305', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
320+('308', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
321+('309', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
322+('310', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
323+('311', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
324+('312', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
325+('313', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
326+('314', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
327+('315', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
328+('316', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
329+('317', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
330+('318', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
331+('320', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
332+('321', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
333+('322', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
334+('323', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
335+('324', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
336+('325', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
337+('327', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
338+('328', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
339+('329', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
340+('331', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
341+('332', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
342+('335', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
343+('336', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
344+('337', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
345+('338', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
346+('339', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
347+('340', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
348+('341', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
349+('342', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
350+('343', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
351+('344', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
352+('345', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
353+('347', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
354+('348', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
355+('352', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
356+('353', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
357+('354', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
358+('356', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
359+('357', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
360+('358', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
361+('359', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
362+('363', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
363+('368', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
364+('369', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
365+('370', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
366+('371', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
367+('372', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
368+('373', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
369+('374', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
370+('375', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
371+('376', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
372+('380', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
373+('381', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
374+('385', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
375+('387', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
376+('388', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
377+('389', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
378+('390', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
379+('392', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
380+('395', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
381+('396', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
382+('397', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
383+('399', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
384+('135', '12', '52362', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
385+('349', '24', '62544', '62575', '62960', '62552', '64077', '62863', '0', '0', '0', '0', '62853'),
386+('68', '24', '52435', '52576', '52588', '0', '0', '0', '0', '0', '0', '0', '0');
387+
388+UPDATE creature_template SET maxhealth = 133525, minhealth = 133525, maxmana = 51360, minmana = 51360 WHERE entry = 28670;
389+UPDATE creature_template SET maxhealth = 50000, minhealth = 50000 WHERE entry = 28094;
390+UPDATE creature_template SET maxhealth = 75000, minhealth = 75000 WHERE entry IN (28312,32627);
391+UPDATE creature_template SET maxhealth = 50000, minhealth = 50000 WHERE entry IN (28319,32629);
392+
393+UPDATE creature_template SET minlevel = 80, maxlevel = 80 WHERE entry IN (28312,32627,28319,32629,28094,28670);
394+
395+UPDATE creature_template SET speed_run = 2, InhabitType = 1 WHERE entry IN (28312,32627,28319,32629,28094,29929,28782);
396+UPDATE creature_template SET speed_run = 2.4, InhabitType = 4 WHERE entry IN (28670);
397+UPDATE creature_template SET mechanic_immune_mask = 652951551 WHERE entry IN (28670,28312,32627,28319,32629,28094,29929,28782);
398+
399+DELETE FROM npc_spellclick_spells WHERE npc_entry in (28670, 28312, 32629, 28319, 32627, 28094, 29929, 28782);
400+INSERT INTO npc_spellclick_spells VALUES
401+(28670, 52196, 0, 0, 0, 0),
402+(28312, 60968, 0, 0, 0, 1),
403+(32627, 60968, 0, 0, 0, 1),
404+(28319, 60968, 0, 0, 0, 1),
405+(32629, 60968, 0, 0, 0, 1),
406+(28094, 60968, 0, 0, 0, 1),
407+(29929, 58961, 0, 0, 0, 1),
408+(28782, 52280, 12687, 1, 12687, 1);
409+
410+DELETE FROM creature_template_addon WHERE entry in (28670, 28312, 32629, 28319, 32627, 28094, 29929, 28782);
411+INSERT INTO creature_template_addon VALUES
412+(28670, 0, 50331648, 1, 0, 1024, 156, NULL, '53112 0 53112 1'),
413+(28312, 0, 0, 0, 0, 0, 117, '28319 7', NULL),
414+(32627, 0, 0, 0, 0, 0, 117, '32629 7', NULL),
415+(28319, 0, 0, 0, 0, 0, 116, NULL, NULL),
416+(32629, 0, 0, 0, 0, 0, 116, NULL, NULL),
417+(28094, 0, 0, 0, 0, 0, 106, NULL, NULL),
418+(29929, 0, 0, 0, 0, 0, 210, NULL, NULL),
419+(28782, 0, 0, 0, 0, 0, 200, NULL, NULL);
420+
421+DELETE FROM vehicle_data WHERE entry in (106, 116, 117, 156, 200, 210);
422+INSERT INTO vehicle_data VALUES (106, 4, 50896, 0, 50652, 0, 0, 0, 0, 0, 0, 0, 0),
423+(116, 5, 51362, 51421, 0, 0, 0, 0, 0, 0, 0, 0, 0),
424+(117, 4, 50652, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
425+(156, 24, 53114, 0, 53110, 0, 0, 0, 0, 0, 0, 0, 0),
426+(200, 30, 52362, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
427+(210, 166, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
428+
429+DELETE FROM vehicle_seat_data WHERE seat in (1643, 1648, 1649, 1650, 1652, 1554, 1556, 1557, 1986, 1987, 2144, 2181, 2182);
430+INSERT INTO vehicle_seat_data VALUES
431+(1643, 3),
432+(1648, 3),
433+(1649, 2),
434+(1650, 2),
435+(1652, 4),
436+(1554, 3),
437+(1556, 6),
438+(1557, 6),
439+(1986, 3),
440+(1987, 8),
441+(2144, 1),
442+(2181, 1),
443+(2182, 0);
444+
445+/* Some quests
446+Argent tournament*/
447+UPDATE creature_template SET speed_run = '1.5', unit_flags = 8 WHERE entry IN (33844,33845);
448+DELETE FROM creature_addon WHERE guid IN (SELECT guid FROM creature WHERE id IN (33844,33845));
449+DELETE FROM creature WHERE id IN (33844,33845);
450+DELETE FROM vehicle_data WHERE entry in (349);
451+INSERT INTO `vehicle_data` VALUES ('349', '24', '62544', '62575', '62960', '62552', '64077', '62863', '0', '0', '0', '0', '62853');
452+DELETE FROM vehicle_seat_data WHERE seat in (3129);
453+INSERT INTO `vehicle_seat_data` VALUES ('3129', '1');
454+INSERT INTO `npc_spellclick_spells` VALUES ('33842', '63791', '13829', '1', '0', '3');
455+INSERT INTO `npc_spellclick_spells` VALUES ('33842', '63791', '13839', '1', '0', '3');
456+INSERT INTO `npc_spellclick_spells` VALUES ('33842', '63791', '13838', '1', '0', '3');
457+INSERT INTO `npc_spellclick_spells` VALUES ('33843', '63792', '13828', '1', '0', '3');
458+INSERT INTO `npc_spellclick_spells` VALUES ('33843', '63792', '13837', '1', '0', '3');
459+INSERT INTO `npc_spellclick_spells` VALUES ('33843', '63792', '13835', '1', '0', '3');
460+DELETE FROM creature_template_addon WHERE entry IN (33844,33845);
461+INSERT INTO creature_template_addon (`entry`, `mount`, `bytes1`, `bytes2`, `emote`, `moveflags`, `vehicle_id`, `passengers`, `auras`) VALUES (33844, 0, 0, 2049, 0, 0, 349, '', '');
462+INSERT INTO creature_template_addon (`entry`, `mount`, `bytes1`, `bytes2`, `emote`, `moveflags`, `vehicle_id`, `passengers`, `auras`) VALUES (33845, 0, 0, 2049, 0, 0, 349, '', '');
463+
464+/*Quest Into the Realm of Shadows (12687)*/
465+UPDATE creature_template SET faction_A = 2082, faction_H = 2082, unit_flags = 0 WHERE entry = 28782;
466+DELETE FROM creature_addon WHERE guid IN (SELECT guid FROM creature WHERE id = 28782);
467+DELETE FROM vehicle_data WHERE entry in (135);
468+INSERT INTO vehicle_data VALUES (135, 12, 52362, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
469+DELETE FROM vehicle_seat_data WHERE seat in (1871);
470+INSERT INTO vehicle_seat_data VALUES (1871, 1);
471+DELETE FROM npc_spellclick_spells WHERE npc_entry in (28782);
472+INSERT INTO npc_spellclick_spells VALUES (28782, 52349, 12687, 1, 12687, 3);
473+DELETE FROM creature_template_addon WHERE entry IN (28782);
474+INSERT INTO creature_template_addon (`entry`, `mount`, `bytes1`, `bytes2`, `emote`, `moveflags`, `vehicle_id`, `passengers`, `auras`) VALUES (28782, 0, 0, 1, 0, 0, 135, '', '');
475+
476+/*Quest Grand Theft Palomino (12680)*/
477+DELETE FROM creature_addon WHERE guid IN (SELECT guid FROM creature WHERE id IN (28605,28606,28607));
478+REPLACE INTO spell_script_target VALUES (52264,1,28653);
479+DELETE FROM vehicle_data WHERE entry in (123);
480+INSERT INTO vehicle_data VALUES (123, 12, 52264, 52268, 0, 0, 0, 0, 0, 0, 0, 0, 0);
481+DELETE FROM vehicle_seat_data WHERE seat in (1782);
482+INSERT INTO vehicle_seat_data VALUES (1782, 1);
483+DELETE FROM npc_spellclick_spells WHERE npc_entry in (28605,28606,28607);
484+INSERT INTO npc_spellclick_spells VALUES (28605, 52263, 12680, 1, 12680, 3);
485+INSERT INTO npc_spellclick_spells VALUES (28606, 52263, 12680, 1, 12680, 3);
486+INSERT INTO npc_spellclick_spells VALUES (28607, 52263, 12680, 1, 12680, 3);
487+DELETE FROM creature_template_addon WHERE entry IN (28605,28606,28607);
488+INSERT INTO creature_template_addon (`entry`, `mount`, `bytes1`, `bytes2`, `emote`, `moveflags`, `vehicle_id`, `passengers`, `auras`) VALUES (28605, 0, 0, 1, 0, 0, 123, '', '');
489+INSERT INTO creature_template_addon (`entry`, `mount`, `bytes1`, `bytes2`, `emote`, `moveflags`, `vehicle_id`, `passengers`, `auras`) VALUES (28606, 0, 0, 1, 0, 0, 123, '', '');
490+INSERT INTO creature_template_addon (`entry`, `mount`, `bytes1`, `bytes2`, `emote`, `moveflags`, `vehicle_id`, `passengers`, `auras`) VALUES (28607, 0, 0, 1, 0, 0, 123, '', '');
491+
492+/*Quest Going Bearback*/
493+DELETE FROM npc_spellclick_spells WHERE npc_entry in (29598);
494+INSERT INTO npc_spellclick_spells VALUES (29598, 54908, 12851, 1, 12851, 1);
495+DELETE FROM creature_template_addon WHERE entry IN (29598);
496+INSERT INTO creature_template_addon (`entry`, `mount`, `bytes1`, `bytes2`, `emote`, `moveflags`, `vehicle_id`, `passengers`, `auras`) VALUES (29598, 0, 0, 1, 0, 0, 308, '', '');
497+DELETE FROM vehicle_data WHERE entry in (308);
498+INSERT INTO `vehicle_data` VALUES ('308', '24', '54897', '54907', '0', '0', '0', '0', '0', '0', '0', '0', '0');
499+REPLACE INTO vehicle_seat_data VALUES (2699, 3);
500+
501+/*Mamonth*/
502+DELETE FROM creature_template_addon WHERE entry in (32633,32640);
503+INSERT INTO creature_template_addon (`entry`, `mount`, `bytes1`, `bytes2`, `emote`, `moveflags`, `vehicle_id`, `passengers`, `auras`) VALUES (32633, 0, 0, 1, 0, 0, 312, '', '');
504+INSERT INTO creature_template_addon (`entry`, `mount`, `bytes1`, `bytes2`, `emote`, `moveflags`, `vehicle_id`, `passengers`, `auras`) VALUES (32640, 0, 0, 1, 0, 0, 312, '', '');
505+DELETE FROM vehicle_data WHERE entry in (312);
506+
507+/*Massacre At Light's Point*/
508+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;
509+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;
510+
511+DELETE FROM creature_addon WHERE guid IN (SELECT guid FROM creature WHERE id IN (28887,28833));
512+DELETE FROM vehicle_data WHERE entry in (68);
513+INSERT INTO `vehicle_data` VALUES ('68', '24', '52435', '52576', '52588', '0', '0', '0', '0', '0', '0', '0', '0');
514+DELETE FROM vehicle_seat_data WHERE seat in (1301);
515+INSERT INTO `vehicle_seat_data` VALUES ('1301', '3');
516+INSERT INTO `npc_spellclick_spells` VALUES ('28833', '52447', '12701', '1', '12701', '1');
517+INSERT INTO `npc_spellclick_spells` VALUES ('28887', '52447', '12701', '1', '12701', '1');
518+
519+DELETE FROM creature_template_addon WHERE entry IN (28887,28833);
520+INSERT INTO creature_template_addon (`entry`, `mount`, `bytes1`, `bytes2`, `emote`, `moveflags`, `vehicle_id`, `passengers`, `auras`) VALUES (28887, 0, 0, 2049, 0, 0, 68, '', '');
521+INSERT INTO creature_template_addon (`entry`, `mount`, `bytes1`, `bytes2`, `emote`, `moveflags`, `vehicle_id`, `passengers`, `auras`) VALUES (28833, 0, 0, 2049, 0, 0, 68, '', '');
522+
523+
524+
525+/*Traveler's Tundra Mammoth */
526+REPLACE INTO npc_spellclick_spells VALUES (32633, 52196, 0, 0, 0, 0);
527+REPLACE INTO creature_template_addon VALUES (32633, 0, 0, 0, 0, 0, 312, NULL, NULL);
528+REPLACE INTO vehicle_data VALUES (312, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
529+
530+/* Grand Ice Mammoth */
531+REPLACE INTO npc_spellclick_spells VALUES (31857, 52196, 0, 0, 0, 0);
532+REPLACE INTO creature_template_addon VALUES (31857, 0, 0, 0, 0, 0, 312, NULL, NULL);
533+
534+/* Salvaged Chopper */
535+REPLACE INTO npc_spellclick_spells VALUES (33062, 52196, 0, 0, 0, 0);
536+REPLACE INTO creature_template_addon VALUES (33062, 0, 0, 0, 0, 0, 335, NULL, NULL);
537+REPLACE INTO vehicle_data VALUES (335, 12, 62974, 62286, 62299, 64660, 0, 0, 0, 0, 0, 0, 0);
538+REPLACE INTO vehicle_seat_data VALUES (3005, 1);
539+
540+/* Salvaged Demolisher */
541+REPLACE INTO npc_spellclick_spells VALUES (33109, 52196, 0, 0, 0, 0);
542+REPLACE INTO creature_template_addon VALUES (33109, 0, 0, 0, 0, 0, 338, NULL, NULL);
543+REPLACE INTO vehicle_data VALUES (338, 12, 62306, 62490, 62308, 62324, 0, 0, 0, 0, 0, 0, 0);
544+REPLACE INTO vehicle_seat_data VALUES (3011, 1),(3005, 1),(3004, 2);
545+
546+/* Salvaged Siege Engine */
547+REPLACE INTO npc_spellclick_spells VALUES (33060, 52196, 0, 0, 0, 0);
548+REPLACE INTO creature_template_addon VALUES (33060, 0, 0, 0, 0, 0, 336, NULL, NULL);
549+REPLACE INTO vehicle_data VALUES (336, 12, 62345, 62522, 62346, 0, 0, 0, 0, 0, 0, 0, 0);
550+REPLACE INTO vehicle_seat_data VALUES (3006, 1);
551+
552+/* Wintergrasp Tower Cannon */
553+DELETE FROM npc_spellclick_spells WHERE npc_entry IN (28366);
554+INSERT INTO npc_spellclick_spells VALUES (28366, 60968, 0, 0, 0, 1);
555+REPLACE INTO creature_template_addon VALUES (28366, 0, 0, 0, 0, 0, 160, NULL, NULL);
556+REPLACE INTO vehicle_data VALUES (160, 5, 51362, 51421, 0, 0, 0, 0, 0, 0, 0, 0, 0);
557+REPLACE INTO vehicle_seat_data VALUES (2029, 1);
558+
559+/* Salvaged Siege Turret */
560+DELETE FROM npc_spellclick_spells WHERE npc_entry = 33067;
561+INSERT INTO npc_spellclick_spells VALUES (33067, 67373, 0, 0, 0, 1);
562+REPLACE INTO creature_template_addon VALUES (33067, 0, 0, 0, 0, 0, 337, NULL, NULL);
563+REPLACE INTO vehicle_data VALUES (337, 5, 62358, 64677, 62359, 0, 0, 0, 0, 0, 0, 0, 0);
564+REPLACE INTO vehicle_data VALUES (336, 4, 62345, 62522, 62346, 0, 0, 0, 0, 0, 0, 0, 0);
565+REPLACE INTO vehicle_seat_data VALUES (3006, 1),(3010, 1),(4026, 8),(4027, 8),(3009, 8);
566+UPDATE `creature_template` SET `minhealth` = 1134000, `maxhealth` = 1134000 WHERE `entry` = 33067;
567+UPDATE `creature_template` SET `unit_flags` = 16384 WHERE `entry` = 33067;
568+DELETE FROM `creature` WHERE `id`= 33067;
569+
570+/* Gunner Salvaged Demolisher */
571+DELETE FROM npc_spellclick_spells WHERE npc_entry IN (33167);
572+INSERT INTO npc_spellclick_spells VALUES (33167, 67373, 0, 0, 0, 1);
573+REPLACE INTO creature_template_addon VALUES (33167, 0, 0, 0, 0, 0, 345, NULL, NULL);
574+REPLACE INTO vehicle_data VALUES (345, 5, 62634, 64979, 62479, 62471, 0, 62428, 0, 0, 0, 0, 0);
575+REPLACE INTO vehicle_data VALUES (338, 4, 62306, 62490, 62308, 62324, 0, 0, 0, 0, 0, 0, 0);
576+REPLACE INTO vehicle_seat_data VALUES (3077, 1),(3106, 8);
577+REPLACE INTO vehicle_seat_data VALUES (3011, 1),(3146, 8),(3013, 8),(3147, 8);
578+UPDATE `creature_template` SET `unit_flags` = 16384 WHERE `entry` = 33167;
579+UPDATE `creature_template` SET `minhealth` = 630000, `maxhealth` = 630000 WHERE `entry` = 33167;
580+DELETE FROM `creature` WHERE `id`=33167;
581+
582+/* Massacre At Light's Point */
583+DELETE FROM creature_addon WHERE guid IN (SELECT guid FROM creature WHERE id IN (28887, 28833, 28864));
584+DELETE FROM vehicle_data WHERE entry IN (25, 79);
585+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);
586+DELETE FROM vehicle_seat_data WHERE seat IN (1427, 341);
587+INSERT INTO vehicle_seat_data VALUES (1427, 1),(341, 1);
588+DELETE FROM npc_spellclick_spells WHERE npc_entry IN (28887, 28833, 28864);
589+INSERT INTO npc_spellclick_spells VALUES (28833, 52447, 12701, 1, 12701, 1),(28887, 52447, 12701, 1, 12701, 1),(28864, 67373, 0, 0, 0, 1);
590+DELETE FROM creature_template_addon WHERE entry IN (28887, 28833, 28864);
591+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');
592+
593+DELETE FROM creature_template_addon WHERE entry = 28670;
594+INSERT INTO creature_template_addon VALUES (28670, 0, 50331648, 1, 0, 1024, 156, NULL, '53112 0 53112 1 53112 2');
595+UPDATE creature_template SET InhabitType = 3 WHERE entry = 28670;
596+
597+/* the Oculus */
598+DELETE FROM spell_script_target where entry IN (49460, 49346, 49464);
599+DELETE FROM npc_spellclick_spells where npc_entry IN (27755, 27692, 27756);
600+DELETE FROM creature_template_addon where entry IN (27755, 27692, 27756);
601+/* Amber Drake */
602+INSERT INTO spell_script_target VALUES (49460, 1, 27755);
603+INSERT INTO npc_spellclick_spells VALUES (27755, 49459, 0, 0, 0, 1);
604+INSERT INTO creature_template_addon VALUES (27755, 0, 0, 0, 0, 0, 29, NULL, '53112 0 53112 1');
605+REPLACE INTO vehicle_data VALUES (29, 12, 49840, 49838, 49592, 0, 0, 0, 0, 0, 0, 0, 0);
606+REPLACE INTO vehicle_seat_data VALUES (422, 3);
607+/* Emerald Drake */
608+INSERT INTO spell_script_target VALUES (49346, 1, 27692);
609+INSERT INTO npc_spellclick_spells VALUES (27692, 49427, 0, 0, 0, 1);
610+INSERT INTO creature_template_addon VALUES (27692, 0, 0, 0, 0, 0, 39, NULL, '53112 0 53112 1');
611+REPLACE INTO vehicle_data VALUES (39, 12, 50328, 50341, 50344, 0, 0, 0, 0, 0, 0, 0, 0);
612+REPLACE INTO vehicle_seat_data VALUES (662, 3);
613+/* Ruby Drake */
614+INSERT INTO spell_script_target VALUES (49464, 1, 27756);
615+INSERT INTO npc_spellclick_spells VALUES (27756, 49463, 0, 0, 0, 1);
616+INSERT INTO creature_template_addon VALUES (27756, 0, 0, 0, 0, 0, 43, NULL, '53112 0 53112 1');
617+REPLACE INTO vehicle_data VALUES (43, 12, 50232, 50248, 50240, 0, 0, 0, 0, 0, 0, 0, 0);
618+REPLACE INTO vehicle_seat_data VALUES (742, 3);
619\ No newline at end of file
620diff --git a/src/game/AggressorAI.cpp b/src/game/AggressorAI.cpp
621index 2cb7606..2fb5d75 100644
622--- a/src/game/AggressorAI.cpp
623+++ b/src/game/AggressorAI.cpp
624@@ -103,7 +103,7 @@ void AggressorAI::EnterEvadeMode()
625 //i_tracker.Reset(TIME_INTERVAL_LOOK);
626 }
627
628- if (!m_creature->isCharmed())
629+ if(!m_creature->isCharmed() && !m_creature->GetVehicleGUID())
630 {
631 m_creature->RemoveAllAuras();
632
633diff --git a/src/game/BattleGroundMgr.cpp b/src/game/BattleGroundMgr.cpp
634index a735417..206da8d 100644
635--- a/src/game/BattleGroundMgr.cpp
636+++ b/src/game/BattleGroundMgr.cpp
637@@ -1345,11 +1345,15 @@ void BattleGroundMgr::BuildPvpLogDataPacket(WorldPacket *data, BattleGround *bg)
638 *data << (uint32)0x00000001; // count of next fields
639 *data << (uint32)((BattleGroundEYScore*)itr->second)->FlagCaptures; // flag captures
640 break;
641+ case BATTLEGROUND_SA:
642+ *data << (uint32)0x00000002; // count of next fields
643+ *data << (uint32)((BattleGroundSAScore*)itr->second)->DemolishersDestroyed; // demolishers destroyed
644+ *data << (uint32)((BattleGroundSAScore*)itr->second)->GatesDestroyed; // gates destroyed
645+ break;
646 case BATTLEGROUND_NA:
647 case BATTLEGROUND_BE:
648 case BATTLEGROUND_AA:
649 case BATTLEGROUND_RL:
650- case BATTLEGROUND_SA: // wotlk
651 case BATTLEGROUND_DS: // wotlk
652 case BATTLEGROUND_RV: // wotlk
653 case BATTLEGROUND_IC: // wotlk
654diff --git a/src/game/BattleGroundSA.h b/src/game/BattleGroundSA.h
655index 31a3ffa..9324999 100644
656--- a/src/game/BattleGroundSA.h
657+++ b/src/game/BattleGroundSA.h
658@@ -24,8 +24,10 @@ class BattleGround;
659 class BattleGroundSAScore : public BattleGroundScore
660 {
661 public:
662- BattleGroundSAScore() {};
663+ BattleGroundSAScore(): DemolishersDestroyed(0), GatesDestroyed(0) {};
664 virtual ~BattleGroundSAScore() {};
665+ uint32 DemolishersDestroyed;
666+ uint32 GatesDestroyed;
667 };
668
669 class BattleGroundSA : public BattleGround
670diff --git a/src/game/Chat.cpp b/src/game/Chat.cpp
671index 8dc9148..ee7f905 100644
672--- a/src/game/Chat.cpp
673+++ b/src/game/Chat.cpp
674@@ -497,6 +497,8 @@ ChatCommand * ChatHandler::getCommandTable()
675 { "spell_scripts", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadSpellScriptsCommand, "", NULL },
676 { "spell_target_position", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadSpellTargetPositionCommand, "", NULL },
677 { "spell_threats", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadSpellThreatsCommand, "", NULL },
678+ { "vehicle_data", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadVehicleDataCommand, "", NULL },
679+ { "vehicle_seat_data", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadVehicleSeatDataCommand, "", NULL },
680
681 { NULL, 0, false, NULL, "", NULL }
682 };
683@@ -1815,7 +1817,7 @@ Creature* ChatHandler::getSelectedCreature()
684 if(!m_session)
685 return NULL;
686
687- return m_session->GetPlayer()->GetMap()->GetCreatureOrPetOrVehicle(m_session->GetPlayer()->GetSelection());
688+ return ObjectAccessor::GetCreatureOrPetOrVehicle(*m_session->GetPlayer(),m_session->GetPlayer()->GetSelection());
689 }
690
691 char* ChatHandler::extractKeyFromLink(char* text, char const* linkType, char** something1)
692diff --git a/src/game/Chat.h b/src/game/Chat.h
693index b82899e..daa5170 100644
694--- a/src/game/Chat.h
695+++ b/src/game/Chat.h
696@@ -405,6 +405,8 @@ class ChatHandler
697 bool HandleReloadSpellTargetPositionCommand(const char* args);
698 bool HandleReloadSpellThreatsCommand(const char* args);
699 bool HandleReloadSpellPetAurasCommand(const char* args);
700+ bool HandleReloadVehicleDataCommand(const char* args);
701+ bool HandleReloadVehicleSeatDataCommand(const char* args);
702
703 bool HandleResetAchievementsCommand(const char * args);
704 bool HandleResetAllCommand(const char * args);
705diff --git a/src/game/Creature.cpp b/src/game/Creature.cpp
706index ee759fd..be296fa 100644
707--- a/src/game/Creature.cpp
708+++ b/src/game/Creature.cpp
709@@ -43,6 +43,7 @@
710 #include "GridNotifiers.h"
711 #include "GridNotifiersImpl.h"
712 #include "CellImpl.h"
713+#include "Vehicle.h"
714
715 // apply implementation of the singletons
716 #include "Policies/SingletonImp.h"
717@@ -1129,7 +1130,7 @@ bool Creature::CreateFromProto(uint32 guidlow, uint32 Entry, uint32 team, const
718 }
719 m_originalEntry = Entry;
720
721- Object::_Create(guidlow, Entry, HIGHGUID_UNIT);
722+ Object::_Create(guidlow, Entry, HIGHGUID_UNIT);
723
724 if (!UpdateEntry(Entry, team, data, false))
725 return false;
726@@ -1351,6 +1352,8 @@ void Creature::setDeathState(DeathState s)
727 }
728
729 Unit::setDeathState(CORPSE);
730+ if(isVehicle())
731+ ((Vehicle*)this)->Die();
732 }
733 if (s == JUST_ALIVED)
734 {
735@@ -1454,6 +1457,32 @@ bool Creature::IsImmunedToSpellEffect(SpellEntry const* spellInfo, SpellEffectIn
736 return true;
737 }
738
739+ // Heal immunity
740+ if (isVehicle() && !(((Vehicle*)this)->GetVehicleFlags() & VF_CAN_BE_HEALED))
741+ {
742+ switch(spellInfo->Effect[index])
743+ {
744+ case SPELL_EFFECT_APPLY_AURA:
745+ switch(spellInfo->EffectApplyAuraName[index])
746+ {
747+ case SPELL_AURA_PERIODIC_HEAL:
748+ case SPELL_AURA_OBS_MOD_HEALTH:
749+ case SPELL_AURA_PERIODIC_HEALTH_FUNNEL:
750+ case SPELL_AURA_MOD_REGEN:
751+ return true;
752+ default: break;
753+ }
754+ break;
755+ case SPELL_EFFECT_HEAL:
756+ case SPELL_EFFECT_HEAL_MAX_HEALTH:
757+ // NOTE : this too?
758+ case SPELL_EFFECT_HEAL_MECHANICAL:
759+ case SPELL_EFFECT_HEAL_PCT:
760+ return true;
761+ default : break;
762+ }
763+ }
764+
765 return Unit::IsImmunedToSpellEffect(spellInfo, index);
766 }
767
768@@ -1977,6 +2006,29 @@ bool Creature::IsInEvadeMode() const
769 return !i_motionMaster.empty() && i_motionMaster.GetCurrentMovementGeneratorType() == HOME_MOTION_TYPE;
770 }
771
772+float Creature::GetBaseSpeed() const
773+{
774+ if( isPet() )
775+ {
776+ switch( ((Pet*)this)->getPetType() )
777+ {
778+ case SUMMON_PET:
779+ case HUNTER_PET:
780+ {
781+ //fixed speed fur hunter (and summon!?) pets
782+ return 1.15;
783+ }
784+ case GUARDIAN_PET:
785+ case MINI_PET:
786+ {
787+ //speed of CreatureInfo for guardian- and minipets
788+ break;
789+ }
790+ }
791+ }
792+ return m_creatureInfo->speed_run;
793+}
794+
795 bool Creature::HasSpell(uint32 spellID) const
796 {
797 uint8 i;
798diff --git a/src/game/Creature.h b/src/game/Creature.h
799index 23d47e5..89e4514 100644
800--- a/src/game/Creature.h
801+++ b/src/game/Creature.h
802@@ -212,6 +212,15 @@ struct CreatureDataAddonAura
803 SpellEffectIndex effect_idx;
804 };
805
806+struct CreatureDataAddonPassengers
807+{
808+ CreatureDataAddonPassengers() : entry(0), guid(0), seat_idx(-1) {}
809+
810+ uint32 entry;
811+ uint32 guid;
812+ int8 seat_idx;
813+};
814+
815 // from `creature_addon` table
816 struct CreatureDataAddon
817 {
818@@ -220,7 +229,9 @@ struct CreatureDataAddon
819 uint32 bytes1;
820 uint32 bytes2;
821 uint32 emote;
822- uint32 splineFlags;
823+ uint32 splineFlags;
824+ uint32 vehicle_id;
825+ CreatureDataAddonPassengers const* passengers; // loaded as char* "entry1 seatid1 entry2 seatid2 ... "
826 CreatureDataAddonAura const* auras; // loaded as char* "spell1 eff1 spell2 eff2 ... "
827 };
828
829@@ -400,6 +411,9 @@ class MANGOS_DLL_SPEC Creature : public Unit
830 void GetRespawnCoord(float &x, float &y, float &z, float* ori = NULL, float* dist =NULL) const;
831 uint32 GetEquipmentId() const { return m_equipmentId; }
832
833+ bool CreateVehicleKit(uint32 id);
834+ Vehicle *GetVehicleKit()const { return m_vehicleKit; }
835+
836 CreatureSubtype GetSubtype() const { return m_subtype; }
837 bool isPet() const { return m_subtype == CREATURE_SUBTYPE_PET; }
838 bool isVehicle() const { return m_subtype == CREATURE_SUBTYPE_VEHICLE; }
839@@ -570,6 +584,7 @@ class MANGOS_DLL_SPEC Creature : public Unit
840
841 MovementGeneratorType GetDefaultMovementType() const { return m_defaultMovementType; }
842 void SetDefaultMovementType(MovementGeneratorType mgt) { m_defaultMovementType = mgt; }
843+ float GetBaseSpeed() const;
844
845 // for use only in LoadHelper, Map::Add Map::CreatureCellRelocation
846 Cell const& GetCurrentCell() const { return m_currentCell; }
847@@ -681,7 +696,7 @@ class MANGOS_DLL_SPEC Creature : public Unit
848 float CombatStartX;
849 float CombatStartY;
850 float CombatStartZ;
851-
852+ Vehicle* m_vehicleKit;
853 float m_summonXpoint;
854 float m_summonYpoint;
855 float m_summonZpoint;
856diff --git a/src/game/CreatureAI.cpp b/src/game/CreatureAI.cpp
857index 33cb568..f14bf62 100644
858--- a/src/game/CreatureAI.cpp
859+++ b/src/game/CreatureAI.cpp
860@@ -26,6 +26,10 @@ CreatureAI::~CreatureAI()
861
862 void CreatureAI::AttackedBy( Unit* attacker )
863 {
864+ // vehicle dont have threat list, so this is unnecessary, because it calls move chase
865+ if(m_creature->isVehicle())
866+ return;
867+
868 if(!m_creature->getVictim())
869 AttackStart(attacker);
870 }
871diff --git a/src/game/CreatureAISelector.cpp b/src/game/CreatureAISelector.cpp
872index 87eb1fe..5b5dfbc 100644
873--- a/src/game/CreatureAISelector.cpp
874+++ b/src/game/CreatureAISelector.cpp
875@@ -47,7 +47,7 @@ namespace FactorySelector
876 // excplicit check for isControlled() and owner type to allow guardian, mini-pets and pets controlled by NPCs to be scripted by EventAI
877 Unit *owner=NULL;
878 if ((creature->isPet() && ((Pet*)creature)->isControlled() &&
879- ((owner=creature->GetOwner()) && owner->GetTypeId()==TYPEID_PLAYER)) || creature->isCharmed())
880+ ((owner=creature->GetOwner()) && owner->GetTypeId()==TYPEID_PLAYER)) || (creature->isCharmed() && !creature->isVehicle()))
881 ai_factory = ai_registry.GetRegistryItem("PetAI");
882 else if (creature->isTotem())
883 ai_factory = ai_registry.GetRegistryItem("TotemAI");
884diff --git a/src/game/CreatureEventAI.cpp b/src/game/CreatureEventAI.cpp
885index 65cfedd..4ab3f69 100644
886--- a/src/game/CreatureEventAI.cpp
887+++ b/src/game/CreatureEventAI.cpp
888@@ -847,6 +847,7 @@ void CreatureEventAI::JustReachedHome()
889
890 void CreatureEventAI::EnterEvadeMode()
891 {
892+ m_creature->ExitVehicle();
893 m_creature->RemoveAllAuras();
894 m_creature->DeleteThreatList();
895 m_creature->CombatStop(true);
896diff --git a/src/game/DBCStructure.h b/src/game/DBCStructure.h
897index 07d40a2..185a726 100644
898--- a/src/game/DBCStructure.h
899+++ b/src/game/DBCStructure.h
900@@ -1725,7 +1725,7 @@ struct VehicleEntry
901 uint32 m_uiLocomotionType; // 34
902 float m_msslTrgtImpactTexRadius; // 35
903 uint32 m_uiSeatIndicatorType; // 36
904- // 37, new in 3.1
905+ uint32 m_powerType; // 37, new in 3.1 // 37, new in 3.1
906 // 38, new in 3.1
907 // 39, new in 3.1
908 };
909@@ -1779,6 +1779,8 @@ struct VehicleSeatEntry
910 int32 m_uiSkin; // 44
911 uint32 m_flagsB; // 45
912 // 46-57 added in 3.1, floats mostly
913+
914+ bool IsUsable() const { return m_flags & 0x2000000; }
915 };
916
917 struct WMOAreaTableEntry
918diff --git a/src/game/DBCfmt.h b/src/game/DBCfmt.h
919index 3538095..ff83d03 100644
920--- a/src/game/DBCfmt.h
921+++ b/src/game/DBCfmt.h
922@@ -104,7 +104,7 @@ const char TaxiNodesEntryfmt[]="nifffssssssssssssssssxii";
923 const char TaxiPathEntryfmt[]="niii";
924 const char TaxiPathNodeEntryfmt[]="diiifffiiii";
925 const char TotemCategoryEntryfmt[]="nxxxxxxxxxxxxxxxxxii";
926-const char VehicleEntryfmt[]="niffffiiiiiiiifffffffffffffffssssfifixxx";
927+const char VehicleEntryfmt[]="niffffiiiiiiiifffffffffffffffssssfifiixx";
928 const char VehicleSeatEntryfmt[]="niiffffffffffiiiiiifffffffiiifffiiiiiiiffiiiiixxxxxxxxxxxx";
929 const char WMOAreaTableEntryfmt[]="niiixxxxxiixxxxxxxxxxxxxxxxx";
930 const char WorldMapAreaEntryfmt[]="xinxffffixx";
931diff --git a/src/game/GameObject.cpp b/src/game/GameObject.cpp
932index 0834d18..94580b0 100644
933--- a/src/game/GameObject.cpp
934+++ b/src/game/GameObject.cpp
935@@ -418,11 +418,7 @@ void GameObject::Update(uint32 /*p_time*/)
936 if(!m_respawnDelayTime)
937 return;
938
939- if(!m_spawnedByDefault)
940- {
941- m_respawnTime = 0;
942- return;
943- }
944+ m_respawnTime = m_spawnedByDefault ? time(NULL) + m_respawnDelayTime : 0;
945
946 // since pool system can fail to roll unspawned object, this one can remain spawned, so must set respawn nevertheless
947 m_respawnTime = time(NULL) + m_respawnDelayTime;
948@@ -1515,6 +1511,18 @@ bool GameObject::IsFriendlyTo(Unit const* unit) const
949 // common faction based case (GvC,GvP)
950 return tester_faction->IsFriendlyTo(*target_faction);
951 }
952+void GameObject::DealSiegeDamage(uint32 damage)
953+{
954+ m_actualHealth -= damage;
955+
956+ // TODO : there are a lot of thinghts to do here
957+ if(m_actualHealth < 0)
958+ {
959+ m_actualHealth = GetGOInfo()->destructibleBuilding.intactNumHits;
960+ SetLootState(GO_JUST_DEACTIVATED);
961+ }
962+}
963+
964
965 float GameObject::GetObjectBoundingRadius() const
966 {
967@@ -1525,4 +1533,4 @@ float GameObject::GetObjectBoundingRadius() const
968 return fabs(dispEntry->unknown12) * GetObjectScale();
969
970 return DEFAULT_WORLD_OBJECT_SIZE;
971-}
972\ No newline at end of file
973+}
974diff --git a/src/game/GameObject.h b/src/game/GameObject.h
975index d7a9ee6..d77b23a 100644
976--- a/src/game/GameObject.h
977+++ b/src/game/GameObject.h
978@@ -706,12 +706,14 @@ class MANGOS_DLL_SPEC GameObject : public WorldObject
979 GridReference<GameObject> &GetGridRef() { return m_gridRef; }
980
981 uint64 GetRotation() const { return m_rotation; }
982+ void DealSiegeDamage(uint32 damage);
983 protected:
984 uint32 m_spellId;
985 time_t m_respawnTime; // (secs) time of next respawn (or despawn if GO have owner()),
986 uint32 m_respawnDelayTime; // (secs) if 0 then current GO state no dependent from timer
987 LootState m_lootState;
988 bool m_spawnedByDefault;
989+ int32 m_actualHealth; // current health state
990 time_t m_cooldownTime; // used as internal reaction delay time store (not state change reaction).
991 // For traps this: spell casting cooldown, for doors/buttons: reset time.
992 std::list<uint32> m_SkillupList;
993diff --git a/src/game/GridNotifiers.cpp b/src/game/GridNotifiers.cpp
994index da6aa90..d0d360d 100644
995--- a/src/game/GridNotifiers.cpp
996+++ b/src/game/GridNotifiers.cpp
997@@ -92,7 +92,12 @@ VisibleNotifier::Notify()
998 {
999 // target aura duration for caster show only if target exist at caster client
1000 if ((*vItr) != &player && (*vItr)->isType(TYPEMASK_UNIT))
1001+ {
1002 player.SendAurasForTarget((Unit*)(*vItr));
1003+ WorldPacket data;
1004+ ((Unit*)(*vItr))->BuildHeartBeatMsg(&data);
1005+ player.GetSession()->SendPacket(&data);
1006+ }
1007
1008 // non finished movements show to player
1009 if ((*vItr)->GetTypeId()==TYPEID_UNIT && ((Creature*)(*vItr))->isAlive())
1010diff --git a/src/game/Group.h b/src/game/Group.h
1011index ea8d737..eef86a7 100644
1012--- a/src/game/Group.h
1013+++ b/src/game/Group.h
1014@@ -115,7 +115,8 @@ enum GroupUpdateFlags
1015 GROUP_UPDATE_FLAG_PET_AURAS = 0x00040000, // uint64 mask, for each bit set uint32 spellid + uint8 unk, pet auras...
1016 GROUP_UPDATE_FLAG_VEHICLE_SEAT = 0x00080000, // uint32 vehicle_seat_id (index from VehicleSeat.dbc)
1017 GROUP_UPDATE_PET = 0x0007FC00, // all pet flags
1018- GROUP_UPDATE_FULL = 0x0007FFFF, // all known flags
1019+ GROUP_UPDATE_VEHICLE = 0x000FFC00, // all vehicle flags
1020+ GROUP_UPDATE_FULL = 0x000FFFFF, // all known flags
1021 };
1022
1023 #define GROUP_UPDATE_FLAGS_COUNT 20
1024diff --git a/src/game/GroupHandler.cpp b/src/game/GroupHandler.cpp
1025index d73b233..46f7897 100644
1026--- a/src/game/GroupHandler.cpp
1027+++ b/src/game/GroupHandler.cpp
1028@@ -28,6 +28,7 @@
1029 #include "Group.h"
1030 #include "SocialMgr.h"
1031 #include "Util.h"
1032+#include "Vehicle.h"
1033
1034 /* differeces from off:
1035 -you can uninvite yourself - is is useful
1036@@ -711,7 +712,7 @@ void WorldSession::BuildPartyMemberStatsChangedPacket(Player *player, WorldPacke
1037 }
1038 }
1039
1040- Pet *pet = player->GetPet();
1041+ Unit *pet = player->GetCharmOrPet();
1042 if (mask & GROUP_UPDATE_FLAG_PET_GUID)
1043 {
1044 if(pet)
1045@@ -794,6 +795,11 @@ void WorldSession::BuildPartyMemberStatsChangedPacket(Player *player, WorldPacke
1046 else
1047 *data << uint64(0);
1048 }
1049+
1050+ if (mask & GROUP_UPDATE_FLAG_VEHICLE_SEAT)
1051+ {
1052+ *data << (uint32) player->m_movementInfo.GetTransportDBCSeat();
1053+ }
1054 }
1055
1056 /*this procedure handles clients CMSG_REQUEST_PARTY_MEMBER_STATS request*/
1057@@ -815,7 +821,7 @@ void WorldSession::HandleRequestPartyMemberStatsOpcode( WorldPacket &recv_data )
1058 return;
1059 }
1060
1061- Pet *pet = player->GetPet();
1062+ Unit *pet = player->GetCharmOrPet();
1063
1064 WorldPacket data(SMSG_PARTY_MEMBER_STATS_FULL, 4+2+2+2+1+2*6+8+1+8);
1065 data << uint8(0); // only for SMSG_PARTY_MEMBER_STATS_FULL, probably arena/bg related
1066@@ -823,7 +829,7 @@ void WorldSession::HandleRequestPartyMemberStatsOpcode( WorldPacket &recv_data )
1067
1068 uint32 mask1 = 0x00040BFF; // common mask, real flags used 0x000040BFF
1069 if(pet)
1070- mask1 = 0x7FFFFFFF; // for hunters and other classes with pets
1071+ mask1 = 0xFFFFFFFF; // for hunters and other classes with pets
1072
1073 Powers powerType = player->getPowerType();
1074 data << uint32(mask1); // group update mask
1075@@ -877,6 +883,7 @@ void WorldSession::HandleRequestPartyMemberStatsOpcode( WorldPacket &recv_data )
1076 }
1077 }
1078 data.put<uint64>(petMaskPos, petauramask); // GROUP_UPDATE_FLAG_PET_AURAS
1079+ data << (uint32) player->m_movementInfo.GetTransportDBCSeat();
1080 }
1081 else
1082 {
1083diff --git a/src/game/Level3.cpp b/src/game/Level3.cpp
1084index d3bcbb8..e4a1142 100644
1085--- a/src/game/Level3.cpp
1086+++ b/src/game/Level3.cpp
1087@@ -74,6 +74,9 @@ bool ChatHandler::HandleReloadAllCommand(const char*)
1088 HandleReloadReservedNameCommand("");
1089 HandleReloadMangosStringCommand("");
1090 HandleReloadGameTeleCommand("");
1091+
1092+ HandleReloadVehicleDataCommand("");
1093+ HandleReloadVehicleSeatDataCommand("");
1094 return true;
1095 }
1096
1097@@ -891,6 +894,22 @@ bool ChatHandler::HandleReloadMailLevelRewardCommand(const char* /*arg*/)
1098 return true;
1099 }
1100
1101+bool ChatHandler::HandleReloadVehicleDataCommand(const char*)
1102+{
1103+ sLog.outString( "Re-Loading `vehicle_data` Table!" );
1104+ sObjectMgr.LoadVehicleData();
1105+ SendGlobalSysMessage("DB table `vehicle_data` reloaded.");
1106+ return true;
1107+}
1108+
1109+bool ChatHandler::HandleReloadVehicleSeatDataCommand(const char*)
1110+{
1111+ sLog.outString( "Re-Loading `vehicle_seat_data` Table!" );
1112+ sObjectMgr.LoadVehicleSeatData();
1113+ SendGlobalSysMessage("DB table `vehicle_seat_data` reloaded.");
1114+ return true;
1115+}
1116+
1117 bool ChatHandler::HandleLoadScriptsCommand(const char* args)
1118 {
1119 if(!LoadScriptingModule(args)) return true;
1120diff --git a/src/game/Map.h b/src/game/Map.h
1121index c798c61..f28acb4 100644
1122--- a/src/game/Map.h
1123+++ b/src/game/Map.h
1124@@ -38,7 +38,6 @@
1125 #include <bitset>
1126 #include <list>
1127
1128-class Creature;
1129 class Unit;
1130 class WorldPacket;
1131 class InstanceData;
1132diff --git a/src/game/MiscHandler.cpp b/src/game/MiscHandler.cpp
1133index b4ddc71..643ee61 100644
1134--- a/src/game/MiscHandler.cpp
1135+++ b/src/game/MiscHandler.cpp
1136@@ -267,6 +267,7 @@ void WorldSession::HandleLogoutRequestOpcode( WorldPacket & /*recv_data*/ )
1137 //Can not logout if...
1138 if( GetPlayer()->isInCombat() || //...is in combat
1139 GetPlayer()->duel || //...is in Duel
1140+ GetPlayer()->GetVehicleGUID() || //...is in vehicle
1141 //...is jumping ...is falling
1142 GetPlayer()->m_movementInfo.HasMovementFlag(MovementFlags(MOVEFLAG_FALLING | MOVEFLAG_FALLINGFAR)))
1143 {
1144diff --git a/src/game/MovementHandler.cpp b/src/game/MovementHandler.cpp
1145index c637664..b3f98d2 100644
1146--- a/src/game/MovementHandler.cpp
1147+++ b/src/game/MovementHandler.cpp
1148@@ -248,7 +248,7 @@ void WorldSession::HandleMovementOpcodes( WorldPacket & recv_data )
1149 }
1150
1151 /* handle special cases */
1152- if (movementInfo.HasMovementFlag(MOVEFLAG_ONTRANSPORT))
1153+ if (movementInfo.HasMovementFlag(MOVEFLAG_ONTRANSPORT) && !mover->GetVehicleGUID())
1154 {
1155 // transports size limited
1156 // (also received at zeppelin/lift leave by some reason with t_* as absolute in continent coordinates, can be safely skipped)
1157@@ -296,6 +296,17 @@ void WorldSession::HandleMovementOpcodes( WorldPacket & recv_data )
1158 // now client not include swimming flag in case jumping under water
1159 plMover->SetInWater( !plMover->IsInWater() || plMover->GetBaseMap()->IsUnderWater(movementInfo.GetPos()->x, movementInfo.GetPos()->y, movementInfo.GetPos()->z) );
1160 }
1161+ if (movementInfo.HasMovementFlag(MOVEFLAG_SWIMMING))
1162+ {
1163+ if(mover->GetTypeId() == TYPEID_UNIT)
1164+ {
1165+ if(((Creature*)mover)->isVehicle() && !((Creature*)mover)->canSwim())
1166+ {
1167+ // NOTE : we should enter evade mode here, but...
1168+ ((Vehicle*)mover)->SetSpawnDuration(1);
1169+ }
1170+ }
1171+ }
1172
1173 /*----------------------*/
1174
1175@@ -354,7 +365,11 @@ void WorldSession::HandleMovementOpcodes( WorldPacket & recv_data )
1176 else // creature charmed
1177 {
1178 if(mover->IsInWorld())
1179+ {
1180 mover->GetMap()->CreatureRelocation((Creature*)mover, movementInfo.GetPos()->x, movementInfo.GetPos()->y, movementInfo.GetPos()->z, movementInfo.GetPos()->o);
1181+ if(((Creature*)mover)->isVehicle())
1182+ ((Vehicle*)mover)->RellocatePassengers(mover->GetMap());
1183+ }
1184 }
1185 }
1186
1187@@ -480,18 +495,124 @@ void WorldSession::HandleDismissControlledVehicle(WorldPacket &recv_data)
1188 recv_data >> guid.ReadAsPacked();
1189 recv_data >> mi;
1190
1191- uint64 vehicleGUID = _player->GetCharmGUID();
1192+ uint64 vehicleGUID = _player->GetVehicleGUID();
1193+
1194+ if(!vehicleGUID) // something wrong here...
1195+ return;
1196+
1197+ _player->m_movementInfo = mi;
1198+
1199+ if(Vehicle *vehicle = ObjectAccessor::GetVehicle(vehicleGUID))
1200+ {
1201+ if(vehicle->GetVehicleFlags() & VF_DESPAWN_AT_LEAVE)
1202+ vehicle->Dismiss();
1203+ else
1204+ _player->ExitVehicle();
1205+ }
1206+}
1207+
1208+void WorldSession::HandleRequestVehicleExit(WorldPacket &recv_data)
1209+{
1210+ sLog.outDebug("WORLD: Recvd CMSG_REQUEST_VEHICLE_EXIT");
1211+ recv_data.hexlike();
1212+
1213+ uint64 vehicleGUID = _player->GetVehicleGUID();
1214+
1215+ if(!vehicleGUID) // something wrong here...
1216+ return;
1217+
1218+ if(Vehicle *vehicle = ObjectAccessor::GetVehicle(vehicleGUID))
1219+ {
1220+ _player->ExitVehicle();
1221+ }
1222+}
1223+
1224+void WorldSession::HandleRequestVehicleSwitchSeat(WorldPacket &recv_data)
1225+{
1226+ sLog.outDebug("WORLD: Recvd CMSG_REQUEST_VEHICLE_SWITCH_SEAT");
1227+ recv_data.hexlike();
1228+
1229+ uint64 vehicleGUID = _player->GetVehicleGUID();
1230+
1231+ if(!vehicleGUID) // something wrong here...
1232+ return;
1233+
1234+ if(Vehicle *vehicle = ObjectAccessor::GetVehicle(vehicleGUID))
1235+ {
1236+ ObjectGuid guid;
1237+ recv_data >> guid.ReadAsPacked();
1238+
1239+ int8 seatId = 0;
1240+ recv_data >> seatId;
1241+
1242+ if(!guid.IsEmpty())
1243+ {
1244+ if(vehicleGUID != guid.GetRawValue())
1245+ {
1246+ if(Vehicle *veh = ObjectAccessor::GetVehicle(guid.GetRawValue()))
1247+ {
1248+ if(!_player->IsWithinDistInMap(veh, 10))
1249+ return;
1250+
1251+ if(Vehicle *v = veh->FindFreeSeat(&seatId, false))
1252+ {
1253+ vehicle->RemovePassenger(_player);
1254+ _player->EnterVehicle(v, seatId, false);
1255+ }
1256+ }
1257+ return;
1258+ }
1259+ }
1260+ if(Vehicle *v = vehicle->FindFreeSeat(&seatId, false))
1261+ {
1262+ vehicle->RemovePassenger(_player);
1263+ _player->EnterVehicle(v, seatId, false);
1264+ }
1265+ }
1266+}
1267+
1268+void WorldSession::HandleChangeSeatsOnControlledVehicle(WorldPacket &recv_data)
1269+{
1270+ sLog.outDebug("WORLD: Recvd CMSG_CHANGE_SEATS_ON_CONTROLLED_VEHICLE");
1271+ recv_data.hexlike();
1272+
1273+ uint64 vehicleGUID = _player->GetVehicleGUID();
1274
1275 if(!vehicleGUID) // something wrong here...
1276 return;
1277
1278+ if(recv_data.GetOpcode() == CMSG_REQUEST_VEHICLE_PREV_SEAT)
1279+ {
1280+ _player->ChangeSeat(-1, false);
1281+ return;
1282+ }
1283+ else if(recv_data.GetOpcode() == CMSG_REQUEST_VEHICLE_NEXT_SEAT)
1284+ {
1285+ _player->ChangeSeat(-1, true);
1286+ return;
1287+ }
1288+
1289+ ObjectGuid guid, guid2;
1290+ recv_data >> guid.ReadAsPacked();
1291+
1292+ MovementInfo mi;
1293+ recv_data >> mi;
1294 _player->m_movementInfo = mi;
1295
1296- // using charm guid, because we don't have vehicle guid...
1297- if(Vehicle *vehicle = _player->GetMap()->GetVehicle(vehicleGUID))
1298+ recv_data >> guid2.ReadAsPacked(); //guid of vehicle or of vehicle in target seat
1299+
1300+ int8 seatId;
1301+ recv_data >> seatId;
1302+
1303+ if(guid.GetRawValue() == guid2.GetRawValue())
1304+ _player->ChangeSeat(seatId, false);
1305+ else if(Vehicle *vehicle = ObjectAccessor::GetVehicle(guid2.GetRawValue()))
1306 {
1307- // Aura::HandleAuraControlVehicle will call Player::ExitVehicle
1308- vehicle->RemoveSpellsCausingAura(SPELL_AURA_CONTROL_VEHICLE);
1309+ if(vehicle->HasEmptySeat(seatId))
1310+ {
1311+ _player->ExitVehicle();
1312+ _player->EnterVehicle(vehicle, seatId);
1313+ }
1314 }
1315 }
1316
1317@@ -554,4 +675,4 @@ void WorldSession::HandleSummonResponseOpcode(WorldPacket& recv_data)
1318 recv_data >> agree;
1319
1320 _player->SummonIfPossible(agree);
1321-}
1322+}
1323\ No newline at end of file
1324diff --git a/src/game/Object.cpp b/src/game/Object.cpp
1325index 8386721..32a60fd 100644
1326--- a/src/game/Object.cpp
1327+++ b/src/game/Object.cpp
1328@@ -289,6 +289,9 @@ void Object::BuildMovementUpdate(ByteBuffer * data, uint16 updateFlags) const
1329 }
1330 }
1331 }
1332+ if(unit->GetVehicleGUID())
1333+ unit->m_movementInfo.AddMovementFlag(MOVEFLAG_ONTRANSPORT);
1334+
1335 }
1336 break;
1337 case TYPEID_PLAYER:
1338@@ -303,6 +306,8 @@ void Object::BuildMovementUpdate(ByteBuffer * data, uint16 updateFlags) const
1339 // remove unknown, unused etc flags for now
1340 player->m_movementInfo.RemoveMovementFlag(MOVEFLAG_SPLINE_ENABLED);
1341
1342+ if(((Unit*)this)->GetVehicleGUID())
1343+ player->m_movementInfo.AddMovementFlag(MOVEFLAG_ONTRANSPORT);
1344 if(player->isInFlight())
1345 {
1346 ASSERT(player->GetMotionMaster()->GetCurrentMovementGeneratorType() == FLIGHT_MOTION_TYPE);
1347@@ -1113,7 +1118,11 @@ void WorldObject::Relocate(float x, float y, float z, float orientation)
1348 m_orientation = orientation;
1349
1350 if(isType(TYPEMASK_UNIT))
1351+ {
1352 ((Unit*)this)->m_movementInfo.ChangePosition(x, y, z, orientation);
1353+ if(((Creature*)this)->isVehicle() && IsInWorld())
1354+ ((Vehicle*)this)->RellocatePassengers(GetMap());
1355+ }
1356 }
1357
1358 void WorldObject::Relocate(float x, float y, float z)
1359@@ -1123,7 +1132,11 @@ void WorldObject::Relocate(float x, float y, float z)
1360 m_positionZ = z;
1361
1362 if(isType(TYPEMASK_UNIT))
1363+ {
1364 ((Unit*)this)->m_movementInfo.ChangePosition(x, y, z, GetOrientation());
1365+ if(((Creature*)this)->isVehicle() && IsInWorld())
1366+ ((Vehicle*)this)->RellocatePassengers(GetMap());
1367+ }
1368 }
1369
1370 uint32 WorldObject::GetZoneId() const
1371@@ -1665,6 +1678,42 @@ Creature* WorldObject::SummonCreature(uint32 id, float x, float y, float z, floa
1372 return pCreature;
1373 }
1374
1375+Vehicle* WorldObject::SummonVehicle(uint32 id, float x, float y, float z, float ang, uint32 vehicleId)
1376+{
1377+ Vehicle *v = new Vehicle;
1378+
1379+ Map *map = GetMap();
1380+ uint32 team = 0;
1381+ if (GetTypeId()==TYPEID_PLAYER)
1382+ team = ((Player*)this)->GetTeam();
1383+
1384+ if(!v->Create(sObjectMgr.GenerateLowGuid(HIGHGUID_VEHICLE), map, GetPhaseMask(), id, vehicleId, team))
1385+ {
1386+ delete v;
1387+ return NULL;
1388+ }
1389+
1390+ if (x == 0.0f && y == 0.0f && z == 0.0f)
1391+ GetClosePoint(x, y, z, v->GetObjectSize());
1392+
1393+ v->Relocate(x, y, z, ang);
1394+
1395+ if(!v->IsPositionValid())
1396+ {
1397+ sLog.outError("ERROR: Vehicle (guidlow %d, entry %d) not created. Suggested coordinates isn't valid (X: %f Y: %f)",
1398+ v->GetGUIDLow(), v->GetEntry(), v->GetPositionX(), v->GetPositionY());
1399+ delete v;
1400+ return NULL;
1401+ }
1402+ map->Add((Creature*)v);
1403+ v->AIM_Initialize();
1404+
1405+ if(GetTypeId()==TYPEID_UNIT && ((Creature*)this)->AI())
1406+ ((Creature*)this)->AI()->JustSummoned((Creature*)v);
1407+
1408+ return v;
1409+}
1410+
1411 namespace MaNGOS
1412 {
1413 class NearUsedPosDo
1414diff --git a/src/game/Object.h b/src/game/Object.h
1415index c900e4d..ac1aa7d 100644
1416--- a/src/game/Object.h
1417+++ b/src/game/Object.h
1418@@ -71,6 +71,7 @@ class Unit;
1419 class Map;
1420 class UpdateMask;
1421 class InstanceData;
1422+class Vehicle;
1423
1424 typedef UNORDERED_MAP<Player*, UpdateData> UpdateDataMapType;
1425
1426@@ -490,6 +491,9 @@ class MANGOS_DLL_SPEC WorldObject : public Object
1427 bool isActiveObject() const { return m_isActiveObject || m_viewPoint.hasViewers(); }
1428
1429 ViewPoint& GetViewPoint() { return m_viewPoint; }
1430+
1431+ Vehicle* SummonVehicle(uint32 id, float x, float y, float z, float ang, uint32 vehicleId = NULL);
1432+
1433 protected:
1434 explicit WorldObject();
1435
1436diff --git a/src/game/ObjectAccessor.cpp b/src/game/ObjectAccessor.cpp
1437index 2d39db4..0ecd27b 100644
1438--- a/src/game/ObjectAccessor.cpp
1439+++ b/src/game/ObjectAccessor.cpp
1440@@ -54,6 +54,21 @@ ObjectAccessor::~ObjectAccessor()
1441 }
1442 }
1443
1444+Creature*
1445+ObjectAccessor::GetCreatureOrPetOrVehicle(WorldObject const &u, ObjectGuid guid)
1446+{
1447+ if(guid.IsPlayer() || !u.IsInWorld())
1448+ return NULL;
1449+
1450+ if(guid.IsPet())
1451+ return u.GetMap()->GetPet(guid);
1452+
1453+ if(guid.IsVehicle())
1454+ return u.GetMap()->GetVehicle(guid);
1455+
1456+ return u.GetMap()->GetCreature(guid);
1457+}
1458+
1459 Unit*
1460 ObjectAccessor::GetUnit(WorldObject const &u, ObjectGuid guid)
1461 {
1462@@ -63,10 +78,7 @@ ObjectAccessor::GetUnit(WorldObject const &u, ObjectGuid guid)
1463 if(guid.IsPlayer())
1464 return FindPlayer(guid);
1465
1466- if (!u.IsInWorld())
1467- return NULL;
1468-
1469- return u.GetMap()->GetCreatureOrPetOrVehicle(guid);
1470+ return GetCreatureOrPetOrVehicle(u, guid);
1471 }
1472
1473 Corpse* ObjectAccessor::GetCorpseInMap(ObjectGuid guid, uint32 mapid)
1474diff --git a/src/game/ObjectAccessor.h b/src/game/ObjectAccessor.h
1475index 3caed16..8061ed2 100644
1476--- a/src/game/ObjectAccessor.h
1477+++ b/src/game/ObjectAccessor.h
1478@@ -39,6 +39,7 @@
1479 class Creature;
1480 class Unit;
1481 class GameObject;
1482+class Vehicle;
1483 class WorldObject;
1484 class Map;
1485
1486@@ -99,12 +100,20 @@ class MANGOS_DLL_DECL ObjectAccessor : public MaNGOS::Singleton<ObjectAccessor,
1487 // global (obj used for map only location local guid objects (pets currently)
1488 static Unit* GetUnitInWorld(WorldObject const& obj, ObjectGuid guid);
1489
1490- // FIXME: map local object with global search
1491+ // map local object with global search
1492 static Creature* GetCreatureInWorld(ObjectGuid guid) { return FindHelper<Creature>(guid); }
1493 static GameObject* GetGameObjectInWorld(ObjectGuid guid) { return FindHelper<GameObject>(guid); }
1494+ static Pet* GetGameObjectInWorld(uint64 guid, Pet* /*fake*/) { return FindHelper<Pet>(guid); }
1495+ static Vehicle* GetGameObjectInWorld(uint64 guid, Vehicle* /*fake*/) { return FindHelper<Vehicle>(guid); }
1496
1497 // possible local search for specific object map
1498 static Unit* GetUnit(WorldObject const &, ObjectGuid guid);
1499+ static Creature* GetCreatureOrPetOrVehicle(WorldObject const &, ObjectGuid guid);
1500+ //static Player* GetPlayer(Unit const &, uint64 guid) { return FindPlayer(guid); }
1501+ //static Corpse* GetCorpse(WorldObject const &u, uint64 guid);
1502+ //static Pet* GetPet(uint64 guid) { return GetObjectInWorld(guid, (Pet*)NULL); }
1503+ static Vehicle* GetVehicle(uint64 guid) { return GetGameObjectInWorld(guid, (Vehicle*)NULL); }
1504+ //static Player* FindPlayer(uint64);
1505
1506 // Player access
1507 static Player* FindPlayer(ObjectGuid guid);
1508@@ -176,6 +185,9 @@ inline Unit* ObjectAccessor::GetUnitInWorld(WorldObject const& obj, ObjectGuid g
1509 if (guid.IsPet())
1510 return obj.IsInWorld() ? obj.GetMap()->GetPet(guid) : NULL;
1511
1512+ if (guid.IsVehicle())
1513+ return obj.IsInWorld() ? ((Unit*)obj.GetMap()->GetVehicle(guid)) : NULL;
1514+
1515 return GetCreatureInWorld(guid);
1516 }
1517
1518diff --git a/src/game/ObjectMgr.cpp b/src/game/ObjectMgr.cpp
1519index 2aa9bb1..b6b3899 100644
1520--- a/src/game/ObjectMgr.cpp
1521+++ b/src/game/ObjectMgr.cpp
1522@@ -834,6 +834,93 @@ void ObjectMgr::ConvertCreatureAddonAuras(CreatureDataAddon* addon, char const*
1523 endAura.effect_idx = EFFECT_INDEX_0;
1524 }
1525
1526+void ObjectMgr::ConvertCreatureAddonPassengers(CreatureDataAddon* addon, char const* table, char const* guidEntryStr)
1527+{
1528+ // Now add the passengers, format "creature_entry/guid seatindex creature_entry/guid seatindex..."
1529+ char *p,*s;
1530+ std::vector<int> val;
1531+ s=p=(char*)reinterpret_cast<char const*>(addon->passengers);
1532+ if(p)
1533+ {
1534+ while (p[0]!=0)
1535+ {
1536+ ++p;
1537+ if (p[0]==' ')
1538+ {
1539+ val.push_back(atoi(s));
1540+ s=++p;
1541+ }
1542+ }
1543+ if (p!=s)
1544+ val.push_back(atoi(s));
1545+
1546+ // free char* loaded memory
1547+ delete[] (char*)reinterpret_cast<char const*>(addon->passengers);
1548+
1549+ // wrong list
1550+ if (val.size()%2)
1551+ {
1552+ addon->auras = NULL;
1553+ sLog.outErrorDb("Creature (%s: %u) has wrong `passengers` data in `%s`.",guidEntryStr,addon->guidOrEntry,table);
1554+ return;
1555+ }
1556+ }
1557+
1558+ // empty list
1559+ if(val.empty())
1560+ {
1561+ addon->passengers = NULL;
1562+ return;
1563+ }
1564+
1565+ // replace by new structures array
1566+ const_cast<CreatureDataAddonPassengers*&>(addon->passengers) = new CreatureDataAddonPassengers[val.size()/2+1];
1567+
1568+ int i=0;
1569+ for(int j=0;j<val.size()/2;++j)
1570+ {
1571+ CreatureDataAddonPassengers& cPas = const_cast<CreatureDataAddonPassengers&>(addon->passengers[i]);
1572+ if(guidEntryStr == "Entry")
1573+ cPas.entry = (uint32)val[2*j+0];
1574+ else
1575+ cPas.guid = (uint32)val[2*j+0];
1576+ cPas.seat_idx = (int8)val[2*j+1];
1577+ if ( cPas.seat_idx > 7 )
1578+ {
1579+ 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);
1580+ continue;
1581+ }
1582+ if(cPas.entry == 0 && cPas.guid == 0)
1583+ {
1584+ sLog.outErrorDb("Creature (%s: %u) has NULL creature entry/guid in `passengers` field in `%s`.",guidEntryStr,addon->guidOrEntry,table);
1585+ continue;
1586+ }
1587+ if(cPas.entry > 0)
1588+ {
1589+ if(!sCreatureStorage.LookupEntry<CreatureInfo>(cPas.entry))
1590+ {
1591+ sLog.outErrorDb("Creature (%s: %u) has wrong creature entry/guid %u `passengers` field in `%s`.",guidEntryStr,addon->guidOrEntry,cPas.entry,table);
1592+ continue;
1593+ }
1594+ }
1595+ else
1596+ {
1597+ if(mCreatureDataMap.find(cPas.guid)==mCreatureDataMap.end())
1598+ {
1599+ sLog.outErrorDb("Creature (%s: %u) has wrong creature entry/guid %u `passengers` field in `%s`.",guidEntryStr,addon->guidOrEntry,cPas.guid,table);
1600+ continue;
1601+ }
1602+ }
1603+ ++i;
1604+ }
1605+
1606+ // fill terminator element (after last added)
1607+ CreatureDataAddonPassengers& endPassenger = const_cast<CreatureDataAddonPassengers&>(addon->passengers[i]);
1608+ endPassenger.entry = 0;
1609+ endPassenger.guid = 0;
1610+ endPassenger.seat_idx = -1;
1611+}
1612+
1613 void ObjectMgr::LoadCreatureAddons(SQLStorage& creatureaddons, char const* entryName, char const* comment)
1614 {
1615 creatureaddons.Load();
1616@@ -870,6 +957,7 @@ void ObjectMgr::LoadCreatureAddons(SQLStorage& creatureaddons, char const* entry
1617 }
1618
1619 ConvertCreatureAddonAuras(const_cast<CreatureDataAddon*>(addon), creatureaddons.GetTableName(), entryName);
1620+ ConvertCreatureAddonPassengers(const_cast<CreatureDataAddon*>(addon), creatureaddons.GetTableName(), entryName);
1621 }
1622 }
1623
1624@@ -5905,6 +5993,8 @@ uint32 ObjectMgr::GenerateLowGuid(HighGuid guidhigh)
1625 return m_ItemGuids.Generate();
1626 case HIGHGUID_UNIT:
1627 return m_CreatureGuids.Generate();
1628+ case HIGHGUID_VEHICLE:
1629+ return m_VehicleGuids.Generate();
1630 case HIGHGUID_PLAYER:
1631 return m_CharGuids.Generate();
1632 case HIGHGUID_GAMEOBJECT:
1633@@ -8704,6 +8794,126 @@ CreatureInfo const* GetCreatureTemplateStore(uint32 entry)
1634 return sCreatureStorage.LookupEntry<CreatureInfo>(entry);
1635 }
1636
1637+void ObjectMgr::LoadVehicleData()
1638+{
1639+ mVehicleData.clear();
1640+
1641+ QueryResult *result = WorldDatabase.Query("SELECT entry, flags, Spell1, Spell2, Spell3, Spell4, Spell5, Spell6, Spell7, Spell8, Spell9, Spell10, req_aura FROM vehicle_data");
1642+ if(!result)
1643+ {
1644+ barGoLink bar( 1 );
1645+ bar.step();
1646+
1647+ sLog.outString();
1648+ sLog.outString( ">> Loaded 0 vehicle data" );
1649+ sLog.outErrorDb("`vehicle_data` table is empty!");
1650+ return;
1651+ }
1652+
1653+ uint32 count = 0;
1654+
1655+ barGoLink bar( result->GetRowCount() );
1656+ do
1657+ {
1658+ bar.step();
1659+
1660+ Field* fields = result->Fetch();
1661+
1662+ VehicleDataStructure VDS;
1663+ // NOTE : we can use spellid or creature id
1664+ uint32 v_entry = fields[0].GetUInt32();
1665+ VDS.v_flags = fields[1].GetUInt32();
1666+ for(uint8 j = 0; j < MAX_VEHICLE_SPELLS; j++)
1667+ {
1668+ VDS.v_spells[j] = fields[j+2].GetUInt32();
1669+ }
1670+ VDS.req_aura = fields[12].GetUInt32();
1671+
1672+ VehicleEntry const *vehicleInfo = sVehicleStore.LookupEntry(v_entry);
1673+ if(!vehicleInfo)
1674+ {
1675+ sLog.outErrorDb("Vehicle id %u listed in `vehicle_data` does not exist",v_entry);
1676+ continue;
1677+ }
1678+ for(uint8 j = 0; j < MAX_VEHICLE_SPELLS; j++)
1679+ {
1680+ if(VDS.v_spells[j])
1681+ {
1682+ SpellEntry const* j_spell = sSpellStore.LookupEntry(VDS.v_spells[j]);
1683+ if(!j_spell)
1684+ {
1685+ sLog.outErrorDb("Spell %u listed in `vehicle_data` does not exist, skipped",VDS.v_spells[j]);
1686+ VDS.v_spells[j] = 0;
1687+ }
1688+ }
1689+ }
1690+ if(VDS.req_aura)
1691+ {
1692+ SpellEntry const* i_spell = sSpellStore.LookupEntry(VDS.req_aura);
1693+ if(!i_spell)
1694+ {
1695+ sLog.outErrorDb("Spell %u listed in `vehicle_data` does not exist, skipped",VDS.req_aura);
1696+ VDS.req_aura = 0;
1697+ }
1698+ }
1699+
1700+ mVehicleData[v_entry] = VDS;
1701+ ++count;
1702+ }
1703+ while (result->NextRow());
1704+
1705+ delete result;
1706+
1707+ sLog.outString();
1708+ sLog.outString( ">> Loaded %u vehicle data", count );
1709+}
1710+
1711+void ObjectMgr::LoadVehicleSeatData()
1712+{
1713+ mVehicleSeatData.clear();
1714+
1715+ QueryResult *result = WorldDatabase.Query("SELECT seat,flags FROM vehicle_seat_data");
1716+
1717+ if( !result )
1718+ {
1719+ barGoLink bar( 1 );
1720+
1721+ bar.step();
1722+
1723+ sLog.outString();
1724+ sLog.outString( ">> Loaded 0 vehicle seat data" );
1725+ sLog.outErrorDb("`vehicle_seat_data` table is empty!");
1726+ return;
1727+ }
1728+ uint32 count = 0;
1729+
1730+ barGoLink bar( result->GetRowCount() );
1731+ do
1732+ {
1733+ bar.step();
1734+
1735+ Field *fields = result->Fetch();
1736+ uint32 entry = fields[0].GetUInt32();
1737+ uint32 flag = fields[1].GetUInt32();
1738+
1739+ VehicleSeatEntry const *vsInfo = sVehicleSeatStore.LookupEntry(entry);
1740+ if(!vsInfo)
1741+ {
1742+ sLog.outErrorDb("Vehicle seat %u listed in `vehicle_seat_data` does not exist",entry);
1743+ continue;
1744+ }
1745+
1746+ mVehicleSeatData[entry] = flag;
1747+ ++count;
1748+ }
1749+ while (result->NextRow());
1750+
1751+ delete result;
1752+
1753+ sLog.outString();
1754+ sLog.outString( ">> Loaded %u vehicle seat data", count );
1755+}
1756+
1757 Quest const* GetQuestTemplateStore(uint32 entry)
1758 {
1759 return sObjectMgr.GetQuestTemplate(entry);
1760diff --git a/src/game/ObjectMgr.h b/src/game/ObjectMgr.h
1761index 78b79b9..579221d 100644
1762--- a/src/game/ObjectMgr.h
1763+++ b/src/game/ObjectMgr.h
1764@@ -419,6 +419,8 @@ extern LanguageDesc lang_description[LANGUAGES_COUNT];
1765 MANGOS_DLL_SPEC LanguageDesc const* GetLanguageDescByID(uint32 lang);
1766
1767 class PlayerDumpReader;
1768+// vehicle system
1769+#define MAX_VEHICLE_SPELLS 6
1770
1771 template<typename T>
1772 class IdGenerator
1773@@ -438,6 +440,16 @@ class IdGenerator
1774 T m_nextGuid;
1775 };
1776
1777+struct VehicleDataStructure
1778+{
1779+ uint32 v_flags; // vehicle flags, see enum CustomVehicleFLags
1780+ uint32 v_spells[MAX_VEHICLE_SPELLS]; // spells
1781+ uint32 req_aura; // requieres aura on player to enter (eg. in wintergrasp)
1782+};
1783+
1784+typedef UNORDERED_MAP<uint32, VehicleDataStructure> VehicleDataMap;
1785+typedef std::map<uint32,uint32> VehicleSeatDataMap;
1786+
1787 class ObjectMgr
1788 {
1789 friend class PlayerDumpReader;
1790@@ -702,6 +714,9 @@ class ObjectMgr
1791 void LoadVendors();
1792 void LoadTrainerSpell();
1793
1794+ void LoadVehicleData();
1795+ void LoadVehicleSeatData();
1796+
1797 std::string GeneratePetName(uint32 entry);
1798 uint32 GetBaseXP(uint32 level) const;
1799 uint32 GetXPForLevel(uint32 level) const;
1800@@ -950,6 +965,24 @@ class ObjectMgr
1801
1802 int GetOrNewIndexForLocale(LocaleConstant loc);
1803
1804+ VehicleDataMap mVehicleData;
1805+ VehicleSeatDataMap mVehicleSeatData;
1806+
1807+ uint32 GetSeatFlags(uint32 seatid)
1808+ {
1809+ VehicleSeatDataMap::iterator i = mVehicleSeatData.find(seatid);
1810+ if(i == mVehicleSeatData.end())
1811+ return NULL;
1812+ else
1813+ return i->second;
1814+ }
1815+ VehicleDataStructure const* GetVehicleData(uint32 entry) const
1816+ {
1817+ VehicleDataMap::const_iterator itr = mVehicleData.find(entry);
1818+ if(itr==mVehicleData.end()) return NULL;
1819+ return &itr->second;
1820+ }
1821+
1822 SpellClickInfoMapBounds GetSpellClickInfoMapBounds(uint32 creature_id) const
1823 {
1824 return SpellClickInfoMapBounds(mSpellClickInfoMap.lower_bound(creature_id),mSpellClickInfoMap.upper_bound(creature_id));
1825@@ -987,6 +1020,7 @@ class ObjectMgr
1826 ObjectGuidGenerator<HIGHGUID_ITEM> m_ItemGuids;
1827 ObjectGuidGenerator<HIGHGUID_GAMEOBJECT> m_GameobjectGuids;
1828 ObjectGuidGenerator<HIGHGUID_CORPSE> m_CorpseGuids;
1829+ ObjectGuidGenerator<HIGHGUID_VEHICLE> m_VehicleGuids;
1830
1831 QuestMap mQuestTemplates;
1832
1833@@ -1040,6 +1074,7 @@ class ObjectMgr
1834 void CheckScriptTexts(ScriptMapMap const& scripts,std::set<int32>& ids);
1835 void LoadCreatureAddons(SQLStorage& creatureaddons, char const* entryName, char const* comment);
1836 void ConvertCreatureAddonAuras(CreatureDataAddon* addon, char const* table, char const* guidEntryStr);
1837+ void ConvertCreatureAddonPassengers(CreatureDataAddon* addon, char const* table, char const* guidEntryStr);
1838 void LoadQuestRelationsHelper(QuestRelations& map,char const* table);
1839
1840 MailLevelRewardMap m_mailLevelRewardMap;
1841diff --git a/src/game/Opcodes.cpp b/src/game/Opcodes.cpp
1842index 6c26ded..41ceeb1 100644
1843--- a/src/game/Opcodes.cpp
1844+++ b/src/game/Opcodes.cpp
1845@@ -1168,10 +1168,10 @@ OpcodeHandler opcodeTable[NUM_MSG_TYPES] =
1846 /*0x473*/ { "CMSG_CHAR_CUSTOMIZE", STATUS_AUTHED, &WorldSession::HandleCharCustomize },
1847 /*0x474*/ { "SMSG_CHAR_CUSTOMIZE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
1848 /*0x475*/ { "SMSG_PET_RENAMEABLE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
1849- /*0x476*/ { "CMSG_REQUEST_VEHICLE_EXIT", STATUS_NEVER, &WorldSession::Handle_NULL },
1850- /*0x477*/ { "CMSG_REQUEST_VEHICLE_PREV_SEAT", STATUS_NEVER, &WorldSession::Handle_NULL },
1851- /*0x478*/ { "CMSG_REQUEST_VEHICLE_NEXT_SEAT", STATUS_NEVER, &WorldSession::Handle_NULL },
1852- /*0x479*/ { "CMSG_REQUEST_VEHICLE_SWITCH_SEAT", STATUS_NEVER, &WorldSession::Handle_NULL },
1853+ /*0x476*/ { "CMSG_REQUEST_VEHICLE_EXIT", STATUS_LOGGEDIN, &WorldSession::HandleRequestVehicleExit },
1854+ /*0x477*/ { "CMSG_REQUEST_VEHICLE_PREV_SEAT", STATUS_LOGGEDIN, &WorldSession::HandleChangeSeatsOnControlledVehicle},
1855+ /*0x478*/ { "CMSG_REQUEST_VEHICLE_NEXT_SEAT", STATUS_LOGGEDIN, &WorldSession::HandleChangeSeatsOnControlledVehicle},
1856+ /*0x479*/ { "CMSG_REQUEST_VEHICLE_SWITCH_SEAT", STATUS_LOGGEDIN, &WorldSession::HandleRequestVehicleSwitchSeat },
1857 /*0x47A*/ { "CMSG_PET_LEARN_TALENT", STATUS_LOGGEDIN, &WorldSession::HandlePetLearnTalent },
1858 /*0x47B*/ { "CMSG_PET_UNLEARN_TALENTS", STATUS_NEVER, &WorldSession::Handle_NULL },
1859 /*0x47C*/ { "SMSG_SET_PHASE_SHIFT", STATUS_NEVER, &WorldSession::Handle_ServerSide },
1860@@ -1205,7 +1205,7 @@ OpcodeHandler opcodeTable[NUM_MSG_TYPES] =
1861 /*0x498*/ { "SMSG_SERVER_FIRST_ACHIEVEMENT", STATUS_NEVER, &WorldSession::Handle_ServerSide },
1862 /*0x499*/ { "SMSG_PET_LEARNED_SPELL", STATUS_NEVER, &WorldSession::Handle_ServerSide },
1863 /*0x49A*/ { "SMSG_PET_REMOVED_SPELL", STATUS_NEVER, &WorldSession::Handle_ServerSide },
1864- /*0x49B*/ { "CMSG_CHANGE_SEATS_ON_CONTROLLED_VEHICLE", STATUS_NEVER, &WorldSession::Handle_NULL },
1865+ /*0x49B*/ { "CMSG_CHANGE_SEATS_ON_CONTROLLED_VEHICLE", STATUS_LOGGEDIN, &WorldSession::HandleChangeSeatsOnControlledVehicle},
1866 /*0x49C*/ { "CMSG_HEARTH_AND_RESURRECT", STATUS_LOGGEDIN, &WorldSession::HandleHearthandResurrect },
1867 /*0x49D*/ { "SMSG_ON_CANCEL_EXPECTED_RIDE_VEHICLE_AURA", STATUS_NEVER, &WorldSession::Handle_ServerSide },
1868 /*0x49E*/ { "SMSG_CRITERIA_DELETED", STATUS_NEVER, &WorldSession::Handle_ServerSide },
1869diff --git a/src/game/Pet.cpp b/src/game/Pet.cpp
1870index 45339c5..52c41d3 100644
1871--- a/src/game/Pet.cpp
1872+++ b/src/game/Pet.cpp
1873@@ -39,7 +39,7 @@ char const* petTypeSuffix[MAX_PET_TYPE] =
1874
1875 Pet::Pet(PetType type) :
1876 Creature(CREATURE_SUBTYPE_PET), m_removed(false), m_petType(type), m_happinessTimer(7500), m_duration(0), m_resetTalentsCost(0),
1877-m_bonusdamage(0), m_resetTalentsTime(0), m_usedTalentCount(0), m_auraUpdateMask(0), m_loading(false),
1878+m_bonusdamage(0), m_resetTalentsTime(0), m_usedTalentCount(0), m_loading(false),
1879 m_declinedname(NULL), m_petModeFlags(PET_MODE_DEFAULT)
1880 {
1881 m_name = "Pet";
1882diff --git a/src/game/Pet.h b/src/game/Pet.h
1883index efc9ecd..5d7417a 100644
1884--- a/src/game/Pet.h
1885+++ b/src/game/Pet.h
1886@@ -236,10 +236,6 @@ class Pet : public Creature
1887 time_t m_resetTalentsTime;
1888 uint32 m_usedTalentCount;
1889
1890- const uint64& GetAuraUpdateMask() const { return m_auraUpdateMask; }
1891- void SetAuraUpdateMask(uint8 slot) { m_auraUpdateMask |= (uint64(1) << slot); }
1892- void ResetAuraUpdateMask() { m_auraUpdateMask = 0; }
1893-
1894 // overwrite Creature function for name localization back to WorldObject version without localization
1895 const char* GetNameForLocaleIdx(int32 locale_idx) const { return WorldObject::GetNameForLocaleIdx(locale_idx); }
1896
1897@@ -251,7 +247,6 @@ class Pet : public Creature
1898 PetType m_petType;
1899 int32 m_duration; // time until unsummon (used mostly for summoned guardians and not used for controlled pets)
1900 int32 m_bonusdamage;
1901- uint64 m_auraUpdateMask;
1902 bool m_loading;
1903
1904 DeclinedName *m_declinedname;
1905diff --git a/src/game/PetHandler.cpp b/src/game/PetHandler.cpp
1906index 57356b3..1a855da 100644
1907--- a/src/game/PetHandler.cpp
1908+++ b/src/game/PetHandler.cpp
1909@@ -286,7 +286,7 @@ void WorldSession::HandlePetNameQuery( WorldPacket & recv_data )
1910
1911 void WorldSession::SendPetNameQuery( uint64 petguid, uint32 petnumber)
1912 {
1913- Creature* pet = _player->GetMap()->GetCreatureOrPetOrVehicle(petguid);
1914+ Creature* pet = ObjectAccessor::GetCreatureOrPetOrVehicle(*_player, petguid);
1915 if(!pet || !pet->GetCharmInfo() || pet->GetCharmInfo()->GetPetNumber() != petnumber)
1916 return;
1917
1918@@ -318,7 +318,12 @@ void WorldSession::HandlePetSetAction( WorldPacket & recv_data )
1919
1920 recv_data >> petguid;
1921
1922- Creature* pet = _player->GetMap()->GetCreatureOrPetOrVehicle(petguid);
1923+ // FIXME: charmed case
1924+ //Pet* pet = ObjectAccessor::Instance().GetPet(petguid);
1925+ if(ObjectAccessor::FindPlayer(petguid))
1926+ return;
1927+
1928+ Creature* pet = ObjectAccessor::GetCreatureOrPetOrVehicle(*_player, petguid);
1929
1930 if(!pet || (pet != _player->GetPet() && pet != _player->GetCharm()))
1931 {
1932@@ -506,7 +511,8 @@ void WorldSession::HandlePetAbandon( WorldPacket & recv_data )
1933 return;
1934
1935 // pet/charmed
1936- if (Creature* pet = _player->GetMap()->GetCreatureOrPetOrVehicle(guid))
1937+ Creature* pet = ObjectAccessor::GetCreatureOrPetOrVehicle(*_player, guid);
1938+ if(pet)
1939 {
1940 if(pet->isPet())
1941 {
1942@@ -560,29 +566,32 @@ void WorldSession::HandlePetSpellAutocastOpcode( WorldPacket& recvPacket )
1943 uint8 state; //1 for on, 0 for off
1944 recvPacket >> guid >> spellid >> state;
1945
1946- if(!_player->GetPet() && !_player->GetCharm())
1947+ if (!_player->GetPet() && !_player->GetCharm())
1948 return;
1949
1950- Creature* pet = _player->GetMap()->GetCreatureOrPetOrVehicle(guid);
1951+ if(ObjectAccessor::FindPlayer(guid))
1952+ return;
1953
1954- if(!pet || (pet != _player->GetPet() && pet != _player->GetCharm()))
1955+ Creature* pet=ObjectAccessor::GetCreatureOrPetOrVehicle(*_player,guid);
1956+
1957+ if (!pet || (pet != _player->GetPet() && pet != _player->GetCharm()))
1958 {
1959 sLog.outError( "HandlePetSpellAutocastOpcode.Pet %u isn't pet of player %s .", uint32(GUID_LOPART(guid)),GetPlayer()->GetName() );
1960 return;
1961 }
1962
1963 // do not add not learned spells/ passive spells
1964- if(!pet->HasSpell(spellid) || IsPassiveSpell(spellid))
1965+ if (!pet->HasSpell(spellid) || IsPassiveSpell(spellid))
1966 return;
1967
1968 CharmInfo *charmInfo = pet->GetCharmInfo();
1969- if(!charmInfo)
1970+ if (!charmInfo)
1971 {
1972 sLog.outError("WorldSession::HandlePetSpellAutocastOpcod: object (GUID: %u TypeId: %u) is considered pet-like but doesn't have a charminfo!", pet->GetGUIDLow(), pet->GetTypeId());
1973 return;
1974 }
1975
1976- if(pet->isCharmed())
1977+ if (pet->isCharmed())
1978 //state can be used as boolean
1979 pet->GetCharmInfo()->ToggleCreatureAutocast(spellid, state);
1980 else
1981@@ -594,6 +603,23 @@ void WorldSession::HandlePetSpellAutocastOpcode( WorldPacket& recvPacket )
1982 void WorldSession::HandlePetCastSpellOpcode( WorldPacket& recvPacket )
1983 {
1984 DETAIL_LOG("WORLD: CMSG_PET_CAST_SPELL");
1985+ recvPacket.hexlike();
1986+ recvPacket.print_storage();
1987+
1988+ //2 - 0 - 0 - 43 - 129 - 0 - 80 - 241 | - 42 - 211 - 253 - 0 | - 0 | - 2 |- 96 - 0 - 0 - 0 | - 0 - 26
1989+ //- 164 - 59 - 196 - 174 - 98 - 131 | - 194 - 182 - 171 - 218| - 67 - 0 - 48 - 93| - 0 - 196 - 32
1990+ //- 177| - 242 - 193 - 22 - 110 - 224 - 67 - 203 - 166 | - 68 - 61 - 133 - 1| - 240 - 66 - 1 - 183 |
1991+ //- 0 - 0 - 0 - 217| - 2 - 43 - 129 - 80 - 241 - 0 - 10 - 0 - 0 - 0 - 0 - 76 - 109 - 175 - 0
1992+ //- 238 - 115 - 58 - 196 - 20 - 110 - 121 - 194 - 187 - 107 - 217 - 67 - 32 - 44 - 27 - 62 - 217
1993+ //- 1 - 36 - 129 - 80 - 241 - 0 - 0 - 160 - 64 - 0 - 0 - 160 - 64 - 0 - 0 - 160 - 64 - 192 - 233
1994+ //- 172 - 62 - 4 - 0 - 0 - 0 - 7 - 230 - 0 - 0 - 0 -
1995+
1996+ //5 - 0 - 0 - 43 - 129 - 0 - 80 - 241 | - 85 - 211 - 253 - 0 | - 0 | - 2 | - 96 - 0 - 0 - 0 | - 0 - 69 - 60 - 61
1997+ //- 196 - 171 - 248 - 107| - 194 - 8 - 236 - 218 | - 67 - 0 - 177 - 11 | - 46 - 196 - 89 - 16 | - 14 - 195
1998+ //- 5 - 38 - 231 - 67 - 23 - 221 | - 110 - 62 - 15 - 3 | - 240 - 66 -| 1 - 183 | - 0 - 0 - 0 - 217 | - 5 - 43
1999+ //- 129 - 80 - 241 - 0 - 10 - 0 - 0 - 0 - 0 - 233 - 41 - 203 - 0 - 106 - 207 - 59 - 196 - 179 - 173 - 83
2000+ //- 194 - 8 - 108 - 217 - 67 - 127 - 153 - 170 - 64 - 217 - 4 - 36 - 129 - 80 - 241 - 0 - 0 - 160 - 64
2001+ //- 0 - 0 - 160 - 64 - 0 - 0 - 160 - 64 - 7 - 77 - 175 - 64 - 4 - 0 - 0 - 0 - 7 - 195 - 0 - 0 - 0 -
2002
2003 uint64 guid;
2004 uint32 spellid;
2005@@ -607,7 +633,10 @@ void WorldSession::HandlePetCastSpellOpcode( WorldPacket& recvPacket )
2006 if (!_player->GetPet() && !_player->GetCharm())
2007 return;
2008
2009- Creature* pet = _player->GetMap()->GetCreatureOrPetOrVehicle(guid);
2010+ if (GUID_HIPART(guid) == HIGHGUID_PLAYER)
2011+ return;
2012+
2013+ Creature* pet = ObjectAccessor::GetCreatureOrPetOrVehicle(*_player,guid);
2014
2015 if (!pet || (pet != _player->GetPet() && pet!= _player->GetCharm()))
2016 {
2017diff --git a/src/game/Player.cpp b/src/game/Player.cpp
2018index 4b71715..4f96537 100644
2019--- a/src/game/Player.cpp
2020+++ b/src/game/Player.cpp
2021@@ -465,7 +465,6 @@ Player::Player (WorldSession *session): Unit(), m_achievementMgr(this), m_reputa
2022 // group is initialized in the reference constructor
2023 SetGroupInvite(NULL);
2024 m_groupUpdateMask = 0;
2025- m_auraUpdateMask = 0;
2026
2027 duel = NULL;
2028
2029@@ -1755,6 +1754,7 @@ bool Player::TeleportTo(uint32 mapid, float x, float y, float z, float orientati
2030 m_transport = NULL;
2031 m_movementInfo.ClearTransportData();
2032 }
2033+ ExitVehicle();
2034
2035 // The player was ported to another map and looses the duel immediately.
2036 // We have to perform this check before the teleport, otherwise the
2037@@ -2237,7 +2237,7 @@ Creature* Player::GetNPCIfCanInteractWith(ObjectGuid guid, uint32 npcflagmask)
2038 return NULL;
2039
2040 // exist (we need look pets also for some interaction (quest/etc)
2041- Creature *unit = GetMap()->GetCreatureOrPetOrVehicle(guid);
2042+ Creature *unit = ObjectAccessor::GetCreatureOrPetOrVehicle(*this,guid);
2043 if (!unit)
2044 return NULL;
2045
2046@@ -8454,6 +8454,41 @@ void Player::SendInitWorldStates(uint32 zoneid, uint32 areaid)
2047 break;
2048 case 3703: // Shattrath City
2049 break;
2050+ case 4384: // SA
2051+ /*if (bg && bg->GetTypeID() == BATTLEGROUND_SA)
2052+ bg->FillInitialWorldStates(data);
2053+ else
2054+ {*/
2055+ // 1-3 A defend, 4-6 H defend, 7-9 unk defend, 1 - ok, 2 - half destroyed, 3 - destroyed
2056+ data << uint32(0xf09) << uint32(0x4); // 7 3849 Gate of Temple
2057+ data << uint32(0xe36) << uint32(0x4); // 8 3638 Gate of Yellow Moon
2058+ data << uint32(0xe27) << uint32(0x4); // 9 3623 Gate of Green Emerald
2059+ data << uint32(0xe24) << uint32(0x4); // 10 3620 Gate of Blue Sapphire
2060+ data << uint32(0xe21) << uint32(0x4); // 11 3617 Gate of Red Sun
2061+ data << uint32(0xe1e) << uint32(0x4); // 12 3614 Gate of Purple Ametyst
2062+
2063+ data << uint32(0xdf3) << uint32(0x0); // 13 3571 bonus timer (1 - on, 0 - off)
2064+ data << uint32(0xded) << uint32(0x0); // 14 3565 Horde Attacker
2065+ data << uint32(0xdec) << uint32(0x1); // 15 3564 Alliance Attacker
2066+ // End Round (timer), better explain this by example, eg. ends in 19:59 -> A:BC
2067+ data << uint32(0xde9) << uint32(0x9); // 16 3561 C
2068+ data << uint32(0xde8) << uint32(0x5); // 17 3560 B
2069+ data << uint32(0xde7) << uint32(0x19); // 18 3559 A
2070+ data << uint32(0xe35) << uint32(0x1); // 19 3637 East g - Horde control
2071+ data << uint32(0xe34) << uint32(0x1); // 20 3636 West g - Horde control
2072+ data << uint32(0xe33) << uint32(0x1); // 21 3635 South g - Horde control
2073+ data << uint32(0xe32) << uint32(0x0); // 22 3634 East g - Alliance control
2074+ data << uint32(0xe31) << uint32(0x0); // 23 3633 West g - Alliance control
2075+ data << uint32(0xe30) << uint32(0x0); // 24 3632 South g - Alliance control
2076+ data << uint32(0xe2f) << uint32(0x1); // 25 3631 Chamber of Ancients - Horde control
2077+ data << uint32(0xe2e) << uint32(0x0); // 26 3630 Chamber of Ancients - Alliance control
2078+ data << uint32(0xe2d) << uint32(0x0); // 27 3629 Beach1 - Horde control
2079+ data << uint32(0xe2c) << uint32(0x0); // 28 3628 Beach2 - Horde control
2080+ data << uint32(0xe2b) << uint32(0x1); // 29 3627 Beach1 - Alliance control
2081+ data << uint32(0xe2a) << uint32(0x1); // 30 3626 Beach2 - Alliance control
2082+ // and many unks...
2083+ //}
2084+ break;
2085 default:
2086 FillInitialWorldState(data,count, 0x914, 0x0); // 7
2087 FillInitialWorldState(data,count, 0x913, 0x0); // 8
2088@@ -13064,7 +13099,8 @@ void Player::PrepareQuestMenu( uint64 guid )
2089 QuestRelations* pObjectQIR;
2090
2091 // pets also can have quests
2092- if (Creature *pCreature = GetMap()->GetCreatureOrPetOrVehicle(guid))
2093+ Creature *pCreature = ObjectAccessor::GetCreatureOrPetOrVehicle(*this, guid);
2094+ if( pCreature )
2095 {
2096 pObject = (Object*)pCreature;
2097 pObjectQR = &sObjectMgr.mCreatureQuestRelations;
2098@@ -13158,7 +13194,8 @@ void Player::SendPreparedQuest(uint64 guid)
2099 std::string title = "";
2100
2101 // need pet case for some quests
2102- if (Creature *pCreature = GetMap()->GetCreatureOrPetOrVehicle(guid))
2103+ Creature *pCreature = ObjectAccessor::GetCreatureOrPetOrVehicle(*this,guid);
2104+ if (pCreature)
2105 {
2106 uint32 textid = GetGossipTextId(pCreature);
2107
2108@@ -13231,7 +13268,8 @@ Quest const * Player::GetNextQuest( uint64 guid, Quest const *pQuest )
2109 QuestRelations* pObjectQR;
2110 QuestRelations* pObjectQIR;
2111
2112- if (Creature *pCreature = GetMap()->GetCreatureOrPetOrVehicle(guid))
2113+ Creature *pCreature = ObjectAccessor::GetCreatureOrPetOrVehicle(*this,guid);
2114+ if( pCreature )
2115 {
2116 pObject = (Object*)pCreature;
2117 pObjectQR = &sObjectMgr.mCreatureQuestRelations;
2118@@ -18183,7 +18221,12 @@ void Player::HandleStealthedUnitsDetection()
2119 // target aura duration for caster show only if target exist at caster client
2120 // send data at target visibility change (adding to client)
2121 if((*i)!=this && (*i)->isType(TYPEMASK_UNIT))
2122+ {
2123 SendAurasForTarget(*i);
2124+ WorldPacket data;
2125+ (*i)->BuildHeartBeatMsg(&data);
2126+ GetSession()->SendPacket(&data);
2127+ }
2128 }
2129 }
2130 else
2131@@ -18218,7 +18261,7 @@ bool Player::ActivateTaxiPathTo(std::vector<uint32> const& nodes, Creature* npc
2132 if(npc)
2133 {
2134 // not let cheating with start flight mounted
2135- if(IsMounted())
2136+ if(IsMounted() || GetVehicleGUID())
2137 {
2138 WorldPacket data(SMSG_ACTIVATETAXIREPLY, 4);
2139 data << uint32(ERR_TAXIPLAYERALREADYMOUNTED);
2140@@ -18247,6 +18290,7 @@ bool Player::ActivateTaxiPathTo(std::vector<uint32> const& nodes, Creature* npc
2141 else
2142 {
2143 RemoveSpellsCausingAura(SPELL_AURA_MOUNTED);
2144+ ExitVehicle();
2145
2146 if( m_ShapeShiftFormSpellId && m_form != FORM_BATTLESTANCE && m_form != FORM_BERSERKERSTANCE && m_form != FORM_DEFENSIVESTANCE && m_form != FORM_SHADOW )
2147 RemoveAurasDueToSpell(m_ShapeShiftFormSpellId);
2148@@ -19366,7 +19410,12 @@ void Player::UpdateVisibilityOf(WorldObject const* viewPoint, WorldObject* targe
2149 // target aura duration for caster show only if target exist at caster client
2150 // send data at target visibility change (adding to client)
2151 if(target!=this && target->isType(TYPEMASK_UNIT))
2152+ {
2153 SendAurasForTarget((Unit*)target);
2154+ WorldPacket data;
2155+ ((Unit*)target)->BuildHeartBeatMsg(&data);
2156+ GetSession()->SendPacket(&data);
2157+ }
2158
2159 if(target->GetTypeId()==TYPEID_UNIT && ((Creature*)target)->isAlive())
2160 ((Creature*)target)->SendMonsterMoveWithSpeedToCurrentDestination(this);
2161@@ -19431,13 +19480,22 @@ void Player::InitPrimaryProfessions()
2162 void Player::SendComboPoints()
2163 {
2164 Unit *combotarget = ObjectAccessor::GetUnit(*this, m_comboTarget);
2165- if (combotarget)
2166- {
2167- WorldPacket data(SMSG_UPDATE_COMBO_POINTS, combotarget->GetPackGUID().size()+1);
2168- data << combotarget->GetPackGUID();
2169- data << uint8(m_comboPoints);
2170- GetSession()->SendPacket(&data);
2171- }
2172+ if (!combotarget)
2173+ return;
2174+
2175+ WorldPacket data;
2176+ if(!GetVehicleGUID())
2177+ data.Initialize(SMSG_UPDATE_COMBO_POINTS, combotarget->GetPackGUID().size()+1);
2178+ else{
2179+ if(Unit *vehicle = ObjectAccessor::GetUnit(*this, GetVehicleGUID()))
2180+ {
2181+ data.Initialize(SMSG_PET_UPDATE_COMBO_POINTS, vehicle->GetPackGUID().size()+combotarget->GetPackGUID().size()+1);
2182+ data << vehicle->GetPackGUID();
2183+ }else return;
2184+ }
2185+ data << combotarget->GetPackGUID();
2186+ data << uint8(m_comboPoints);
2187+ GetSession()->SendPacket(&data);
2188 }
2189
2190 void Player::AddComboPoints(Unit* target, int8 count)
2191@@ -19560,6 +19618,13 @@ void Player::SendInitialPacketsBeforeAddToMap()
2192
2193 void Player::SendInitialPacketsAfterAddToMap()
2194 {
2195+ if(getClass() == CLASS_DEATH_KNIGHT)
2196+ ResyncRunes(MAX_RUNES);
2197+
2198+ WorldPacket data0(SMSG_SET_PHASE_SHIFT, 4);
2199+ data0 << uint32(GetPhaseMask());
2200+ GetSession()->SendPacket(&data0);
2201+
2202 // update zone
2203 uint32 newzone, newarea;
2204 GetZoneAndAreaId(newzone,newarea);
2205@@ -19598,6 +19663,14 @@ void Player::SendInitialPacketsAfterAddToMap()
2206 SendMessageToSet(&data2,true);
2207 }
2208
2209+ if(GetVehicleGUID())
2210+ {
2211+ WorldPacket data3(SMSG_FORCE_MOVE_ROOT, 10);
2212+ data3 << GetPackGUID();
2213+ data3 << (uint32)((m_movementInfo.GetVehicleSeatFlags() & SF_CAN_CAST) ? 2 : 0);
2214+ SendMessageToSet(&data3,true);
2215+ }
2216+
2217 SendAurasForTarget(this);
2218 SendEnchantmentDurations(); // must be after add to map
2219 SendItemDurations(); // must be after add to map
2220@@ -19612,7 +19685,7 @@ void Player::SendUpdateToOutOfRangeGroupMembers()
2221
2222 m_groupUpdateMask = GROUP_UPDATE_FLAG_NONE;
2223 m_auraUpdateMask = 0;
2224- if(Pet *pet = GetPet())
2225+ if(Unit *pet = GetCharmOrPet())
2226 pet->ResetAuraUpdateMask();
2227 }
2228
2229@@ -20057,7 +20130,7 @@ void Player::UpdateForQuestWorldObjects()
2230 }
2231 else if (itr->IsCreatureOrVehicle())
2232 {
2233- Creature *obj = GetMap()->GetCreatureOrPetOrVehicle(*itr);
2234+ Creature *obj = ObjectAccessor::GetCreatureOrPetOrVehicle(*this, *itr);
2235 if(!obj)
2236 continue;
2237
2238@@ -20329,8 +20402,8 @@ void Player::RewardSinglePlayerAtKill(Unit* pVictim)
2239 // honor can be in PvP and !PvP (racial leader) cases
2240 RewardHonor(pVictim,1);
2241
2242- // xp and reputation only in !PvP case
2243- if(!PvP)
2244+ // xp and reputation only in !PvP case and not in vehicle
2245+ if(!PvP && !(GetVehicleGUID() && (m_movementInfo.GetVehicleFlags() & VF_GIVE_EXP)))
2246 {
2247 RewardReputation(pVictim,1);
2248 GiveXP(xp, pVictim);
2249@@ -20830,26 +20903,16 @@ void Player::ApplyGlyphs(bool apply)
2250 ApplyGlyph(i,apply);
2251 }
2252
2253-void Player::EnterVehicle(Vehicle *vehicle)
2254+void Player::SendEnterVehicle(Vehicle *vehicle)
2255 {
2256- VehicleEntry const *ve = sVehicleStore.LookupEntry(vehicle->GetVehicleId());
2257- if(!ve)
2258- return;
2259-
2260- VehicleSeatEntry const *veSeat = sVehicleSeatStore.LookupEntry(ve->m_seatID[0]);
2261- if(!veSeat)
2262- return;
2263-
2264- vehicle->SetCharmerGUID(GetGUID());
2265- vehicle->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_SPELLCLICK);
2266- vehicle->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PLAYER_CONTROLLED);
2267- vehicle->setFaction(getFaction());
2268-
2269- SetCharm(vehicle); // charm
2270- m_camera.SetView(vehicle); // set view
2271-
2272- SetClientControl(vehicle, 1); // redirect controls to vehicle
2273- SetMover(vehicle);
2274+ if(m_transport) // if we were on a transport, leave
2275+ {
2276+ m_transport->RemovePassenger(this);
2277+ m_transport = NULL;
2278+ }
2279+ // vehicle is our transport from now, if we get to zeppelin or boat
2280+ // with vehicle, ONLY my vehicle will be passenger on that transport
2281+ // player ----> vehicle ----> zeppelin
2282
2283 WorldPacket data(SMSG_ON_CANCEL_EXPECTED_RIDE_VEHICLE_AURA, 0);
2284 GetSession()->SendPacket(&data);
2285@@ -20866,60 +20929,20 @@ void Player::EnterVehicle(Vehicle *vehicle)
2286 data << vehicle->GetOrientation(); // o
2287 // transport part, TODO: load/calculate seat offsets
2288 data << uint64(vehicle->GetGUID()); // transport guid
2289- data << float(veSeat->m_attachmentOffsetX); // transport offsetX
2290- data << float(veSeat->m_attachmentOffsetY); // transport offsetY
2291- data << float(veSeat->m_attachmentOffsetZ); // transport offsetZ
2292- data << float(0); // transport orientation
2293+ data << float(m_movementInfo.GetTransportPos()->x); // transport offsetX
2294+ data << float(m_movementInfo.GetTransportPos()->y); // transport offsetY
2295+ data << float(m_movementInfo.GetTransportPos()->z); // transport offsetZ
2296+ data << float(m_movementInfo.GetTransportPos()->o); // transport orientation
2297 data << uint32(getMSTime()); // transport time
2298 data << uint8(0); // seat
2299 // end of transport part
2300 data << uint32(0); // fall time
2301 GetSession()->SendPacket(&data);
2302
2303- data.Initialize(SMSG_PET_SPELLS, 8+2+4+4+4*MAX_UNIT_ACTION_BAR_INDEX+1+1);
2304- data << uint64(vehicle->GetGUID());
2305- data << uint16(0);
2306- data << uint32(0);
2307- data << uint32(0x00000101);
2308-
2309- for(uint32 i = 0; i < 10; ++i)
2310- data << uint16(0) << uint8(0) << uint8(i+8);
2311-
2312- data << uint8(0);
2313- data << uint8(0);
2314- GetSession()->SendPacket(&data);
2315-}
2316-
2317-void Player::ExitVehicle(Vehicle *vehicle)
2318-{
2319- vehicle->SetCharmerGUID(0);
2320- vehicle->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_SPELLCLICK);
2321- vehicle->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PLAYER_CONTROLLED);
2322- vehicle->setFaction((GetTeam() == ALLIANCE) ? vehicle->GetCreatureInfo()->faction_A : vehicle->GetCreatureInfo()->faction_H);
2323-
2324- SetCharm(NULL);
2325- m_camera.ResetView();
2326-
2327- SetClientControl(vehicle, 0);
2328- SetMover(NULL);
2329-
2330- WorldPacket data(MSG_MOVE_TELEPORT_ACK, 30);
2331- data << GetPackGUID();
2332- data << uint32(0); // counter?
2333- data << uint32(MOVEFLAG_ROOT); // fly unk
2334- data << uint16(MOVEFLAG2_UNK4); // special flags
2335- data << uint32(getMSTime()); // time
2336- data << vehicle->GetPositionX(); // x
2337- data << vehicle->GetPositionY(); // y
2338- data << vehicle->GetPositionZ(); // z
2339- data << vehicle->GetOrientation(); // o
2340- data << uint32(0); // fall time
2341- GetSession()->SendPacket(&data);
2342-
2343- RemovePetActionBar();
2344-
2345- // maybe called at dummy aura remove?
2346- // CastSpell(this, 45472, true); // Parachute
2347+ /*data.Initialize(SMSG_UNKNOWN_1191, 12);
2348+ data << uint64(GetGUID());
2349+ data << uint64(vehicle->GetVehicleId()); // not sure
2350+ SendMessageToSet(&data, true);*/
2351 }
2352
2353 bool Player::isTotalImmune()
2354@@ -20984,7 +21007,8 @@ void Player::ConvertRune(uint8 index, RuneType newType)
2355
2356 void Player::ResyncRunes(uint8 count)
2357 {
2358- WorldPacket data(SMSG_RESYNC_RUNES, count * 2);
2359+ WorldPacket data(SMSG_RESYNC_RUNES, 4 + count * 2);
2360+ data << uint32(count + 1);
2361 for(uint32 i = 0; i < count; ++i)
2362 {
2363 data << uint8(GetCurrentRune(i)); // rune type
2364diff --git a/src/game/Player.h b/src/game/Player.h
2365index f7b0afa..e4a2da1 100644
2366--- a/src/game/Player.h
2367+++ b/src/game/Player.h
2368@@ -2194,6 +2194,7 @@ class MANGOS_DLL_SPEC Player : public Unit
2369 /*********************************************************/
2370 bool HasMovementFlag(MovementFlags f) const; // for script access to m_movementInfo.HasMovementFlag
2371 void UpdateFallInformationIfNeed(MovementInfo const& minfo,uint16 opcode);
2372+
2373 void SetFallInformation(uint32 time, float z)
2374 {
2375 m_lastFallTime = time;
2376@@ -2215,8 +2216,8 @@ class MANGOS_DLL_SPEC Player : public Unit
2377 Unit* GetMover() const { return m_mover; }
2378 bool IsSelfMover() const { return m_mover == this; }// normal case for player not controlling other unit
2379
2380- void EnterVehicle(Vehicle *vehicle);
2381- void ExitVehicle(Vehicle *vehicle);
2382+ // vehicle system
2383+ void SendEnterVehicle(Vehicle *vehicle);
2384
2385 ObjectGuid const& GetFarSightGuid() const { return GetGuidValue(PLAYER_FARSIGHT); }
2386
2387@@ -2319,8 +2320,6 @@ class MANGOS_DLL_SPEC Player : public Unit
2388 uint8 GetSubGroup() const { return m_group.getSubGroup(); }
2389 uint32 GetGroupUpdateFlag() const { return m_groupUpdateMask; }
2390 void SetGroupUpdateFlag(uint32 flag) { m_groupUpdateMask |= flag; }
2391- const uint64& GetAuraUpdateMask() const { return m_auraUpdateMask; }
2392- void SetAuraUpdateMask(uint8 slot) { m_auraUpdateMask |= (uint64(1) << slot); }
2393 Player* GetNextRandomRaidMember(float radius);
2394 PartyResult CanUninviteFromGroup() const;
2395 // BattleGround Group System
2396@@ -2571,7 +2570,6 @@ class MANGOS_DLL_SPEC Player : public Unit
2397 GroupReference m_originalGroup;
2398 Group *m_groupInvite;
2399 uint32 m_groupUpdateMask;
2400- uint64 m_auraUpdateMask;
2401
2402 uint64 m_miniPet;
2403
2404diff --git a/src/game/QuestHandler.cpp b/src/game/QuestHandler.cpp
2405index a0b7872..b8c9374 100644
2406--- a/src/game/QuestHandler.cpp
2407+++ b/src/game/QuestHandler.cpp
2408@@ -659,9 +659,8 @@ void WorldSession::HandleQuestgiverStatusMultipleQuery(WorldPacket& /*recvPacket
2409 if (itr->IsCreatureOrPet())
2410 {
2411 // need also pet quests case support
2412- Creature *questgiver = GetPlayer()->GetMap()->GetCreatureOrPetOrVehicle(*itr);
2413-
2414- if (!questgiver || questgiver->IsHostileTo(_player))
2415+ Creature *questgiver = ObjectAccessor::GetCreatureOrPetOrVehicle(*GetPlayer(),*itr);
2416+ if(!questgiver || questgiver->IsHostileTo(_player))
2417 continue;
2418
2419 if (!questgiver->HasFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_QUESTGIVER))
2420diff --git a/src/game/ReactorAI.cpp b/src/game/ReactorAI.cpp
2421index f39cd1a..fd52ee2 100644
2422--- a/src/game/ReactorAI.cpp
2423+++ b/src/game/ReactorAI.cpp
2424@@ -116,6 +116,7 @@ ReactorAI::EnterEvadeMode()
2425 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());
2426 }
2427
2428+ m_creature->ExitVehicle();
2429 m_creature->RemoveAllAuras();
2430 m_creature->DeleteThreatList();
2431 i_victimGuid = 0;
2432diff --git a/src/game/SharedDefines.h b/src/game/SharedDefines.h
2433index 3e25e4b..9e8715b 100644
2434--- a/src/game/SharedDefines.h
2435+++ b/src/game/SharedDefines.h
2436@@ -2462,6 +2462,29 @@ enum DiminishingGroup
2437 DIMINISHING_LIMITONLY
2438 };
2439
2440+
2441+/* NOTE : vehicles and seats has their own flags in DBC,
2442+but for now, they are too unknown for us, to use them */
2443+enum CustomVehicleFLags
2444+{
2445+ VF_CANT_MOVE = 0x0001, // vehicle cant move, only turn, maybe handle by some auras?
2446+ VF_FACTION = 0x0002, // vehicle retain its own faction
2447+ VF_DESPAWN_NPC = 0x0004, // vehicle will delete npc on spellclick
2448+ VF_DESPAWN_AT_LEAVE = 0x0008, // vehicle will be deleted when rider leaves
2449+ VF_CAN_BE_HEALED = 0x0010, // vehicle can be healed
2450+ VF_GIVE_EXP = 0x0020, // vehicle will give exp for killing enemies
2451+ VF_MOVEMENT = 0x0040, // vehicle will move on its own, not depending on rider, however rider can cast spells
2452+ VF_NON_SELECTABLE = 0x0080 // vehicle will be not selectable after rider enter
2453+ //VF_HAS_FUEL = 0x0100, // TODO : find out what energy type is fuel and implement this
2454+};
2455+
2456+enum CustomVehicleSeatFLags
2457+{
2458+ SF_MAIN_RIDER = 0x0001, // the one who controlls vehicle, can also cast spells
2459+ SF_UNATTACKABLE = 0x0002, // hided inside, and unatackable until vehicle is destroyed
2460+ SF_CAN_CAST = 0x0004, // player/npc can rotate, and cast OWN spells
2461+ SF_UNACCESSIBLE = 0x0008 // player cant enter this seat by normal way (only by script)
2462+};
2463 enum ResponseCodes
2464 {
2465 RESPONSE_SUCCESS = 0x00,
2466diff --git a/src/game/Spell.cpp b/src/game/Spell.cpp
2467index 9727b61..f40ee66 100644
2468--- a/src/game/Spell.cpp
2469+++ b/src/game/Spell.cpp
2470@@ -120,7 +120,8 @@ SpellCastTargets::SpellCastTargets()
2471 m_itemTargetGUID = 0;
2472 m_itemTargetEntry = 0;
2473
2474- m_srcX = m_srcY = m_srcZ = m_destX = m_destY = m_destZ = 0.0f;
2475+ m_srcX = m_srcY = m_srcZ = m_srcO = m_destX = m_destY = m_destZ = 0.0f;
2476+ m_elevation = m_speed = 0.0f;
2477 m_strTarget = "";
2478 m_targetMask = 0;
2479 }
2480@@ -257,6 +258,19 @@ void SpellCastTargets::read( ByteBuffer& data, Unit *caster )
2481 data >> m_destX >> m_destY >> m_destZ;
2482 if(!MaNGOS::IsValidMapCoord(m_destX, m_destY, m_destZ))
2483 throw ByteBufferException(false, data.rpos(), 0, data.size());
2484+
2485+ if( m_targetMask & TARGET_FLAG_SOURCE_LOCATION )
2486+ {
2487+ if(data.rpos() + 4 + 4 <= data.size())
2488+ {
2489+ data >> m_elevation >> m_speed;
2490+ // TODO: should also read
2491+ m_srcO = caster->GetOrientation();
2492+ //*data >> uint16 >> uint8 >> uint32 >> uint32;
2493+ //*data >> float >> float >> float >> float...
2494+ }
2495+ }
2496+
2497 }
2498
2499 if( m_targetMask & TARGET_FLAG_STRING )
2500@@ -1596,9 +1610,11 @@ void Spell::SetTargetMap(SpellEffectIndex effIndex, uint32 targetMode, UnitList&
2501 case TARGET_TOTEM_FIRE:
2502 case TARGET_SELF:
2503 case TARGET_SELF2:
2504- case TARGET_AREAEFFECT_CUSTOM_2:
2505+ {
2506+ // used for targeting gameobjects
2507 targetUnitMap.push_back(m_caster);
2508 break;
2509+ }
2510 case TARGET_RANDOM_ENEMY_CHAIN_IN_AREA:
2511 {
2512 m_targets.m_targetMask = 0;
2513@@ -1867,6 +1883,9 @@ void Spell::SetTargetMap(SpellEffectIndex effIndex, uint32 targetMode, UnitList&
2514 break;
2515 default:
2516 FillAreaTargets(targetUnitMap, m_targets.m_destX, m_targets.m_destY, radius, PUSH_DEST_CENTER, SPELL_TARGETS_AOE_DAMAGE);
2517+
2518+ // exclude caster (this can be important if this not original caster, for example vehicle)
2519+ targetUnitMap.remove(m_caster);
2520 break;
2521 }
2522 break;
2523@@ -2361,7 +2380,13 @@ void Spell::SetTargetMap(SpellEffectIndex effIndex, uint32 targetMode, UnitList&
2524 case TARGET_DYNAMIC_OBJECT_LEFT_SIDE:
2525 case TARGET_DYNAMIC_OBJECT_RIGHT_SIDE:
2526 {
2527- if (!(m_targets.m_targetMask & TARGET_FLAG_DEST_LOCATION))
2528+ //This should be targeting of destructible objects by vehicles (ram spells...)
2529+ if(m_spellInfo->EffectImplicitTargetB[effIndex] == TARGET_AREAEFFECT_CUSTOM_2)
2530+ {
2531+ //FIXME
2532+ break;
2533+ }
2534+ else if (!(m_targets.m_targetMask & TARGET_FLAG_DEST_LOCATION))
2535 {
2536 float angle = m_caster->GetOrientation();
2537 switch(targetMode)
2538@@ -3347,7 +3372,7 @@ void Spell::finish(bool ok)
2539 m_caster->resetAttackTimer(RANGED_ATTACK);*/
2540
2541 // Clear combo at finish state
2542- if(m_caster->GetTypeId() == TYPEID_PLAYER && NeedsComboPoints(m_spellInfo))
2543+ if((m_caster->GetTypeId() == TYPEID_PLAYER || ((Creature*)m_caster)->isVehicle()) && NeedsComboPoints(m_spellInfo))
2544 {
2545 // Not drop combopoints if negative spell and if any miss on enemy exist
2546 bool needDrop = true;
2547@@ -3366,7 +3391,12 @@ void Spell::finish(bool ok)
2548 }
2549 }
2550 if (needDrop)
2551- ((Player*)m_caster)->ClearComboPoints();
2552+ {
2553+ if(m_caster->GetTypeId() == TYPEID_PLAYER)
2554+ ((Player*)m_caster)->ClearComboPoints();
2555+ else
2556+ ((Player*)m_caster->GetCharmer())->ClearComboPoints();
2557+ }
2558 }
2559
2560 // potions disabled by client, send event "not in combat" if need
2561@@ -4560,11 +4590,16 @@ SpellCastResult Spell::CheckCast(bool strict)
2562 return locRes;
2563
2564 // not let players cast spells at mount (and let do it to creatures)
2565- if (m_caster->IsMounted() && m_caster->GetTypeId()==TYPEID_PLAYER && !m_IsTriggeredSpell &&
2566+ if ((m_caster->IsMounted() || m_caster->GetVehicleGUID()) && m_caster->GetTypeId()==TYPEID_PLAYER && !m_IsTriggeredSpell &&
2567 !IsPassiveSpell(m_spellInfo) && !(m_spellInfo->Attributes & SPELL_ATTR_CASTABLE_WHILE_MOUNTED))
2568 {
2569 if (m_caster->isInFlight())
2570 return SPELL_FAILED_NOT_ON_TAXI;
2571+ else if(m_caster->GetVehicleGUID())
2572+ {
2573+ if(!(m_caster->m_movementInfo.GetVehicleSeatFlags() & SF_CAN_CAST))
2574+ return SPELL_FAILED_NOT_MOUNTED;
2575+ }
2576 else
2577 return SPELL_FAILED_NOT_MOUNTED;
2578 }
2579@@ -5384,33 +5419,48 @@ SpellCastResult Spell::CheckPetCast(Unit* target)
2580 if(!_target->isAlive())
2581 return SPELL_FAILED_BAD_TARGETS;
2582
2583- if(IsPositiveSpell(m_spellInfo->Id))
2584- {
2585- if(m_caster->IsHostileTo(_target))
2586- return SPELL_FAILED_BAD_TARGETS;
2587- }
2588- else
2589- {
2590- bool duelvsplayertar = false;
2591- for(int j = 0; j < MAX_EFFECT_INDEX; ++j)
2592- {
2593- //TARGET_DUELVSPLAYER is positive AND negative
2594- duelvsplayertar |= (m_spellInfo->EffectImplicitTargetA[j] == TARGET_DUELVSPLAYER);
2595- }
2596- if(m_caster->IsFriendlyTo(target) && !duelvsplayertar)
2597- {
2598- return SPELL_FAILED_BAD_TARGETS;
2599- }
2600- }
2601+ if(!IsValidSingleTargetSpell(_target))
2602+ return SPELL_FAILED_BAD_TARGETS;
2603 }
2604 //cooldown
2605 if(((Creature*)m_caster)->HasSpellCooldown(m_spellInfo->Id))
2606 return SPELL_FAILED_NOT_READY;
2607 }
2608
2609+ // NOTE : this is done twice, also in spell->prepare(&(spell->m_targets));
2610 return CheckCast(true);
2611 }
2612
2613+bool Spell::IsValidSingleTargetEffect(Unit const* target, Targets type) const
2614+{
2615+ switch(type)
2616+ {
2617+ case TARGET_CHAIN_DAMAGE:
2618+ return !m_caster->IsFriendlyTo(target);
2619+ case TARGET_SINGLE_FRIEND:
2620+ case TARGET_AREAEFFECT_PARTY:
2621+ return m_caster->IsFriendlyTo(target);
2622+ case TARGET_SINGLE_PARTY:
2623+ return m_caster != target && m_caster->IsInPartyWith(target);
2624+ case TARGET_SINGLE_FRIEND_2:
2625+ return m_caster->IsInRaidWith(target);
2626+ }
2627+ return true;
2628+}
2629+
2630+bool Spell::IsValidSingleTargetSpell(Unit const* target) const
2631+{
2632+ for(int i = 0; i < 3; ++i)
2633+ {
2634+ if(!IsValidSingleTargetEffect(target, Targets(m_spellInfo->EffectImplicitTargetA[i])))
2635+ return false;
2636+ // Need to check B?
2637+ //if(!IsValidSingleTargetEffect(m_spellInfo->EffectImplicitTargetB[i], target)
2638+ // return false;
2639+ }
2640+ return true;
2641+}
2642+
2643 SpellCastResult Spell::CheckCasterAuras() const
2644 {
2645 // Flag drop spells totally immuned to caster auras
2646diff --git a/src/game/Spell.h b/src/game/Spell.h
2647index 2db96b1..b80ad5f 100644
2648--- a/src/game/Spell.h
2649+++ b/src/game/Spell.h
2650@@ -166,8 +166,9 @@ class SpellCastTargets
2651
2652 void Update(Unit* caster);
2653
2654- float m_srcX, m_srcY, m_srcZ;
2655+ float m_srcX, m_srcY, m_srcZ, m_srcO;
2656 float m_destX, m_destY, m_destZ;
2657+ float m_elevation, m_speed;
2658 std::string m_strTarget;
2659
2660 uint32 m_targetMask;
2661@@ -342,6 +343,8 @@ class Spell
2662 void EffectPlayMusic(SpellEffectIndex eff_idx);
2663 void EffectSpecCount(SpellEffectIndex eff_idx);
2664 void EffectActivateSpec(SpellEffectIndex eff_idx);
2665+ void EffectSummonVehicle(SpellEffectIndex eff_idx);
2666+ void EffectDamageBuilding(SpellEffectIndex eff_idx);
2667
2668 Spell( Unit* caster, SpellEntry const *info, bool triggered, ObjectGuid originalCasterGUID = ObjectGuid(), Spell** triggeringContainer = NULL );
2669 ~Spell();
2670@@ -357,6 +360,8 @@ class Spell
2671
2672 SpellCastResult CheckCast(bool strict);
2673 SpellCastResult CheckPetCast(Unit* target);
2674+ bool IsValidSingleTargetEffect(Unit const* target, Targets type) const;
2675+ bool IsValidSingleTargetSpell(Unit const* target) const;
2676
2677 // handlers
2678 void handle_immediate();
2679diff --git a/src/game/SpellAuras.cpp b/src/game/SpellAuras.cpp
2680index 5ff4944..eae5df1 100644
2681--- a/src/game/SpellAuras.cpp
2682+++ b/src/game/SpellAuras.cpp
2683@@ -3282,7 +3282,7 @@ void Aura::HandleModPossess(bool apply, bool Real)
2684 {
2685 ((Creature*)target)->AIM_Initialize();
2686 }
2687- else if(target->GetTypeId() == TYPEID_PLAYER)
2688+ else if(target->GetTypeId() == TYPEID_PLAYER && !target->GetVehicleGUID())
2689 {
2690 ((Player*)target)->SetClientControl(target, 0);
2691 }
2692@@ -3313,7 +3313,7 @@ void Aura::HandleModPossess(bool apply, bool Real)
2693
2694 target->SetCharmerGUID(0);
2695
2696- if(target->GetTypeId() == TYPEID_PLAYER)
2697+ if(target->GetTypeId() == TYPEID_PLAYER && !target->GetVehicleGUID())
2698 {
2699 ((Player*)target)->setFactionForRace(target->getRace());
2700 ((Player*)target)->SetClientControl(target, 1);
2701@@ -3595,10 +3595,13 @@ void Aura::HandleAuraModStun(bool apply, bool Real)
2702 target->SetStandState(UNIT_STAND_STATE_STAND);// in 1.5 client
2703 }
2704
2705- WorldPacket data(SMSG_FORCE_MOVE_ROOT, 8);
2706- data << target->GetPackGUID();
2707- data << uint32(0);
2708- target->SendMessageToSet(&data, true);
2709+ if(!m_target->hasUnitState(UNIT_STAT_ON_VEHICLE))
2710+ {
2711+ WorldPacket data(SMSG_FORCE_MOVE_ROOT, 8);
2712+ data << target->GetPackGUID();
2713+ data << uint32(0);
2714+ target->SendMessageToSet(&data,true);
2715+ }
2716
2717 // Summon the Naj'entus Spine GameObject on target if spell is Impaling Spine
2718 if(GetId() == 39837)
2719@@ -3648,7 +3651,7 @@ void Aura::HandleAuraModStun(bool apply, bool Real)
2720 target->clearUnitState(UNIT_STAT_STUNNED);
2721 target->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_STUNNED);
2722
2723- if(!target->hasUnitState(UNIT_STAT_ROOT)) // prevent allow move if have also root effect
2724+ if(!target->hasUnitState(UNIT_STAT_ROOT | UNIT_STAT_ON_VEHICLE)) // prevent allow move if have also root effect
2725 {
2726 if(target->getVictim() && target->isAlive())
2727 target->SetTargetGUID(target->getVictim()->GetGUID());
2728@@ -3876,11 +3879,13 @@ void Aura::HandleAuraModRoot(bool apply, bool Real)
2729
2730 if(target->GetTypeId() == TYPEID_PLAYER)
2731 {
2732- WorldPacket data(SMSG_FORCE_MOVE_ROOT, 10);
2733- data << target->GetPackGUID();
2734- data << (uint32)2;
2735- target->SendMessageToSet(&data, true);
2736-
2737+ if(!target->hasUnitState(UNIT_STAT_ON_VEHICLE))
2738+ {
2739+ WorldPacket data(SMSG_FORCE_MOVE_ROOT, 10);
2740+ data << target->GetPackGUID();
2741+ data << (uint32)2;
2742+ target->SendMessageToSet(&data,true);
2743+ }
2744 //Clear unit movement flags
2745 ((Player*)target)->m_movementInfo.SetMovementFlags(MOVEFLAG_NONE);
2746 }
2747@@ -3918,7 +3923,7 @@ void Aura::HandleAuraModRoot(bool apply, bool Real)
2748
2749 target->clearUnitState(UNIT_STAT_ROOT);
2750
2751- if(!target->hasUnitState(UNIT_STAT_STUNNED)) // prevent allow move if have also stun effect
2752+ if(!target->hasUnitState(UNIT_STAT_STUNNED | UNIT_STAT_ON_VEHICLE)) // prevent allow move if have also stun effect
2753 {
2754 if(target->getVictim() && target->isAlive())
2755 target->SetTargetGUID(target->getVictim()->GetGUID());
2756@@ -3951,7 +3956,7 @@ void Aura::HandleAuraModSilence(bool apply, bool Real)
2757 if(spell->m_spellInfo->PreventionType == SPELL_PREVENTION_TYPE_SILENCE)
2758 // Stop spells on prepare or casting state
2759 target->InterruptSpell(CurrentSpellTypes(i), false);
2760- }
2761+ }
2762 else
2763 {
2764 // Real remove called after current aura remove from lists, check if other similar auras active
2765@@ -7317,32 +7322,40 @@ void Aura::HandleArenaPreparation(bool apply, bool Real)
2766 */
2767 void Aura::HandleAuraControlVehicle(bool apply, bool Real)
2768 {
2769- if(!Real)
2770- return;
2771+ if(!Real)
2772+ return;
2773
2774 Unit* target = GetTarget();
2775+ Unit* caster = GetCaster();
2776 if (target->GetTypeId() != TYPEID_UNIT || !((Creature*)target)->isVehicle())
2777 return;
2778 Vehicle* vehicle = (Vehicle*)target;
2779
2780- Unit *player = GetCaster();
2781- if(!player || player->GetTypeId() != TYPEID_PLAYER)
2782+ if(!caster || !vehicle)
2783+ return;
2784+
2785+ // this can happen due to wrong caster/target spell handling
2786+ // note : SPELL_AURA_CONTROL_VEHICLE can have EffectImplicitTargetA
2787+ // TARGET_SCRIPT, TARGET_DUELVSPLAYER.. etc
2788+ if(caster->GetGUID() == vehicle->GetGUID())
2789 return;
2790
2791 if (apply)
2792 {
2793- if(Pet *pet = player->GetPet())
2794- pet->Remove(PET_SAVE_AS_CURRENT);
2795- ((Player*)player)->EnterVehicle(vehicle);
2796+ if(caster->GetTypeId() == TYPEID_PLAYER)
2797+ {
2798+ WorldPacket data(SMSG_ON_CANCEL_EXPECTED_RIDE_VEHICLE_AURA, 0);
2799+ ((Player*)caster)->GetSession()->SendPacket(&data);
2800+ }
2801+ // if we leave and enter again, this will refresh
2802+ int32 duration = GetSpellMaxDuration(GetSpellProto());
2803+ if(duration > 0)
2804+ vehicle->SetSpawnDuration(duration);
2805 }
2806 else
2807 {
2808- SpellEntry const *spell = GetSpellProto();
2809-
2810 // some SPELL_AURA_CONTROL_VEHICLE auras have a dummy effect on the player - remove them
2811- player->RemoveAurasDueToSpell(spell->Id);
2812-
2813- ((Player*)player)->ExitVehicle(vehicle);
2814+ caster->RemoveAurasDueToSpell(GetId());
2815 }
2816 }
2817
2818diff --git a/src/game/SpellEffects.cpp b/src/game/SpellEffects.cpp
2819index 28ae6dc..a0c8613 100644
2820--- a/src/game/SpellEffects.cpp
2821+++ b/src/game/SpellEffects.cpp
2822@@ -57,6 +57,7 @@
2823 #include "GridNotifiers.h"
2824 #include "GridNotifiersImpl.h"
2825 #include "CellImpl.h"
2826+#include "Vehicle.h"
2827
2828 pEffect SpellEffects[TOTAL_SPELL_EFFECTS]=
2829 {
2830@@ -147,9 +148,9 @@ pEffect SpellEffects[TOTAL_SPELL_EFFECTS]=
2831 &Spell::EffectStuck, // 84 SPELL_EFFECT_STUCK
2832 &Spell::EffectSummonPlayer, // 85 SPELL_EFFECT_SUMMON_PLAYER
2833 &Spell::EffectActivateObject, // 86 SPELL_EFFECT_ACTIVATE_OBJECT
2834- &Spell::EffectNULL, // 87 SPELL_EFFECT_WMO_DAMAGE (57 spells in 3.3.2)
2835- &Spell::EffectNULL, // 88 SPELL_EFFECT_WMO_REPAIR (2 spells in 3.3.2)
2836- &Spell::EffectNULL, // 89 SPELL_EFFECT_WMO_CHANGE (7 spells in 3.3.2)
2837+ &Spell::EffectDamageBuilding, // 87 SPELL_EFFECT_WMO_DAMAGE
2838+ &Spell::EffectUnused, // 88 SPELL_EFFECT_WMO_REPAIR
2839+ &Spell::EffectUnused, // 89 SPELL_EFFECT_WMO_CHANGE
2840 &Spell::EffectKillCreditPersonal, // 90 SPELL_EFFECT_KILL_CREDIT Kill credit but only for single person
2841 &Spell::EffectUnused, // 91 SPELL_EFFECT_THREAT_ALL one spell: zzOLDBrainwash
2842 &Spell::EffectEnchantHeldItem, // 92 SPELL_EFFECT_ENCHANT_HELD_ITEM
2843@@ -3862,7 +3863,7 @@ void Spell::EffectSummonType(SpellEffectIndex eff_idx)
2844 case SUMMON_PROP_TYPE_SIEGE_VEH:
2845 case SUMMON_PROP_TYPE_DRAKE_VEH:
2846 // TODO
2847- // EffectSummonVehicle(i);
2848+ EffectSummonVehicle(eff_idx);
2849 break;
2850 default:
2851 sLog.outError("EffectSummonType: Unhandled summon type %u", summon_prop->Type);
2852@@ -3891,7 +3892,7 @@ void Spell::EffectSummonType(SpellEffectIndex eff_idx)
2853 case SUMMON_PROP_GROUP_VEHICLE:
2854 {
2855 // TODO
2856- // EffectSummonVehicle(i);
2857+ EffectSummonVehicle(eff_idx);
2858 break;
2859 }
2860 default:
2861@@ -3899,7 +3900,6 @@ void Spell::EffectSummonType(SpellEffectIndex eff_idx)
2862 break;
2863 }
2864 }
2865-
2866 void Spell::DoSummon(SpellEffectIndex eff_idx)
2867 {
2868 if (m_caster->GetPetGUID())
2869@@ -6519,13 +6519,15 @@ void Spell::EffectAddComboPoints(SpellEffectIndex /*eff_idx*/)
2870 if(!unitTarget)
2871 return;
2872
2873- if(m_caster->GetTypeId() != TYPEID_PLAYER)
2874- return;
2875-
2876 if(damage <= 0)
2877 return;
2878
2879- ((Player*)m_caster)->AddComboPoints(unitTarget, damage);
2880+ if(m_caster->GetTypeId() != TYPEID_PLAYER)
2881+ {
2882+ if(((Creature*)m_caster)->isVehicle())
2883+ ((Player*)m_caster->GetCharmer())->AddComboPoints(unitTarget, damage);
2884+ }else
2885+ ((Player*)m_caster)->AddComboPoints(unitTarget, damage);
2886 }
2887
2888 void Spell::EffectDuel(SpellEffectIndex eff_idx)
2889@@ -7789,6 +7791,54 @@ void Spell::EffectRenamePet(SpellEffectIndex /*eff_idx*/)
2890 unitTarget->RemoveByteFlag(UNIT_FIELD_BYTES_2, 2, UNIT_CAN_BE_RENAMED);
2891 }
2892
2893+void Spell::EffectSummonVehicle(SpellEffectIndex eff_idx)
2894+{
2895+ uint32 creature_entry = m_spellInfo->EffectMiscValue[eff_idx];
2896+ if(!creature_entry)
2897+ return;
2898+
2899+ float px, py, pz;
2900+ // If dest location if present
2901+ if (m_targets.m_targetMask & TARGET_FLAG_DEST_LOCATION)
2902+ {
2903+ // Summon unit in dest location
2904+ px = m_targets.m_destX;
2905+ py = m_targets.m_destY;
2906+ pz = m_targets.m_destZ;
2907+ }
2908+ // Summon if dest location not present near caster
2909+ else
2910+ m_caster->GetClosePoint(px,py,pz,3.0f);
2911+
2912+ Vehicle *v = m_caster->SummonVehicle(creature_entry, px, py, pz, m_caster->GetOrientation());
2913+ if(!v)
2914+ return;
2915+
2916+ v->SetUInt32Value(UNIT_CREATED_BY_SPELL, m_spellInfo->Id);
2917+ v->SetCreatorGUID(m_caster->GetGUID());
2918+
2919+ if(damage)
2920+ {
2921+ m_caster->CastSpell(v, damage, true);
2922+ m_caster->EnterVehicle(v, 0);
2923+ }
2924+ int32 duration = GetSpellMaxDuration(m_spellInfo);
2925+ if(duration > 0)
2926+ v->SetSpawnDuration(duration);
2927+}
2928+
2929+void Spell::EffectDamageBuilding(SpellEffectIndex eff_idx)
2930+{
2931+ if(!gameObjTarget)
2932+ return;
2933+
2934+ if(gameObjTarget->GetGoType() != GAMEOBJECT_TYPE_DESTRUCTIBLE_BUILDING)
2935+ return;
2936+
2937+ // NOTE : this can be increased by scaling stat system in vehicles
2938+ gameObjTarget->DealSiegeDamage(damage);
2939+}
2940+
2941 void Spell::EffectPlayMusic(SpellEffectIndex eff_idx)
2942 {
2943 if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
2944diff --git a/src/game/SpellHandler.cpp b/src/game/SpellHandler.cpp
2945index 41adfd3..ef7cda3 100644
2946--- a/src/game/SpellHandler.cpp
2947+++ b/src/game/SpellHandler.cpp
2948@@ -27,6 +27,7 @@
2949 #include "Spell.h"
2950 #include "ScriptCalls.h"
2951 #include "Totem.h"
2952+#include "Vehicle.h"
2953 #include "SpellAuras.h"
2954
2955 void WorldSession::HandleUseItemOpcode(WorldPacket& recvPacket)
2956@@ -320,6 +321,11 @@ void WorldSession::HandleCastSpellOpcode(WorldPacket& recvPacket)
2957 DEBUG_LOG("WORLD: got cast spell packet, spellId - %u, cast_count: %u, unk_flags %u, data length = %i",
2958 spellId, cast_count, unk_flags, (uint32)recvPacket.size());
2959
2960+ // vehicle spells are handled by CMSG_PET_CAST_SPELL,
2961+ // but player is still able to cast own spells
2962+ if(_player->GetCharmGUID() && _player->GetCharmGUID() == _player->GetVehicleGUID())
2963+ mover = _player;
2964+
2965 SpellEntry const *spellInfo = sSpellStore.LookupEntry(spellId );
2966
2967 if(!spellInfo)
2968@@ -486,7 +492,7 @@ void WorldSession::HandlePetCancelAuraOpcode( WorldPacket& recvPacket)
2969 return;
2970 }
2971
2972- Creature* pet = GetPlayer()->GetMap()->GetCreatureOrPetOrVehicle(guid);
2973+ Creature* pet=ObjectAccessor::GetCreatureOrPetOrVehicle(*_player,guid);
2974
2975 if(!pet)
2976 {
2977@@ -574,19 +580,67 @@ void WorldSession::HandleSpellClick( WorldPacket & recv_data )
2978 if (_player->isInCombat()) // client prevent click and set different icon at combat state
2979 return;
2980
2981- Creature *unit = _player->GetMap()->GetCreatureOrPetOrVehicle(guid);
2982+ Creature *unit = ObjectAccessor::GetCreatureOrPetOrVehicle(*_player, guid);
2983 if (!unit || unit->isInCombat()) // client prevent click and set different icon at combat state
2984 return;
2985
2986- SpellClickInfoMapBounds clickPair = sObjectMgr.GetSpellClickInfoMapBounds(unit->GetEntry());
2987- for(SpellClickInfoMap::const_iterator itr = clickPair.first; itr != clickPair.second; ++itr)
2988+ if(!_player->IsWithinDistInMap(unit, 10))
2989+ return;
2990+
2991+ // cheater?
2992+ if(!unit->HasFlag(UNIT_NPC_FLAGS,UNIT_NPC_FLAG_SPELLCLICK))
2993+ return;
2994+
2995+ uint32 vehicleId = 0;
2996+ CreatureDataAddon const *cainfo = unit->GetCreatureAddon();
2997+ if(cainfo)
2998+ vehicleId = cainfo->vehicle_id;
2999+
3000+ // handled other (hacky) way to avoid overwriting auras
3001+ if(vehicleId || unit->isVehicle())
3002+ {
3003+ if(!unit->isAlive())
3004+ return;
3005+
3006+ if(_player->GetVehicleGUID())
3007+ return;
3008+
3009+ // create vehicle if no one present and kill the original creature to avoid double, triple etc spawns
3010+ if(!unit->isVehicle())
3011+ {
3012+ Vehicle *v = _player->SummonVehicle(unit->GetEntry(), unit->GetPositionX(), unit->GetPositionY(), unit->GetPositionZ(), unit->GetOrientation(), vehicleId);
3013+ if(!v)
3014+ return;
3015+
3016+ if(v->GetVehicleFlags() & VF_DESPAWN_NPC)
3017+ {
3018+ v->SetSpawnDuration(unit->GetRespawnDelay()*IN_MILLISECONDS);
3019+ unit->setDeathState(JUST_DIED);
3020+ unit->RemoveCorpse();
3021+ unit->SetHealth(0);
3022+ }
3023+ unit = v;
3024+ }
3025+
3026+ if(((Vehicle*)unit)->GetVehicleData())
3027+ if(uint32 r_aura = ((Vehicle*)unit)->GetVehicleData()->req_aura)
3028+ if(!_player->HasAura(r_aura))
3029+ return;
3030+
3031+ _player->EnterVehicle((Vehicle*)unit, 0);
3032+ }
3033+ else
3034 {
3035- if (itr->second.IsFitToRequirements(_player))
3036+ SpellClickInfoMapBounds clickPair = sObjectMgr.GetSpellClickInfoMapBounds(unit->GetEntry());
3037+ for(SpellClickInfoMap::const_iterator itr = clickPair.first; itr != clickPair.second; ++itr)
3038 {
3039- Unit *caster = (itr->second.castFlags & 0x1) ? (Unit*)_player : (Unit*)unit;
3040- Unit *target = (itr->second.castFlags & 0x2) ? (Unit*)_player : (Unit*)unit;
3041+ if (itr->second.IsFitToRequirements(_player))
3042+ {
3043+ Unit *caster = (itr->second.castFlags & 0x1) ? (Unit*)_player : (Unit*)unit;
3044+ Unit *target = (itr->second.castFlags & 0x2) ? (Unit*)_player : (Unit*)unit;
3045
3046- caster->CastSpell(target, itr->second.spellId, true);
3047+ caster->CastSpell(target, itr->second.spellId, true);
3048+ }
3049 }
3050 }
3051 }
3052diff --git a/src/game/Unit.cpp b/src/game/Unit.cpp
3053index 3bb2b78..ec13a6f 100644
3054--- a/src/game/Unit.cpp
3055+++ b/src/game/Unit.cpp
3056@@ -46,6 +46,7 @@
3057 #include "CellImpl.h"
3058 #include "Path.h"
3059 #include "Traveller.h"
3060+#include "Vehicle.h"
3061 #include "VMapFactory.h"
3062 #include "MovementGenerator.h"
3063
3064@@ -242,6 +243,9 @@ Unit::Unit()
3065 // remove aurastates allowing special moves
3066 for(int i=0; i < MAX_REACTIVE; ++i)
3067 m_reactiveTimer[i] = 0;
3068+
3069+ m_auraUpdateMask = 0;
3070+ m_vehicleGUID = 0;
3071 }
3072
3073 Unit::~Unit()
3074@@ -411,20 +415,9 @@ void Unit::SendMonsterMoveWithSpeed(float x, float y, float z, uint32 transitTim
3075
3076 void Unit::BuildHeartBeatMsg(WorldPacket *data) const
3077 {
3078- MovementFlags move_flags = GetTypeId()==TYPEID_PLAYER
3079- ? ((Player const*)this)->m_movementInfo.GetMovementFlags()
3080- : MOVEFLAG_NONE;
3081-
3082- data->Initialize(MSG_MOVE_HEARTBEAT, 32);
3083+ data->Initialize(MSG_MOVE_HEARTBEAT);
3084 *data << GetPackGUID();
3085- *data << uint32(move_flags); // movement flags
3086- *data << uint16(0); // 2.3.0
3087- *data << uint32(getMSTime()); // time
3088- *data << float(GetPositionX());
3089- *data << float(GetPositionY());
3090- *data << float(GetPositionZ());
3091- *data << float(GetOrientation());
3092- *data << uint32(0);
3093+ ((Unit*)this)->m_movementInfo.Write(*data);
3094 }
3095
3096 void Unit::resetAttackTimer(WeaponAttackType type)
3097@@ -5097,15 +5090,10 @@ void Unit::setPowerType(Powers new_powertype)
3098 if(((Player*)this)->GetGroup())
3099 ((Player*)this)->SetGroupUpdateFlag(GROUP_UPDATE_FLAG_POWER_TYPE);
3100 }
3101- else if(((Creature*)this)->isPet())
3102+ else if(Unit* owner = GetCharmerOrOwner())
3103 {
3104- Pet *pet = ((Pet*)this);
3105- if(pet->isControlled())
3106- {
3107- Unit *owner = GetOwner();
3108- if(owner && (owner->GetTypeId() == TYPEID_PLAYER) && ((Player*)owner)->GetGroup())
3109- ((Player*)owner)->SetGroupUpdateFlag(GROUP_UPDATE_FLAG_PET_POWER_TYPE);
3110- }
3111+ if((owner->GetTypeId() == TYPEID_PLAYER) && ((Player*)owner)->GetGroup())
3112+ ((Player*)owner)->SetGroupUpdateFlag(GROUP_UPDATE_FLAG_PET_POWER_TYPE);
3113 }
3114
3115 switch(new_powertype)
3116@@ -5262,6 +5250,38 @@ bool Unit::IsHostileTo(Unit const* unit) const
3117 return tester_faction->IsHostileTo(*target_faction);
3118 }
3119
3120+bool Unit::IsInPartyWith(Unit const *unit) const
3121+{
3122+ if(this == unit)
3123+ return true;
3124+
3125+ const Unit *u1 = GetCharmerOrOwnerOrSelf();
3126+ const Unit *u2 = unit->GetCharmerOrOwnerOrSelf();
3127+ if(u1 == u2)
3128+ return true;
3129+
3130+ if(u1->GetTypeId() == TYPEID_PLAYER && u2->GetTypeId() == TYPEID_PLAYER)
3131+ return ((Player*)u1)->IsInSameGroupWith((Player*)u2);
3132+ else
3133+ return false;
3134+}
3135+
3136+bool Unit::IsInRaidWith(Unit const *unit) const
3137+{
3138+ if(this == unit)
3139+ return true;
3140+
3141+ const Unit *u1 = GetCharmerOrOwnerOrSelf();
3142+ const Unit *u2 = unit->GetCharmerOrOwnerOrSelf();
3143+ if(u1 == u2)
3144+ return true;
3145+
3146+ if(u1->GetTypeId() == TYPEID_PLAYER && u2->GetTypeId() == TYPEID_PLAYER)
3147+ return ((Player*)u1)->IsInSameRaidWith((Player*)u2);
3148+ else
3149+ return false;
3150+}
3151+
3152 bool Unit::IsFriendlyTo(Unit const* unit) const
3153 {
3154 // always friendly to self
3155@@ -5413,6 +5433,14 @@ bool Unit::Attack(Unit *victim, bool meleeAttack)
3156 if(GetTypeId()==TYPEID_PLAYER && IsMounted())
3157 return false;
3158
3159+ // player (also npc?) cannot attack on vehicle
3160+ if(GetTypeId()==TYPEID_PLAYER && GetVehicleGUID())
3161+ return false;
3162+
3163+ // player (also npc?) cannot attack on vehicle
3164+ if(GetTypeId()==TYPEID_UNIT && ((Creature*)this)->isVehicle() && GetCharmerGUID())
3165+ return false;
3166+
3167 // nobody can attack GM in GM-mode
3168 if(victim->GetTypeId()==TYPEID_PLAYER)
3169 {
3170@@ -7974,6 +8002,11 @@ void Unit::UpdateSpeed(UnitMoveType mtype, bool forced, float ratio)
3171 }
3172
3173 float bonus = non_stack_bonus > stack_bonus ? non_stack_bonus : stack_bonus;
3174+
3175+ //apply creature's base speed
3176+ if(GetTypeId() == TYPEID_UNIT)
3177+ bonus *= ((Creature*)this)->GetBaseSpeed();
3178+
3179 // now we ready for speed calculation
3180 float speed = main_speed_mod ? bonus*(100.0f + main_speed_mod)/100.0f : bonus;
3181
3182@@ -8170,6 +8203,7 @@ void Unit::setDeathState(DeathState s)
3183
3184 if (s == JUST_DIED)
3185 {
3186+ ExitVehicle();
3187 RemoveAllAurasOnDeath();
3188 RemoveGuardians();
3189 UnsummonAllTotems();
3190@@ -8395,7 +8429,8 @@ bool Unit::SelectHostileTarget()
3191 }
3192
3193 // enter in evade mode in other case
3194- ((Creature*)this)->AI()->EnterEvadeMode();
3195+ if(!((Creature*)this)->isVehicle())
3196+ ((Creature*)this)->AI()->EnterEvadeMode();
3197
3198 return false;
3199 }
3200@@ -8406,7 +8441,14 @@ bool Unit::SelectHostileTarget()
3201
3202 int32 Unit::CalculateSpellDamage(Unit const* target, SpellEntry const* spellProto, SpellEffectIndex effect_index, int32 const* effBasePoints)
3203 {
3204- Player* unitPlayer = (GetTypeId() == TYPEID_PLAYER) ? (Player*)this : NULL;
3205+ Player* unitPlayer;
3206+
3207+ if(GetTypeId() == TYPEID_PLAYER)
3208+ unitPlayer = (Player*)this;
3209+ else if(((Creature*)this)->isVehicle())
3210+ unitPlayer = (Player*)GetCharmer();
3211+ else
3212+ unitPlayer = NULL;
3213
3214 uint8 comboPoints = unitPlayer ? unitPlayer->GetComboPoints() : 0;
3215
3216@@ -8471,7 +8513,14 @@ int32 Unit::CalculateSpellDamage(Unit const* target, SpellEntry const* spellProt
3217
3218 int32 Unit::CalculateSpellDuration(SpellEntry const* spellProto, SpellEffectIndex effect_index, Unit const* target)
3219 {
3220- Player* unitPlayer = (GetTypeId() == TYPEID_PLAYER) ? (Player*)this : NULL;
3221+ Player* unitPlayer;
3222+
3223+ if(GetTypeId() == TYPEID_PLAYER)
3224+ unitPlayer = (Player*)this;
3225+ else if(((Creature*)this)->isVehicle())
3226+ unitPlayer = (Player*)GetCharmer();
3227+ else
3228+ unitPlayer = NULL;
3229
3230 uint8 comboPoints = unitPlayer ? unitPlayer->GetComboPoints() : 0;
3231
3232@@ -8881,15 +8930,10 @@ void Unit::SetHealth(uint32 val)
3233 if(((Player*)this)->GetGroup())
3234 ((Player*)this)->SetGroupUpdateFlag(GROUP_UPDATE_FLAG_CUR_HP);
3235 }
3236- else if(((Creature*)this)->isPet())
3237+ else if(Unit* owner = GetCharmerOrOwner())
3238 {
3239- Pet *pet = ((Pet*)this);
3240- if(pet->isControlled())
3241- {
3242- Unit *owner = GetOwner();
3243- if(owner && (owner->GetTypeId() == TYPEID_PLAYER) && ((Player*)owner)->GetGroup())
3244- ((Player*)owner)->SetGroupUpdateFlag(GROUP_UPDATE_FLAG_PET_CUR_HP);
3245- }
3246+ if((owner->GetTypeId() == TYPEID_PLAYER) && ((Player*)owner)->GetGroup())
3247+ ((Player*)owner)->SetGroupUpdateFlag(GROUP_UPDATE_FLAG_PET_CUR_HP);
3248 }
3249 }
3250
3251@@ -8904,15 +8948,10 @@ void Unit::SetMaxHealth(uint32 val)
3252 if(((Player*)this)->GetGroup())
3253 ((Player*)this)->SetGroupUpdateFlag(GROUP_UPDATE_FLAG_MAX_HP);
3254 }
3255- else if(((Creature*)this)->isPet())
3256+ else if(Unit* owner = GetCharmerOrOwner())
3257 {
3258- Pet *pet = ((Pet*)this);
3259- if(pet->isControlled())
3260- {
3261- Unit *owner = GetOwner();
3262- if(owner && (owner->GetTypeId() == TYPEID_PLAYER) && ((Player*)owner)->GetGroup())
3263- ((Player*)owner)->SetGroupUpdateFlag(GROUP_UPDATE_FLAG_PET_MAX_HP);
3264- }
3265+ if((owner->GetTypeId() == TYPEID_PLAYER) && ((Player*)owner)->GetGroup())
3266+ ((Player*)owner)->SetGroupUpdateFlag(GROUP_UPDATE_FLAG_PET_MAX_HP);
3267 }
3268
3269 if(val < health)
3270@@ -8948,20 +8987,19 @@ void Unit::SetPower(Powers power, uint32 val)
3271 if(((Player*)this)->GetGroup())
3272 ((Player*)this)->SetGroupUpdateFlag(GROUP_UPDATE_FLAG_CUR_POWER);
3273 }
3274- else if(((Creature*)this)->isPet())
3275+ else if(Unit* owner = GetCharmerOrOwner())
3276 {
3277- Pet *pet = ((Pet*)this);
3278- if(pet->isControlled())
3279- {
3280- Unit *owner = GetOwner();
3281- if(owner && (owner->GetTypeId() == TYPEID_PLAYER) && ((Player*)owner)->GetGroup())
3282- ((Player*)owner)->SetGroupUpdateFlag(GROUP_UPDATE_FLAG_PET_CUR_POWER);
3283- }
3284+ if((owner->GetTypeId() == TYPEID_PLAYER) && ((Player*)owner)->GetGroup())
3285+ ((Player*)owner)->SetGroupUpdateFlag(GROUP_UPDATE_FLAG_PET_CUR_POWER);
3286
3287- // Update the pet's character sheet with happiness damage bonus
3288- if(pet->getPetType() == HUNTER_PET && power == POWER_HAPPINESS)
3289+ if(((Creature*)this)->isPet())
3290 {
3291- pet->UpdateDamagePhysical(BASE_ATTACK);
3292+ Pet *pet = ((Pet*)this);
3293+ // Update the pet's character sheet with happiness damage bonus
3294+ if(pet->getPetType() == HUNTER_PET && power == POWER_HAPPINESS)
3295+ {
3296+ pet->UpdateDamagePhysical(BASE_ATTACK);
3297+ }
3298 }
3299 }
3300 }
3301@@ -8977,15 +9015,10 @@ void Unit::SetMaxPower(Powers power, uint32 val)
3302 if(((Player*)this)->GetGroup())
3303 ((Player*)this)->SetGroupUpdateFlag(GROUP_UPDATE_FLAG_MAX_POWER);
3304 }
3305- else if(((Creature*)this)->isPet())
3306+ else if(Unit* owner = GetCharmerOrOwner())
3307 {
3308- Pet *pet = ((Pet*)this);
3309- if(pet->isControlled())
3310- {
3311- Unit *owner = GetOwner();
3312- if(owner && (owner->GetTypeId() == TYPEID_PLAYER) && ((Player*)owner)->GetGroup())
3313- ((Player*)owner)->SetGroupUpdateFlag(GROUP_UPDATE_FLAG_PET_MAX_POWER);
3314- }
3315+ if((owner->GetTypeId() == TYPEID_PLAYER) && ((Player*)owner)->GetGroup())
3316+ ((Player*)owner)->SetGroupUpdateFlag(GROUP_UPDATE_FLAG_PET_MAX_POWER);
3317 }
3318
3319 if(val < cur_power)
3320@@ -9002,15 +9035,10 @@ void Unit::ApplyPowerMod(Powers power, uint32 val, bool apply)
3321 if(((Player*)this)->GetGroup())
3322 ((Player*)this)->SetGroupUpdateFlag(GROUP_UPDATE_FLAG_CUR_POWER);
3323 }
3324- else if(((Creature*)this)->isPet())
3325+ else if(Unit* owner = GetCharmerOrOwner())
3326 {
3327- Pet *pet = ((Pet*)this);
3328- if(pet->isControlled())
3329- {
3330- Unit *owner = GetOwner();
3331- if(owner && (owner->GetTypeId() == TYPEID_PLAYER) && ((Player*)owner)->GetGroup())
3332- ((Player*)owner)->SetGroupUpdateFlag(GROUP_UPDATE_FLAG_PET_CUR_POWER);
3333- }
3334+ if((owner->GetTypeId() == TYPEID_PLAYER) && ((Player*)owner)->GetGroup())
3335+ ((Player*)owner)->SetGroupUpdateFlag(GROUP_UPDATE_FLAG_PET_CUR_POWER);
3336 }
3337 }
3338
3339@@ -9024,15 +9052,10 @@ void Unit::ApplyMaxPowerMod(Powers power, uint32 val, bool apply)
3340 if(((Player*)this)->GetGroup())
3341 ((Player*)this)->SetGroupUpdateFlag(GROUP_UPDATE_FLAG_MAX_POWER);
3342 }
3343- else if(((Creature*)this)->isPet())
3344+ else if(Unit* owner = GetCharmerOrOwner())
3345 {
3346- Pet *pet = ((Pet*)this);
3347- if(pet->isControlled())
3348- {
3349- Unit *owner = GetOwner();
3350- if(owner && (owner->GetTypeId() == TYPEID_PLAYER) && ((Player*)owner)->GetGroup())
3351- ((Player*)owner)->SetGroupUpdateFlag(GROUP_UPDATE_FLAG_PET_MAX_POWER);
3352- }
3353+ if((owner->GetTypeId() == TYPEID_PLAYER) && ((Player*)owner)->GetGroup())
3354+ ((Player*)owner)->SetGroupUpdateFlag(GROUP_UPDATE_FLAG_PET_MAX_POWER);
3355 }
3356 }
3357
3358@@ -9087,6 +9110,7 @@ void Unit::RemoveFromWorld()
3359
3360 void Unit::CleanupsBeforeDelete()
3361 {
3362+ ExitVehicle(); // make sure we always leave vehicle, otherwise it will crash
3363 if(m_uint32Values) // only for fully created object
3364 {
3365 InterruptNonMeleeSpells(true);
3366@@ -9662,8 +9686,12 @@ void Unit::SetFeared(bool apply, uint64 const& casterGUID, uint32 spellID, uint3
3367 }
3368 }
3369
3370- if (GetTypeId() == TYPEID_PLAYER)
3371+ if (GetTypeId() == TYPEID_PLAYER && !GetVehicleGUID())
3372 ((Player*)this)->SetClientControl(this, !apply);
3373+
3374+ if (Unit* owner = GetCharmer())
3375+ if (owner->GetTypeId() == TYPEID_PLAYER)
3376+ ((Player*)owner)->SetClientControl(this, !apply);
3377 }
3378
3379 void Unit::SetConfused(bool apply, uint64 const& casterGUID, uint32 spellID)
3380@@ -9692,8 +9720,12 @@ void Unit::SetConfused(bool apply, uint64 const& casterGUID, uint32 spellID)
3381 }
3382 }
3383
3384- if(GetTypeId() == TYPEID_PLAYER)
3385+ if(GetTypeId() == TYPEID_PLAYER && !GetVehicleGUID())
3386 ((Player*)this)->SetClientControl(this, !apply);
3387+
3388+ if (Unit* owner = GetCharmer())
3389+ if (owner->GetTypeId() == TYPEID_PLAYER)
3390+ ((Player*)owner)->SetClientControl(this, !apply);
3391 }
3392
3393 void Unit::SetFeignDeath(bool apply, uint64 const& casterGUID, uint32 /*spellID*/)
3394@@ -9797,17 +9829,12 @@ void Unit::SetDisplayId(uint32 modelId)
3395 {
3396 SetUInt32Value(UNIT_FIELD_DISPLAYID, modelId);
3397
3398- UpdateModelData();
3399+ UpdateModelData();
3400
3401- if(GetTypeId() == TYPEID_UNIT && ((Creature*)this)->isPet())
3402- {
3403- Pet *pet = ((Pet*)this);
3404- if(!pet->isControlled())
3405- return;
3406- Unit *owner = GetOwner();
3407- if(owner && (owner->GetTypeId() == TYPEID_PLAYER) && ((Player*)owner)->GetGroup())
3408+ if(Unit *owner = GetCharmerOrOwner())
3409+ if((owner->GetTypeId() == TYPEID_PLAYER) && ((Player*)owner)->GetGroup())
3410 ((Player*)owner)->SetGroupUpdateFlag(GROUP_UPDATE_FLAG_PET_MODEL_ID);
3411- }
3412+
3413 }
3414
3415 void Unit::UpdateModelData()
3416@@ -10009,16 +10036,14 @@ void Unit::UpdateAuraForGroup(uint8 slot)
3417 player->SetAuraUpdateMask(slot);
3418 }
3419 }
3420- else if(GetTypeId() == TYPEID_UNIT && ((Creature*)this)->isPet())
3421+ else if(GetTypeId() == TYPEID_UNIT)
3422 {
3423- Pet *pet = ((Pet*)this);
3424- if(pet->isControlled())
3425+ if(Unit *owner = GetCharmerOrOwner())
3426 {
3427- Unit *owner = GetOwner();
3428- if(owner && (owner->GetTypeId() == TYPEID_PLAYER) && ((Player*)owner)->GetGroup())
3429+ if((owner->GetTypeId() == TYPEID_PLAYER) && ((Player*)owner)->GetGroup())
3430 {
3431 ((Player*)owner)->SetGroupUpdateFlag(GROUP_UPDATE_FLAG_PET_AURAS);
3432- pet->SetAuraUpdateMask(slot);
3433+ SetAuraUpdateMask(slot);
3434 }
3435 }
3436 }
3437@@ -10187,6 +10212,7 @@ void Unit::NearTeleportTo( float x, float y, float z, float orientation, bool ca
3438 ((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));
3439 else
3440 {
3441+ ExitVehicle();
3442 Creature* c = (Creature*)this;
3443 // Creature relocation acts like instant movement generator, so current generator expects interrupt/reset calls to react properly
3444 if (!c->GetMotionMaster()->empty())
3445@@ -10258,6 +10284,123 @@ struct SetPvPHelper
3446 bool state;
3447 };
3448
3449+void Unit::ChangeSeat(int8 seatId, bool next)
3450+{
3451+ Vehicle *m_vehicle = ObjectAccessor::GetVehicle(GetVehicleGUID());
3452+
3453+ if (!m_vehicle)
3454+ return;
3455+
3456+ if (seatId < 0)
3457+ {
3458+ seatId = m_vehicle->GetNextEmptySeatNum(m_movementInfo.GetTransportSeat(), next);
3459+ if (seatId < 0)
3460+ return;
3461+ }
3462+ else if (seatId == m_movementInfo.GetTransportSeat() || !m_vehicle->HasEmptySeat(seatId))
3463+ return;
3464+
3465+ m_vehicle->RemovePassenger(this);
3466+ EnterVehicle(m_vehicle, seatId);
3467+}
3468+
3469+void Unit::EnterVehicle(Vehicle *vehicle, int8 seat_id, bool force)
3470+{
3471+ // dont allow multiple vehicles
3472+ ExitVehicle();
3473+
3474+ RemoveSpellsCausingAura(SPELL_AURA_MOUNTED);
3475+ // NOTE : shapeshift too?
3476+
3477+ Vehicle *v = vehicle->FindFreeSeat(&seat_id, force);
3478+ if(!v)
3479+ return;
3480+
3481+ VehicleEntry const *ve = sVehicleStore.LookupEntry(v->GetVehicleId());
3482+ if(!ve)
3483+ return;
3484+
3485+ VehicleSeatEntry const *veSeat = sVehicleSeatStore.LookupEntry(ve->m_seatID[seat_id]);
3486+ if(!veSeat)
3487+ return;
3488+
3489+ m_movementInfo.SetTransportData(v->GetGUID(),
3490+ (veSeat->m_attachmentOffsetX + v->GetObjectSize()) * GetFloatValue(OBJECT_FIELD_SCALE_X),
3491+ (veSeat->m_attachmentOffsetY + v->GetObjectSize()) * GetFloatValue(OBJECT_FIELD_SCALE_X),
3492+ (veSeat->m_attachmentOffsetZ + v->GetObjectSize()) * GetFloatValue(OBJECT_FIELD_SCALE_X),
3493+ veSeat->m_passengerYaw, v->GetCreationTime(), seat_id, veSeat->m_ID,
3494+ sObjectMgr.GetSeatFlags(veSeat->m_ID), v->GetVehicleFlags());
3495+
3496+ m_movementInfo.AddMovementFlag(MOVEFLAG_ONTRANSPORT);
3497+
3498+ addUnitState(UNIT_STAT_ON_VEHICLE);
3499+ InterruptNonMeleeSpells(false);
3500+
3501+ if(Pet *pet = GetPet())
3502+ pet->Remove(PET_SAVE_AS_CURRENT);
3503+
3504+ if(GetTypeId() == TYPEID_PLAYER)
3505+ ((Player*)this)->SendEnterVehicle(v);
3506+
3507+ WorldPacket data(SMSG_MONSTER_MOVE_TRANSPORT, 60);
3508+ data << GetPackGUID();
3509+ data << v->GetPackGUID();
3510+ data << uint8(seat_id);
3511+ data << uint8(0); // new in 3.1
3512+ data << v->GetPositionX() << v->GetPositionY() << v->GetPositionZ();
3513+ data << uint32(getMSTime());
3514+
3515+ data << uint8(4); // unknown
3516+ data << float(0); // facing angle
3517+
3518+ data << uint32(SPLINEFLAG_UNKNOWN5);
3519+
3520+ data << uint32(0); // Time in between points
3521+ data << uint32(1); // 1 single waypoint
3522+ data << m_movementInfo.GetTransportPos()->x;
3523+ data << m_movementInfo.GetTransportPos()->y;
3524+ data << m_movementInfo.GetTransportPos()->z;
3525+ SendMessageToSet(&data, true);
3526+
3527+ v->AddPassenger(this, seat_id, force);
3528+}
3529+
3530+void Unit::ExitVehicle()
3531+{
3532+ if(uint64 vehicleGUID = GetVehicleGUID())
3533+ {
3534+ float v_size = 0.0f;
3535+ if(Vehicle *vehicle = ObjectAccessor::GetVehicle(vehicleGUID))
3536+ {
3537+ if(m_movementInfo.GetVehicleSeatFlags() & SF_MAIN_RIDER)
3538+ {
3539+ if(vehicle->GetVehicleFlags() & VF_DESPAWN_AT_LEAVE)
3540+ {
3541+ // will be deleted at next update
3542+ vehicle->SetSpawnDuration(1);
3543+ }
3544+ }
3545+ v_size = vehicle->GetObjectSize();
3546+ vehicle->RemovePassenger(this);
3547+ }
3548+ SetVehicleGUID(0);
3549+
3550+ clearUnitState(UNIT_STAT_ON_VEHICLE);
3551+
3552+ if(GetTypeId() == TYPEID_PLAYER)
3553+ {
3554+ ((Player*)this)->ResummonPetTemporaryUnSummonedIfAny();
3555+ ((Player*)this)->m_movementInfo.RemoveMovementFlag(MOVEFLAG_ROOT);
3556+ }
3557+
3558+ float x = GetPositionX();
3559+ float y = GetPositionY();
3560+ float z = GetPositionZ() + 2.0f;
3561+ GetClosePoint(x, y, z, 2.0f + v_size);
3562+ SendMonsterMove(x, y, z, SPLINETYPE_NORMAL, SPLINEFLAG_WALKMODE, 0);
3563+ }
3564+}
3565+
3566 void Unit::SetPvP( bool state )
3567 {
3568 if(state)
3569@@ -10478,4 +10621,4 @@ SpellAuraHolder* Unit::GetSpellAuraHolder (uint32 spellid, uint64 casterGUID)
3570 return iter->second;
3571
3572 return NULL;
3573-}
3574+}
3575\ No newline at end of file
3576diff --git a/src/game/Unit.h b/src/game/Unit.h
3577index 35c3767..86aedb6 100644
3578--- a/src/game/Unit.h
3579+++ b/src/game/Unit.h
3580@@ -303,6 +303,7 @@ class Item;
3581 class Pet;
3582 class PetAura;
3583 class Totem;
3584+class Vehicle;
3585
3586 struct SpellImmune
3587 {
3588@@ -440,24 +441,25 @@ enum UnitState
3589 UNIT_STAT_FOLLOW_MOVE = 0x00010000,
3590 UNIT_STAT_FLEEING = 0x00020000, // FleeMovementGenerator/TimedFleeingMovementGenerator active/onstack
3591 UNIT_STAT_FLEEING_MOVE = 0x00040000,
3592+ UNIT_STAT_ON_VEHICLE = 0x00080000,
3593
3594 // masks (only for check)
3595
3596 // can't move currently
3597- UNIT_STAT_CAN_NOT_MOVE = UNIT_STAT_ROOT | UNIT_STAT_STUNNED | UNIT_STAT_DIED,
3598+ UNIT_STAT_CAN_NOT_MOVE = UNIT_STAT_ROOT | UNIT_STAT_STUNNED | UNIT_STAT_DIED | UNIT_STAT_ON_VEHICLE,
3599
3600 // stay by different reasons
3601 UNIT_STAT_NOT_MOVE = UNIT_STAT_ROOT | UNIT_STAT_STUNNED | UNIT_STAT_DIED |
3602- UNIT_STAT_DISTRACTED,
3603+ UNIT_STAT_DISTRACTED | UNIT_STAT_ON_VEHICLE,
3604
3605 // stay or scripted movement for effect( = in player case you can't move by client command)
3606 UNIT_STAT_NO_FREE_MOVE = UNIT_STAT_ROOT | UNIT_STAT_STUNNED | UNIT_STAT_DIED |
3607 UNIT_STAT_IN_FLIGHT |
3608- UNIT_STAT_CONFUSED | UNIT_STAT_FLEEING,
3609+ UNIT_STAT_CONFUSED | UNIT_STAT_FLEEING | UNIT_STAT_ON_VEHICLE,
3610
3611 // not react at move in sight or other
3612 UNIT_STAT_CAN_NOT_REACT = UNIT_STAT_STUNNED | UNIT_STAT_DIED |
3613- UNIT_STAT_CONFUSED | UNIT_STAT_FLEEING,
3614+ UNIT_STAT_CONFUSED | UNIT_STAT_FLEEING | UNIT_STAT_ON_VEHICLE,
3615
3616 // AI disabled by some reason
3617 UNIT_STAT_LOST_CONTROL = UNIT_STAT_FLEEING | UNIT_STAT_CONTROLLED,
3618@@ -767,7 +769,7 @@ class MovementInfo
3619
3620 // Position manipulations
3621 Position const *GetPos() const { return &pos; }
3622- void SetTransportData(ObjectGuid guid, float x, float y, float z, float o, uint32 time, int8 seat)
3623+ 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)
3624 {
3625 t_guid = guid;
3626 t_pos.x = x;
3627@@ -776,6 +778,9 @@ class MovementInfo
3628 t_pos.o = o;
3629 t_time = time;
3630 t_seat = seat;
3631+ t_dbc_seat = dbc_seat;
3632+ t_seat_flags = seat_flags;
3633+ t_vehicle_flags = vehicle_flags;
3634 }
3635 void ClearTransportData()
3636 {
3637@@ -786,11 +791,17 @@ class MovementInfo
3638 t_pos.o = 0.0f;
3639 t_time = 0;
3640 t_seat = -1;
3641+ t_dbc_seat = 0;
3642+ t_seat_flags = 0;
3643+ t_vehicle_flags = 0;
3644 }
3645 ObjectGuid const& GetTransportGuid() const { return t_guid; }
3646 Position const *GetTransportPos() const { return &t_pos; }
3647 int8 GetTransportSeat() const { return t_seat; }
3648 uint32 GetTransportTime() const { return t_time; }
3649+ uint32 GetTransportDBCSeat() const { return t_dbc_seat; }
3650+ uint32 GetVehicleSeatFlags() const { return t_seat_flags; }
3651+ uint32 GetVehicleFlags() const { return t_vehicle_flags; }
3652 uint32 GetFallTime() const { return fallTime; }
3653 void ChangePosition(float x, float y, float z, float o) { pos.x = x; pos.y = y; pos.z = z; pos.o = o; }
3654 void UpdateTime(uint32 _time) { time = _time; }
3655@@ -807,6 +818,9 @@ class MovementInfo
3656 uint32 t_time;
3657 int8 t_seat;
3658 uint32 t_time2;
3659+ uint32 t_dbc_seat;
3660+ uint32 t_seat_flags;
3661+ uint32 t_vehicle_flags;
3662 // swimming and flying
3663 float s_pitch;
3664 // last fall time
3665@@ -1230,6 +1244,8 @@ class MANGOS_DLL_SPEC Unit : public WorldObject
3666 bool IsHostileTo(Unit const* unit) const;
3667 bool IsHostileToPlayers() const;
3668 bool IsFriendlyTo(Unit const* unit) const;
3669+ bool IsInRaidWith(Unit const* unit) const;
3670+ bool IsInPartyWith(Unit const* unit) const;
3671 bool IsNeutralToAll() const;
3672 bool IsContestedGuard() const
3673 {
3674@@ -1365,6 +1381,10 @@ class MANGOS_DLL_SPEC Unit : public WorldObject
3675 return m_spellAuraHolders.find(spellId) != m_spellAuraHolders.end();
3676 }
3677
3678+ const uint64& GetAuraUpdateMask() const { return m_auraUpdateMask; }
3679+ void SetAuraUpdateMask(uint8 slot) { m_auraUpdateMask |= (uint64(1) << slot); }
3680+ void ResetAuraUpdateMask() { m_auraUpdateMask = 0; }
3681+
3682 bool virtual HasSpell(uint32 /*spellID*/) const { return false; }
3683
3684 bool HasStealthAura() const { return HasAuraType(SPELL_AURA_MOD_STEALTH); }
3685@@ -1465,12 +1485,13 @@ class MANGOS_DLL_SPEC Unit : public WorldObject
3686 Unit* GetCharm() const;
3687 void Uncharm();
3688 Unit* GetCharmerOrOwner() const { return GetCharmerGUID() ? GetCharmer() : GetOwner(); }
3689- Unit* GetCharmerOrOwnerOrSelf()
3690+ Unit* GetCharmOrPet() const { return GetCharmGUID() ? GetCharm() : (Unit*)GetPet(); }
3691+ Unit* GetCharmerOrOwnerOrSelf() const
3692 {
3693 if(Unit* u = GetCharmerOrOwner())
3694 return u;
3695
3696- return this;
3697+ return (Unit*)this;
3698 }
3699 bool IsCharmerOrOwnerPlayerOrPlayerItself() const;
3700 Player* GetCharmerOrOwnerPlayerOrPlayerItself();
3701@@ -1876,6 +1897,13 @@ class MANGOS_DLL_SPEC Unit : public WorldObject
3702 // Movement info
3703 MovementInfo m_movementInfo;
3704
3705+ // vehicle system
3706+ void EnterVehicle(Vehicle *vehicle, int8 seat_id, bool force = false);
3707+ void ExitVehicle();
3708+ uint64 GetVehicleGUID() { return m_vehicleGUID; }
3709+ void SetVehicleGUID(uint64 guid) { m_vehicleGUID = guid; }
3710+ void ChangeSeat(int8 seatId, bool next);
3711+
3712 protected:
3713 explicit Unit ();
3714
3715@@ -1924,6 +1952,8 @@ class MANGOS_DLL_SPEC Unit : public WorldObject
3716 uint32 m_reactiveTimer[MAX_REACTIVE];
3717 uint32 m_regenTimer;
3718 uint32 m_lastManaUseTimer;
3719+ uint64 m_auraUpdateMask;
3720+ uint64 m_vehicleGUID;
3721
3722 private:
3723 void CleanupDeletedAuras();
3724diff --git a/src/game/Vehicle.cpp b/src/game/Vehicle.cpp
3725index b92e542..a0df6ab 100644
3726--- a/src/game/Vehicle.cpp
3727+++ b/src/game/Vehicle.cpp
3728@@ -18,12 +18,14 @@
3729
3730 #include "Common.h"
3731 #include "Log.h"
3732-#include "ObjectMgr.h"
3733 #include "Vehicle.h"
3734 #include "Unit.h"
3735 #include "Util.h"
3736+#include "WorldPacket.h"
3737+#include "InstanceData.h"
3738
3739-Vehicle::Vehicle() : Creature(CREATURE_SUBTYPE_VEHICLE), m_vehicleId(0)
3740+Vehicle::Vehicle() : Creature(CREATURE_SUBTYPE_VEHICLE), m_vehicleId(0), m_vehicleInfo(NULL), m_spawnduration(0),
3741+ despawn(false), m_creation_time(0), m_VehicleData(NULL)
3742 {
3743 m_updateFlag = (UPDATEFLAG_LIVING | UPDATEFLAG_HAS_POSITION | UPDATEFLAG_VEHICLE);
3744 }
3745@@ -51,45 +53,721 @@ void Vehicle::RemoveFromWorld()
3746 Unit::RemoveFromWorld();
3747 }
3748
3749+void Vehicle::Respawn()
3750+{
3751+ Creature::Respawn();
3752+ InstallAllAccessories();
3753+}
3754+
3755 void Vehicle::setDeathState(DeathState s) // overwrite virtual Creature::setDeathState and Unit::setDeathState
3756 {
3757 Creature::setDeathState(s);
3758+ if(s == JUST_DIED)
3759+ {
3760+ if(GetVehicleFlags() & VF_DESPAWN_NPC)
3761+ Dismiss();
3762+ else
3763+ RemoveAllPassengers();
3764+ }
3765 }
3766
3767 void Vehicle::Update(uint32 diff)
3768 {
3769 Creature::Update(diff);
3770+
3771+ if(despawn)
3772+ {
3773+ m_spawnduration -= diff;
3774+ if(m_spawnduration < 0)
3775+ Dismiss();
3776+ despawn = false;
3777+ }
3778+
3779+ if(m_regenTimer <= diff)
3780+ {
3781+ RegeneratePower(getPowerType());
3782+ m_regenTimer = 4000;
3783+ }
3784+ else
3785+ m_regenTimer -= diff;
3786 }
3787
3788-bool Vehicle::Create(uint32 guidlow, Map *map, uint32 Entry, uint32 vehicleId, uint32 team)
3789+void Vehicle::RegeneratePower(Powers power)
3790+{
3791+ uint32 curValue = GetPower(power);
3792+ uint32 maxValue = GetMaxPower(power);
3793+
3794+ if (curValue >= maxValue)
3795+ return;
3796+
3797+ float addvalue = 0.0f;
3798+
3799+ // hack: needs more research of power type from the dbc.
3800+ // It must contains some info about vehicles like Salvaged Chopper.
3801+ if(m_vehicleInfo->m_powerType == POWER_TYPE_PYRITE)
3802+ return;
3803+
3804+ addvalue = 20.0f;
3805+
3806+ ModifyPower(power, (int32)addvalue);
3807+}
3808+
3809+bool Vehicle::Create(uint32 guidlow, Map *map, uint32 phaseMask, uint32 Entry, uint32 vehicleId, uint32 team, const CreatureData *data)
3810 {
3811 SetMap(map);
3812+ SetPhaseMask(phaseMask,false);
3813+
3814+ CreatureInfo const *cinfo = sObjectMgr.GetCreatureTemplate(Entry);
3815+ if(!cinfo)
3816+ {
3817+ sLog.outErrorDb("Creature entry %u does not exist.", Entry);
3818+ return false;
3819+ }
3820
3821 Object::_Create(guidlow, Entry, HIGHGUID_VEHICLE);
3822
3823- if(!InitEntry(Entry, team))
3824+ if(!UpdateEntry(Entry, team, data))
3825 return false;
3826
3827- m_defaultMovementType = IDLE_MOTION_TYPE;
3828+ if(!vehicleId)
3829+ {
3830+ CreatureDataAddon const *cainfo = GetCreatureAddon();
3831+ if(!cainfo)
3832+ return false;
3833+ vehicleId = cainfo->vehicle_id;
3834+ }
3835+ if(!SetVehicleId(vehicleId))
3836+ return false;
3837
3838- AIM_Initialize();
3839+ LoadCreaturesAddon();
3840
3841- SetVehicleId(vehicleId);
3842+ m_regenHealth = false;
3843+ m_creation_time = getMSTime();
3844
3845- SetUInt32Value(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_SPELLCLICK);
3846 SetFloatValue(UNIT_FIELD_HOVERHEIGHT, 1.0f);
3847+ //RemoveMonsterMoveFlag(MONSTER_MOVE_WALK);
3848+
3849+ //Notify the map's instance data.
3850+ //Only works if you create the object in it, not if it is moves to that map.
3851+ //Normally non-players do not teleport to other maps.
3852+ if(map->IsDungeon() && ((InstanceMap*)map)->GetInstanceData())
3853+ {
3854+ ((InstanceMap*)map)->GetInstanceData()->OnCreatureCreate(this);
3855+ }
3856+
3857+ if(m_vehicleInfo->m_powerType == POWER_TYPE_STEAM)
3858+ {
3859+ setPowerType(POWER_ENERGY);
3860+ SetMaxPower(POWER_ENERGY, 100);
3861+ SetPower(POWER_ENERGY, 100);
3862+ }
3863+ else if(m_vehicleInfo->m_powerType == POWER_TYPE_PYRITE)
3864+ {
3865+ setPowerType(POWER_ENERGY);
3866+ SetMaxPower(POWER_ENERGY, 50);
3867+ SetPower(POWER_ENERGY, 50);
3868+ }
3869+ else
3870+ {
3871+ for (uint32 i = 0; i < MAX_VEHICLE_SPELLS; ++i)
3872+ {
3873+ if(!GetVehicleData()->v_spells[i])
3874+ continue;
3875+ SpellEntry const *spellInfo = sSpellStore.LookupEntry(GetVehicleData()->v_spells[i]);
3876+ if(!spellInfo)
3877+ continue;
3878
3879- CreatureInfo const *ci = GetCreatureInfo();
3880- setFaction(team == ALLIANCE ? ci->faction_A : ci->faction_H);
3881+ if(spellInfo->powerType == POWER_MANA)
3882+ break;
3883
3884- SelectLevel(ci);
3885+ if(spellInfo->powerType == POWER_ENERGY)
3886+ {
3887+ setPowerType(POWER_ENERGY);
3888+ SetMaxPower(POWER_ENERGY, 100);
3889+ SetPower(POWER_ENERGY, 100);
3890+ break;
3891+ }
3892+ }
3893+ }
3894+ SetHealth(GetMaxHealth());
3895+ InstallAllAccessories();
3896
3897 return true;
3898 }
3899
3900+bool Vehicle::SetVehicleId(uint32 vehicleid)
3901+{
3902+ VehicleEntry const *vehicleInfo = sVehicleStore.LookupEntry(vehicleid);
3903+ if(!vehicleInfo)
3904+ return false;
3905+
3906+ m_vehicleId = vehicleid;
3907+ m_vehicleInfo = vehicleInfo;
3908+
3909+ // can be NULL
3910+ VehicleDataStructure const *VDStructure = sObjectMgr.GetVehicleData(vehicleid);
3911+ if(VDStructure)
3912+ m_VehicleData = VDStructure;
3913+
3914+ InitSeats();
3915+ EmptySeatsCountChanged();
3916+ return true;
3917+}
3918+
3919+void Vehicle::InitSeats()
3920+{
3921+ m_Seats.clear();
3922+
3923+ for(uint32 i = 0; i < MAX_SEAT; ++i)
3924+ {
3925+ uint32 seatId = m_vehicleInfo->m_seatID[i];
3926+ if(seatId)
3927+ {
3928+ if(VehicleSeatEntry const *veSeat = sVehicleSeatStore.LookupEntry(seatId))
3929+ {
3930+ VehicleSeat newseat;
3931+ newseat.seatInfo = veSeat;
3932+ newseat.passenger = NULL;
3933+ newseat.flags = SEAT_FREE;
3934+ newseat.vs_flags = sObjectMgr.GetSeatFlags(seatId);
3935+ m_Seats[i] = newseat;
3936+ }
3937+ }
3938+ }
3939+ // NOTE : there can be vehicles without seats (eg. 180) - probably some TEST vehicles
3940+}
3941+void Vehicle::ChangeSeatFlag(uint8 seat, uint8 flag)
3942+{
3943+ SeatMap::iterator i_seat = m_Seats.find(seat);
3944+ // this should never happen
3945+ if(i_seat == m_Seats.end())
3946+ return;
3947+
3948+ if(i_seat->second.flags != flag)
3949+ {
3950+ i_seat->second.flags = flag;
3951+ EmptySeatsCountChanged();
3952+ }
3953+}
3954+Vehicle* Vehicle::FindFreeSeat(int8 *seatid, bool force)
3955+{
3956+ SeatMap::const_iterator i_seat = m_Seats.find(*seatid);
3957+ if(i_seat == m_Seats.end())
3958+ return GetFirstEmptySeat(seatid, force);
3959+ if((i_seat->second.flags & (SEAT_FULL | SEAT_VEHICLE_FULL)) || (!force && (i_seat->second.vs_flags & SF_UNACCESSIBLE)))
3960+ return GetNextEmptySeat(seatid, true, force);
3961+ if(i_seat->second.flags & SEAT_VEHICLE_FREE)
3962+ {
3963+ // this should never be NULL
3964+ if(Vehicle *v = (Vehicle*)i_seat->second.passenger)
3965+ return v->FindFreeSeat(seatid, force);
3966+ return NULL;
3967+ }
3968+ return this;
3969+}
3970+
3971+Vehicle* Vehicle::GetFirstEmptySeat(int8 *seatId, bool force)
3972+{
3973+ for(SeatMap::iterator itr = m_Seats.begin(); itr != m_Seats.end(); ++itr)
3974+ {
3975+ if(itr->second.flags & SEAT_FREE)
3976+ {
3977+ if(!force && (itr->second.vs_flags & SF_UNACCESSIBLE))
3978+ continue;
3979+
3980+ *seatId = itr->first;
3981+ return this;
3982+ }
3983+ else if(itr->second.flags & SEAT_VEHICLE_FREE)
3984+ {
3985+ *seatId = itr->first;
3986+ if(Vehicle *v = (Vehicle*)itr->second.passenger)
3987+ return v->FindFreeSeat(seatId, force);
3988+ }
3989+ }
3990+
3991+ return NULL;
3992+}
3993+
3994+Vehicle* Vehicle::GetNextEmptySeat(int8 *seatId, bool next, bool force)
3995+{
3996+ SeatMap::const_iterator i_seat = m_Seats.find(*seatId);
3997+ if(i_seat == m_Seats.end()) return GetFirstEmptySeat(seatId, force);
3998+
3999+ while((i_seat->second.flags & (SEAT_FULL | SEAT_VEHICLE_FULL)) || (!force && (i_seat->second.vs_flags & SF_UNACCESSIBLE)))
4000+ {
4001+ if(next)
4002+ {
4003+ ++i_seat;
4004+ if(i_seat == m_Seats.end())
4005+ i_seat = m_Seats.begin();
4006+ }
4007+ else
4008+ {
4009+ if(i_seat == m_Seats.begin())
4010+ i_seat = m_Seats.end();
4011+ --i_seat;
4012+ }
4013+ if(i_seat->first == *seatId)
4014+ return NULL;
4015+ }
4016+ *seatId = i_seat->first;
4017+ if(i_seat->second.flags & SEAT_VEHICLE_FREE)
4018+ {
4019+ if(Vehicle *v = (Vehicle*)i_seat->second.passenger)
4020+ return v->FindFreeSeat(seatId, force);
4021+ return NULL;
4022+ }
4023+
4024+ return this;
4025+}
4026+
4027+int8 Vehicle::GetEmptySeatsCount(bool force)
4028+{
4029+ int8 count = 0;
4030+ for(SeatMap::iterator itr = m_Seats.begin(); itr != m_Seats.end(); ++itr)
4031+ {
4032+ if(itr->second.flags & (SEAT_FREE | SEAT_VEHICLE_FREE))
4033+ {
4034+ if(!force && (itr->second.vs_flags & SF_UNACCESSIBLE))
4035+ continue;
4036+
4037+ count++;
4038+ }
4039+ }
4040+
4041+ return count;
4042+}
4043+int8 Vehicle::GetNextEmptySeatNum(int8 seatId, bool next) const
4044+{
4045+ SeatMap::const_iterator seat = m_Seats.find(seatId);
4046+ if(seat == m_Seats.end()) return -1;
4047+ while(seat->second.passenger || !seat->second.seatInfo->IsUsable())
4048+ {
4049+ if(next)
4050+ {
4051+ ++seat;
4052+ if(seat == m_Seats.end())
4053+ seat = m_Seats.begin();
4054+ }
4055+ else
4056+ {
4057+ if(seat == m_Seats.begin())
4058+ seat = m_Seats.end();
4059+ --seat;
4060+ }
4061+ if(seat->first == seatId)
4062+ return -1; // no available seat
4063+ }
4064+ return seat->first;
4065+}
4066+
4067+bool Vehicle::HasEmptySeat(int8 seatId) const
4068+{
4069+ SeatMap::const_iterator seat = m_Seats.find(seatId);
4070+ if(seat == m_Seats.end()) return false;
4071+ return !seat->second.passenger;
4072+}
4073+
4074+void Vehicle::EmptySeatsCountChanged()
4075+{
4076+ uint8 m_count = GetTotalSeatsCount();
4077+ uint8 p_count = GetEmptySeatsCount(false);
4078+ uint8 u_count = GetEmptySeatsCount(true);
4079+
4080+ // seats accesibles by players
4081+ if(p_count > 0)
4082+ SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_SPELLCLICK);
4083+ else
4084+ RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_SPELLCLICK);
4085+
4086+ if(u_count == m_count)
4087+ {
4088+ RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PLAYER_CONTROLLED);
4089+ }
4090+ else
4091+ SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PLAYER_CONTROLLED);
4092+
4093+ if(uint64 vehicleGUID = GetVehicleGUID())
4094+ {
4095+ if(Vehicle *vehicle = ObjectAccessor::GetVehicle(vehicleGUID))
4096+ {
4097+ if(u_count > 0)
4098+ vehicle->ChangeSeatFlag(m_movementInfo.GetTransportSeat(), SEAT_VEHICLE_FREE);
4099+ else
4100+ vehicle->ChangeSeatFlag(m_movementInfo.GetTransportSeat(), SEAT_VEHICLE_FULL);
4101+ }
4102+ }
4103+}
4104+
4105+
4106+
4107 void Vehicle::Dismiss()
4108 {
4109+ RemoveAllPassengers();
4110 SendObjectDeSpawnAnim(GetGUID());
4111 CombatStop();
4112 AddObjectToRemoveList();
4113 }
4114+
4115+void Vehicle::RellocatePassengers(Map *map)
4116+{
4117+ for(SeatMap::iterator itr = m_Seats.begin(); itr != m_Seats.end(); ++itr)
4118+ {
4119+ if(itr->second.flags & SEAT_FULL)
4120+ {
4121+ // passenger cant be NULL here
4122+ Unit *passengers = itr->second.passenger;
4123+ assert(passengers);
4124+
4125+ float xx = GetPositionX() + passengers->m_movementInfo.GetTransportPos()->x;
4126+ float yy = GetPositionY() + passengers->m_movementInfo.GetTransportPos()->y;
4127+ float zz = GetPositionZ() + passengers->m_movementInfo.GetTransportPos()->z;
4128+ //float oo = passengers->m_SeatData.Orientation;
4129+ // this is not correct, we should recalculate
4130+ // actual rotation depending on vehicle
4131+ float oo = passengers->GetOrientation();
4132+
4133+ if(passengers->GetTypeId() == TYPEID_PLAYER)
4134+ ((Player*)passengers)->SetPosition(xx, yy, zz, oo);
4135+ else
4136+ map->CreatureRelocation((Creature*)passengers, xx, yy, zz, oo);
4137+ }
4138+ else if(itr->second.flags & (SEAT_VEHICLE_FULL | SEAT_VEHICLE_FREE))
4139+ {
4140+ // passenger cant be NULL here
4141+ Unit *passengers = itr->second.passenger;
4142+ assert(passengers);
4143+
4144+ float xx = GetPositionX() + passengers->m_movementInfo.GetTransportPos()->x;
4145+ float yy = GetPositionY() + passengers->m_movementInfo.GetTransportPos()->y;
4146+ float zz = GetPositionZ() + passengers->m_movementInfo.GetTransportPos()->z;
4147+ //float oo = passengers->m_SeatData.Orientation;
4148+ // this is not correct, we should recalculate
4149+ // actual rotation depending on vehicle
4150+ float oo = passengers->GetOrientation();
4151+
4152+ map->CreatureRelocation((Creature*)passengers, xx, yy, zz, oo);
4153+ }
4154+ }
4155+}
4156+
4157+void Vehicle::AddPassenger(Unit *unit, int8 seatId, bool force)
4158+{
4159+ SeatMap::iterator seat;
4160+ seat = m_Seats.find(seatId);
4161+
4162+ // this should never happen
4163+ if(seat == m_Seats.end())
4164+ return;
4165+
4166+ unit->SetVehicleGUID(GetGUID());
4167+ unit->m_movementInfo.AddMovementFlag(MOVEFLAG_ONTRANSPORT);
4168+ unit->m_movementInfo.AddMovementFlag(MOVEFLAG_ROOT);
4169+
4170+ seat->second.passenger = unit;
4171+ if(unit->GetTypeId() == TYPEID_UNIT && ((Creature*)unit)->isVehicle())
4172+ {
4173+ if(((Vehicle*)unit)->GetEmptySeatsCount(true) == 0)
4174+ seat->second.flags = SEAT_VEHICLE_FULL;
4175+ else
4176+ seat->second.flags = SEAT_VEHICLE_FREE;
4177+ }
4178+ else
4179+ {
4180+ seat->second.flags = SEAT_FULL;
4181+ }
4182+
4183+ if(unit->GetTypeId() == TYPEID_PLAYER)
4184+ {
4185+ WorldPacket data0(SMSG_FORCE_MOVE_ROOT, 10);
4186+ data0 << unit->GetPackGUID();
4187+ data0 << (uint32)((seat->second.vs_flags & SF_CAN_CAST) ? 2 : 0);
4188+ unit->SendMessageToSet(&data0,true);
4189+ }
4190+
4191+ if(unit->GetTypeId() == TYPEID_PLAYER)
4192+ {
4193+ uint8 allowMove = 1;
4194+ if(GetVehicleFlags() & VF_MOVEMENT)
4195+ allowMove = 0;
4196+ ((Player*)unit)->SetMover(this);
4197+ ((Player*)unit)->SetClientControl(this, 1);
4198+ ((Player*)unit)->GetCamera().SetView(this);
4199+ }
4200+
4201+ if(seat->second.vs_flags & SF_MAIN_RIDER)
4202+ {
4203+ if(!(GetVehicleFlags() & VF_MOVEMENT))
4204+ {
4205+ GetMotionMaster()->Clear(false);
4206+ GetMotionMaster()->MoveIdle();
4207+ SetCharmerGUID(unit->GetGUID());
4208+ unit->SetUInt64Value(UNIT_FIELD_CHARM, GetGUID());
4209+ if(canFly() || HasAuraType(SPELL_AURA_FLY) || HasAuraType(SPELL_AURA_MOD_FLIGHT_SPEED))
4210+ {
4211+ WorldPacket data3(SMSG_MOVE_SET_CAN_FLY, 12);
4212+ data3<< GetPackGUID();
4213+ data3 << (uint32)(0);
4214+ SendMessageToSet(&data3,false);
4215+ }
4216+ }
4217+
4218+ SpellClickInfoMapBounds clickPair = sObjectMgr.GetSpellClickInfoMapBounds(GetEntry());
4219+ for(SpellClickInfoMap::const_iterator itr = clickPair.first; itr != clickPair.second; ++itr)
4220+ {
4221+ if (unit->GetTypeId() == TYPEID_UNIT || itr->second.IsFitToRequirements((Player*)unit))
4222+ {
4223+ Unit *caster = (itr->second.castFlags & 0x1) ? unit : this;
4224+ Unit *target = (itr->second.castFlags & 0x2) ? unit : this;
4225+
4226+ caster->CastSpell(target, itr->second.spellId, true);
4227+ }
4228+ }
4229+ if(unit->GetTypeId() == TYPEID_PLAYER)
4230+ {
4231+ // it should be added only on rider enter?
4232+ if(((Player*)unit)->GetGroup())
4233+ ((Player*)unit)->SetGroupUpdateFlag(GROUP_UPDATE_VEHICLE);
4234+
4235+ BuildVehicleActionBar((Player*)unit);
4236+ }
4237+
4238+ if(!(GetVehicleFlags() & VF_FACTION))
4239+ setFaction(unit->getFaction());
4240+
4241+ if(GetVehicleFlags() & VF_CANT_MOVE)
4242+ {
4243+ WorldPacket data2(SMSG_FORCE_MOVE_ROOT, 10);
4244+ data2<< GetPackGUID();
4245+ data2 << (uint32)(2);
4246+ SendMessageToSet(&data2,false);
4247+ }
4248+
4249+ if(GetVehicleFlags() & VF_NON_SELECTABLE)
4250+ SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
4251+ }
4252+ if(seat->second.vs_flags & SF_UNATTACKABLE)
4253+ unit->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
4254+
4255+ EmptySeatsCountChanged();
4256+}
4257+
4258+void Vehicle::RemovePassenger(Unit *unit)
4259+{
4260+ SeatMap::iterator seat;
4261+ for(seat = m_Seats.begin(); seat != m_Seats.end(); ++seat)
4262+ {
4263+ if((seat->second.flags & (SEAT_FULL | SEAT_VEHICLE_FREE | SEAT_VEHICLE_FULL)) && seat->second.passenger == unit)
4264+ {
4265+ unit->SetVehicleGUID(0);
4266+ if(unit->GetTypeId() == TYPEID_PLAYER)
4267+ {
4268+ ((Player*)unit)->SetMover(unit);
4269+ ((Player*)unit)->SetClientControl(unit, 1);
4270+ ((Player*)unit)->GetCamera().SetView(unit);
4271+ }
4272+
4273+ if(seat->second.vs_flags & SF_MAIN_RIDER)
4274+ {
4275+ RemoveSpellsCausingAura(SPELL_AURA_CONTROL_VEHICLE);
4276+ if(unit->GetTypeId() == TYPEID_PLAYER)
4277+ {
4278+ ((Player*)unit)->RemovePetActionBar();
4279+
4280+ if(((Player*)unit)->GetGroup())
4281+ ((Player*)unit)->SetGroupUpdateFlag(GROUP_UPDATE_VEHICLE);
4282+ }
4283+ unit->SetCharm(NULL);
4284+ SetCharmerGUID(NULL);
4285+ setFaction(GetCreatureInfo()->faction_A);
4286+ }
4287+ if(GetVehicleFlags() & VF_NON_SELECTABLE)
4288+ RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
4289+ if(seat->second.vs_flags & SF_UNATTACKABLE)
4290+ unit->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
4291+ // restore player control
4292+ if(unit->GetTypeId() == TYPEID_PLAYER)
4293+ {
4294+ if(seat->second.vs_flags & SF_CAN_CAST)
4295+ {
4296+ WorldPacket data0(SMSG_FORCE_MOVE_UNROOT, 10);
4297+ data0 << unit->GetPackGUID();
4298+ data0 << (uint32)(2); // can rotate
4299+ unit->SendMessageToSet(&data0,true);
4300+ }
4301+ else
4302+ {
4303+ WorldPacket data1(SMSG_FORCE_MOVE_UNROOT, 10);
4304+ data1 << unit->GetPackGUID();
4305+ data1 << (uint32)(0); // cannot rotate
4306+ unit->SendMessageToSet(&data1,true);
4307+ }
4308+ }
4309+ unit->m_movementInfo.RemoveMovementFlag(MOVEFLAG_ONTRANSPORT);
4310+ unit->m_movementInfo.RemoveMovementFlag(MOVEFLAG_ROOT);
4311+ unit->m_movementInfo.ClearTransportData();
4312+
4313+ seat->second.passenger = NULL;
4314+ seat->second.flags = SEAT_FREE;
4315+ EmptySeatsCountChanged();
4316+ break;
4317+ }
4318+ }
4319+}
4320+
4321+void Vehicle::RemoveAllPassengers()
4322+{
4323+ for(SeatMap::iterator itr = m_Seats.begin(); itr != m_Seats.end(); ++itr)
4324+ {
4325+ if(itr->second.flags & SEAT_FULL)
4326+ {
4327+ if(Unit *passenger = itr->second.passenger) // this cant be NULL, but..
4328+ passenger->ExitVehicle();
4329+ }
4330+ else if(itr->second.flags & (SEAT_VEHICLE_FULL | SEAT_VEHICLE_FREE))
4331+ {
4332+ if(Unit *passenger = itr->second.passenger) // this cant be NULL, but..
4333+ {
4334+ passenger->ExitVehicle();
4335+ ((Vehicle*)passenger)->Dismiss();
4336+ }
4337+ }
4338+ }
4339+ // make sure everything is cleared
4340+ InitSeats();
4341+}
4342+
4343+bool Vehicle::HasSpell(uint32 spell) const
4344+{
4345+ if(!m_VehicleData)
4346+ return false;
4347+
4348+ for(uint8 j = 0; j < MAX_VEHICLE_SPELLS; j++)
4349+ {
4350+ if(m_VehicleData->v_spells[j] == spell)
4351+ return true;
4352+ }
4353+
4354+ return false;
4355+}
4356+
4357+void Vehicle::BuildVehicleActionBar(Player *plr) const
4358+{
4359+ WorldPacket data(SMSG_PET_SPELLS, 8+2+4+4+4*10+1+1);
4360+ data << uint64(GetGUID());
4361+ data << uint16(0x00000000); // creature family, not used in vehicles
4362+ data << uint32(0x00000000); // unk
4363+ data << uint32(0x00000101); // react state
4364+
4365+ for(uint32 i = 0; i <= MAX_VEHICLE_SPELLS; ++i)
4366+ {
4367+ data << uint16(m_VehicleData ? m_VehicleData->v_spells[i] : NULL) << uint8(0) << uint8(i+8);
4368+ }
4369+
4370+ data << uint8(0); //aditional spells in spellbook, not used in vehicles
4371+
4372+ uint8 cooldownsCount = m_CreatureSpellCooldowns.size() + m_CreatureCategoryCooldowns.size();
4373+ data << uint8(cooldownsCount);
4374+ time_t curTime = time(NULL);
4375+
4376+ for(CreatureSpellCooldowns::const_iterator itr = m_CreatureSpellCooldowns.begin(); itr != m_CreatureSpellCooldowns.end(); ++itr)
4377+ {
4378+ time_t cooldown = (itr->second > curTime) ? (itr->second - curTime) * IN_MILLISECONDS : 0;
4379+
4380+ data << uint32(itr->first); // spellid
4381+ data << uint16(0); // spell category?
4382+ data << uint32(cooldown); // cooldown
4383+ data << uint32(0); // category cooldown
4384+ }
4385+
4386+ for(CreatureSpellCooldowns::const_iterator itr = m_CreatureCategoryCooldowns.begin(); itr != m_CreatureCategoryCooldowns.end(); ++itr)
4387+ {
4388+ time_t cooldown = (itr->second > curTime) ? (itr->second - curTime) * IN_MILLISECONDS : 0;
4389+
4390+ data << uint32(itr->first); // spellid
4391+ data << uint16(0); // spell category?
4392+ data << uint32(0); // cooldown
4393+ data << uint32(cooldown); // category cooldown
4394+ }
4395+
4396+ plr->GetSession()->SendPacket(&data);
4397+
4398+ data.Initialize(SMSG_PET_GUIDS, 12);
4399+ data << uint32(1); // count
4400+ data << uint64(GetGUID());
4401+ plr->GetSession()->SendPacket(&data);
4402+}
4403+void Vehicle::InstallAllAccessories()
4404+{
4405+ if(!GetMap())
4406+ return;
4407+
4408+ CreatureDataAddon const *cainfo = GetCreatureAddon();
4409+ if(!cainfo || !cainfo->passengers)
4410+ return;
4411+ for (CreatureDataAddonPassengers const* cPassanger = cainfo->passengers; cPassanger->seat_idx != -1; ++cPassanger)
4412+ {
4413+ // Continue if seat already taken
4414+ if(GetPassenger(cPassanger->seat_idx))
4415+ continue;
4416+
4417+ uint32 guid = 0;
4418+ bool isVehicle = false;
4419+ // Set guid and check whatever it is
4420+ if(cPassanger->guid != 0)
4421+ guid = cPassanger->guid;
4422+ else
4423+ {
4424+ CreatureDataAddon const* passAddon;
4425+ passAddon = ObjectMgr::GetCreatureTemplateAddon(cPassanger->entry);
4426+ if(passAddon && passAddon->vehicle_id != 0)
4427+ isVehicle = true;
4428+ else
4429+ guid = sObjectMgr.GenerateLowGuid(HIGHGUID_UNIT);
4430+ }
4431+ // Create it
4432+ Creature *pPassenger = new Creature;
4433+ if(!isVehicle)
4434+ {
4435+ uint32 entry = cPassanger->entry;
4436+ if(entry == 0)
4437+ {
4438+ CreatureData const* data = sObjectMgr.GetCreatureData(guid);
4439+ if(!data)
4440+ continue;
4441+ entry = data->id;
4442+ }
4443+
4444+ if(!pPassenger->Create(guid, GetMap(), GetPhaseMask(), entry, 0))
4445+ continue;
4446+ pPassenger->LoadFromDB(guid, GetMap());
4447+ pPassenger->Relocate(GetPositionX(), GetPositionY(), GetPositionZ());
4448+ GetMap()->Add(pPassenger);
4449+ pPassenger->AIM_Initialize();
4450+ }
4451+ else
4452+ pPassenger = (Creature*)SummonVehicle(cPassanger->entry, GetPositionX(), GetPositionY(), GetPositionZ(), 0);
4453+ // Enter vehicle...
4454+ pPassenger->EnterVehicle(this, cPassanger->seat_idx, true);
4455+ // ...and send update. Without this, client wont show this new creature/vehicle...
4456+ WorldPacket data;
4457+ pPassenger->BuildHeartBeatMsg(&data);
4458+ pPassenger->SendMessageToSet(&data, false);
4459+ }
4460+}
4461+
4462+Unit *Vehicle::GetPassenger(int8 seatId) const
4463+{
4464+ SeatMap::const_iterator seat = m_Seats.find(seatId);
4465+ if(seat == m_Seats.end()) return NULL;
4466+ return seat->second.passenger;
4467+}
4468+void Vehicle::Die()
4469+{
4470+ for (SeatMap::iterator itr = m_Seats.begin(); itr != m_Seats.end(); ++itr)
4471+ if(Unit *passenger = itr->second.passenger)
4472+ if(((Creature*)passenger)->isVehicle())
4473+ ((Vehicle*)passenger)->Dismiss();
4474+ RemoveAllPassengers();
4475+}
4476\ No newline at end of file
4477diff --git a/src/game/Vehicle.h b/src/game/Vehicle.h
4478index 4233db6..7252bad 100644
4479--- a/src/game/Vehicle.h
4480+++ b/src/game/Vehicle.h
4481@@ -22,6 +22,34 @@
4482 #include "ObjectGuid.h"
4483 #include "Creature.h"
4484 #include "Unit.h"
4485+#include "ObjectMgr.h"
4486+
4487+struct VehicleSeat
4488+{
4489+ VehicleSeatEntry const *seatInfo;
4490+ Unit* passenger;
4491+ uint8 flags;
4492+ uint32 vs_flags;
4493+};
4494+
4495+enum VehicleSeatFlags
4496+{
4497+ SEAT_FREE = 0x01, // free seat
4498+ SEAT_FULL = 0x02, // seat occupied by player/creature
4499+ // special cases
4500+ SEAT_VEHICLE_FREE = 0x04, // seat occupied by vehicle, but that vehicle is free
4501+ SEAT_VEHICLE_FULL = 0x08 // seat occupied by vehicle and that vehicle is full too
4502+};
4503+
4504+enum PowerType
4505+{
4506+ POWER_TYPE_PYRITE = 41,
4507+ POWER_TYPE_STEAM = 61
4508+};
4509+
4510+#define MAX_SEAT 8
4511+
4512+typedef std::map<int8, VehicleSeat> SeatMap;
4513
4514 class Vehicle : public Creature
4515 {
4516@@ -32,18 +60,57 @@ class Vehicle : public Creature
4517 void AddToWorld();
4518 void RemoveFromWorld();
4519
4520- bool Create (uint32 guidlow, Map *map, uint32 Entry, uint32 vehicleId, uint32 team);
4521+ void Die();
4522+ bool Create (uint32 guidlow, Map *map, uint32 phaseMask, uint32 Entry, uint32 vehicleId, uint32 team, const CreatureData *data = NULL);
4523+ void Respawn();
4524
4525 void setDeathState(DeathState s); // overwrite virtual Creature::setDeathState and Unit::setDeathState
4526 void Update(uint32 diff); // overwrite virtual Creature::Update and Unit::Update
4527
4528+ void RegeneratePower(Powers power);
4529+
4530 uint32 GetVehicleId() { return m_vehicleId; }
4531- void SetVehicleId(uint32 vehicleid) { m_vehicleId = vehicleid; }
4532+ bool SetVehicleId(uint32 vehicleid);
4533+
4534+ void InitSeats();
4535+
4536+ void ChangeSeatFlag(uint8 seat, uint8 flag);
4537+ Vehicle* FindFreeSeat(int8 *seatid, bool force = true);
4538+ Vehicle* GetNextEmptySeat(int8 *seatId, bool next = true, bool force = true);
4539+ Vehicle* GetFirstEmptySeat(int8 *seatId, bool force = true);
4540+ int8 GetEmptySeatsCount(bool force = true);
4541+ void EmptySeatsCountChanged();
4542+ int8 GetTotalSeatsCount() { return m_Seats.size(); }
4543+ bool HasEmptySeat(int8 seatId) const;
4544+ int8 GetNextEmptySeatNum(int8 seatId, bool next) const;
4545
4546 void Dismiss();
4547
4548+ void RellocatePassengers(Map *map);
4549+ void AddPassenger(Unit *unit, int8 seatId, bool force = true);
4550+ void RemovePassenger(Unit *unit);
4551+ void RemoveAllPassengers();
4552+
4553+ bool HasSpell(uint32 spell) const;
4554+ void SetSpawnDuration(int32 duration)
4555+ {
4556+ duration < 1 ? despawn = false : despawn = true;
4557+ m_spawnduration = duration;
4558+ }
4559+ VehicleDataStructure const* GetVehicleData() { return m_VehicleData; }
4560+ uint32 GetVehicleFlags() { return m_VehicleData ? m_VehicleData->v_flags : NULL; }
4561+ uint32 GetCreationTime() { return m_creation_time; }
4562+ void BuildVehicleActionBar(Player *plr) const;
4563+ void InstallAllAccessories();
4564+ Unit *GetPassenger(int8 seatId) const;
4565 protected:
4566 uint32 m_vehicleId;
4567+ VehicleEntry const *m_vehicleInfo;
4568+ VehicleDataStructure const *m_VehicleData;
4569+ uint32 m_creation_time;
4570+ SeatMap m_Seats;
4571+ bool despawn;
4572+ int32 m_spawnduration;
4573
4574 private:
4575 void SaveToDB(uint32, uint8) // overwrited of Creature::SaveToDB - don't must be called
4576diff --git a/src/game/World.cpp b/src/game/World.cpp
4577index 5c87bcc..67c4a93 100644
4578--- a/src/game/World.cpp
4579+++ b/src/game/World.cpp
4580@@ -1220,6 +1220,11 @@ void World::SetInitialWorldSettings()
4581 sLog.outString( "Loading Scripts text locales..." ); // must be after Load*Scripts calls
4582 sObjectMgr.LoadDbScriptStrings();
4583
4584+ sLog.outString( "Loading VehicleData..." );
4585+ sObjectMgr.LoadVehicleData();
4586+ sLog.outString( "Loading VehicleSeatData..." );
4587+ sObjectMgr.LoadVehicleSeatData();
4588+
4589 sLog.outString( "Loading CreatureEventAI Texts...");
4590 sEventAIMgr.LoadCreatureEventAI_Texts(false); // false, will checked in LoadCreatureEventAI_Scripts
4591
4592diff --git a/src/game/WorldSession.h b/src/game/WorldSession.h
4593index af857e2..e3bc43b 100644
4594--- a/src/game/WorldSession.h
4595+++ b/src/game/WorldSession.h
4596@@ -425,6 +425,9 @@ class MANGOS_DLL_SPEC WorldSession
4597 void HandleSetActiveMoverOpcode(WorldPacket &recv_data);
4598 void HandleMoveNotActiveMover(WorldPacket &recv_data);
4599 void HandleDismissControlledVehicle(WorldPacket &recv_data);
4600+ void HandleRequestVehicleExit(WorldPacket &recv_data);
4601+ void HandleRequestVehicleSwitchSeat(WorldPacket &recv_data);
4602+ void HandleChangeSeatsOnControlledVehicle(WorldPacket &recv_data);
4603 void HandleMoveTimeSkippedOpcode(WorldPacket &recv_data);
4604
4605 void HandleRequestRaidInfoOpcode( WorldPacket & recv_data );
4606diff --git a/src/game/debugcmds.cpp b/src/game/debugcmds.cpp
4607index 9ea6958..a01de1c 100644
4608--- a/src/game/debugcmds.cpp
4609+++ b/src/game/debugcmds.cpp
4610@@ -636,7 +636,8 @@ bool ChatHandler::HandleDebugSpawnVehicle(const char* args)
4611
4612 Vehicle *v = new Vehicle;
4613 Map *map = m_session->GetPlayer()->GetMap();
4614- if (!v->Create(map->GenerateLocalLowGuid(HIGHGUID_VEHICLE), map, entry, id, m_session->GetPlayer()->GetTeam()))
4615+
4616+ if (!v->Create(sObjectMgr.GenerateLowGuid(HIGHGUID_VEHICLE), map, m_session->GetPlayer()->GetPhaseMaskForSpawn(), entry, id, m_session->GetPlayer()->GetTeam()))
4617 {
4618 delete v;
4619 return false;
4620@@ -656,6 +657,7 @@ bool ChatHandler::HandleDebugSpawnVehicle(const char* args)
4621 }
4622
4623 map->Add((Creature*)v);
4624+ v->AIM_Initialize();
4625
4626 return true;
4627 }
4628diff --git a/src/shared/Database/SQLStorage.cpp b/src/shared/Database/SQLStorage.cpp
4629index c7644f2..64c4391 100644
4630--- a/src/shared/Database/SQLStorage.cpp
4631+++ b/src/shared/Database/SQLStorage.cpp
4632@@ -27,9 +27,9 @@ extern DatabaseMysql WorldDatabase;
4633
4634 const char CreatureInfosrcfmt[]="iiiiiiiiiisssiiiiiiiiiiifffiffiifiiiiiiiiiiffiiiiiiiiiiiiiiiiiiisiiffliiiiiiiliiis";
4635 const char CreatureInfodstfmt[]="iiiiiiiiiisssiiiiiiiiiiifffiffiifiiiiiiiiiiffiiiiiiiiiiiiiiiiiiisiiffliiiiiiiliiii";
4636-const char CreatureDataAddonInfofmt[]="iiiiiis";
4637+const char CreatureDataAddonInfofmt[]="iiiiiiiss";
4638 const char CreatureModelfmt[]="iffbi";
4639-const char CreatureInfoAddonInfofmt[]="iiiiiis";
4640+const char CreatureInfoAddonInfofmt[]="iiiiiiiss";
4641 const char EquipmentInfofmt[]="iiii";
4642 const char GameObjectInfosrcfmt[]="iiissssiifiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiis";
4643 const char GameObjectInfodstfmt[]="iiissssiifiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii";