|
1 /* $Id$ */ |
|
2 |
|
3 /** @file vehicle.cpp */ |
|
4 |
|
5 #include "stdafx.h" |
|
6 #include "openttd.h" |
|
7 #include "road_map.h" |
|
8 #include "roadveh.h" |
|
9 #include "ship.h" |
|
10 #include "spritecache.h" |
|
11 #include "tile_cmd.h" |
|
12 #include "landscape.h" |
|
13 #include "timetable.h" |
|
14 #include "viewport_func.h" |
|
15 #include "gfx_func.h" |
|
16 #include "news_func.h" |
|
17 #include "command_func.h" |
|
18 #include "saveload.h" |
|
19 #include "player_func.h" |
|
20 #include "debug.h" |
|
21 #include "vehicle_gui.h" |
|
22 #include "rail_type.h" |
|
23 #include "train.h" |
|
24 #include "aircraft.h" |
|
25 #include "industry_map.h" |
|
26 #include "station_map.h" |
|
27 #include "water_map.h" |
|
28 #include "network/network.h" |
|
29 #include "yapf/yapf.h" |
|
30 #include "newgrf_callbacks.h" |
|
31 #include "newgrf_engine.h" |
|
32 #include "newgrf_sound.h" |
|
33 #include "group.h" |
|
34 #include "order_func.h" |
|
35 #include "strings_func.h" |
|
36 #include "zoom_func.h" |
|
37 #include "functions.h" |
|
38 #include "date_func.h" |
|
39 #include "window_func.h" |
|
40 #include "vehicle_func.h" |
|
41 #include "signal_func.h" |
|
42 #include "sound_func.h" |
|
43 #include "variables.h" |
|
44 #include "autoreplace_func.h" |
|
45 #include "autoreplace_gui.h" |
|
46 #include "string_func.h" |
|
47 #include "settings_type.h" |
|
48 #include "oldpool_func.h" |
|
49 #include "depot_map.h" |
|
50 #include "animated_tile_func.h" |
|
51 #include "effectvehicle_base.h" |
|
52 #include "effectvehicle_func.h" |
|
53 |
|
54 #include "table/sprites.h" |
|
55 #include "table/strings.h" |
|
56 |
|
57 static void ChimneySmokeInit(Vehicle *v) |
|
58 { |
|
59 uint32 r = Random(); |
|
60 v->cur_image = SPR_CHIMNEY_SMOKE_0 + GB(r, 0, 3); |
|
61 v->progress = GB(r, 16, 3); |
|
62 } |
|
63 |
|
64 static void ChimneySmokeTick(Vehicle *v) |
|
65 { |
|
66 if (v->progress > 0) { |
|
67 v->progress--; |
|
68 } else { |
|
69 BeginVehicleMove(v); |
|
70 |
|
71 TileIndex tile = TileVirtXY(v->x_pos, v->y_pos); |
|
72 if (!IsTileType(tile, MP_INDUSTRY)) { |
|
73 EndVehicleMove(v); |
|
74 delete v; |
|
75 return; |
|
76 } |
|
77 |
|
78 if (v->cur_image != SPR_CHIMNEY_SMOKE_7) { |
|
79 v->cur_image++; |
|
80 } else { |
|
81 v->cur_image = SPR_CHIMNEY_SMOKE_0; |
|
82 } |
|
83 v->progress = 7; |
|
84 VehiclePositionChanged(v); |
|
85 EndVehicleMove(v); |
|
86 } |
|
87 } |
|
88 |
|
89 static void SteamSmokeInit(Vehicle *v) |
|
90 { |
|
91 v->cur_image = SPR_STEAM_SMOKE_0; |
|
92 v->progress = 12; |
|
93 } |
|
94 |
|
95 static void SteamSmokeTick(Vehicle *v) |
|
96 { |
|
97 bool moved = false; |
|
98 |
|
99 BeginVehicleMove(v); |
|
100 |
|
101 v->progress++; |
|
102 |
|
103 if ((v->progress & 7) == 0) { |
|
104 v->z_pos++; |
|
105 moved = true; |
|
106 } |
|
107 |
|
108 if ((v->progress & 0xF) == 4) { |
|
109 if (v->cur_image != SPR_STEAM_SMOKE_4) { |
|
110 v->cur_image++; |
|
111 } else { |
|
112 EndVehicleMove(v); |
|
113 delete v; |
|
114 return; |
|
115 } |
|
116 moved = true; |
|
117 } |
|
118 |
|
119 if (moved) { |
|
120 VehiclePositionChanged(v); |
|
121 EndVehicleMove(v); |
|
122 } |
|
123 } |
|
124 |
|
125 static void DieselSmokeInit(Vehicle *v) |
|
126 { |
|
127 v->cur_image = SPR_DIESEL_SMOKE_0; |
|
128 v->progress = 0; |
|
129 } |
|
130 |
|
131 static void DieselSmokeTick(Vehicle *v) |
|
132 { |
|
133 v->progress++; |
|
134 |
|
135 if ((v->progress & 3) == 0) { |
|
136 BeginVehicleMove(v); |
|
137 v->z_pos++; |
|
138 VehiclePositionChanged(v); |
|
139 EndVehicleMove(v); |
|
140 } else if ((v->progress & 7) == 1) { |
|
141 BeginVehicleMove(v); |
|
142 if (v->cur_image != SPR_DIESEL_SMOKE_5) { |
|
143 v->cur_image++; |
|
144 VehiclePositionChanged(v); |
|
145 EndVehicleMove(v); |
|
146 } else { |
|
147 EndVehicleMove(v); |
|
148 delete v; |
|
149 } |
|
150 } |
|
151 } |
|
152 |
|
153 static void ElectricSparkInit(Vehicle *v) |
|
154 { |
|
155 v->cur_image = SPR_ELECTRIC_SPARK_0; |
|
156 v->progress = 1; |
|
157 } |
|
158 |
|
159 static void ElectricSparkTick(Vehicle *v) |
|
160 { |
|
161 if (v->progress < 2) { |
|
162 v->progress++; |
|
163 } else { |
|
164 v->progress = 0; |
|
165 BeginVehicleMove(v); |
|
166 if (v->cur_image != SPR_ELECTRIC_SPARK_5) { |
|
167 v->cur_image++; |
|
168 VehiclePositionChanged(v); |
|
169 EndVehicleMove(v); |
|
170 } else { |
|
171 EndVehicleMove(v); |
|
172 delete v; |
|
173 } |
|
174 } |
|
175 } |
|
176 |
|
177 static void SmokeInit(Vehicle *v) |
|
178 { |
|
179 v->cur_image = SPR_SMOKE_0; |
|
180 v->progress = 12; |
|
181 } |
|
182 |
|
183 static void SmokeTick(Vehicle *v) |
|
184 { |
|
185 bool moved = false; |
|
186 |
|
187 BeginVehicleMove(v); |
|
188 |
|
189 v->progress++; |
|
190 |
|
191 if ((v->progress & 3) == 0) { |
|
192 v->z_pos++; |
|
193 moved = true; |
|
194 } |
|
195 |
|
196 if ((v->progress & 0xF) == 4) { |
|
197 if (v->cur_image != SPR_SMOKE_4) { |
|
198 v->cur_image++; |
|
199 } else { |
|
200 EndVehicleMove(v); |
|
201 delete v; |
|
202 return; |
|
203 } |
|
204 moved = true; |
|
205 } |
|
206 |
|
207 if (moved) { |
|
208 VehiclePositionChanged(v); |
|
209 EndVehicleMove(v); |
|
210 } |
|
211 } |
|
212 |
|
213 static void ExplosionLargeInit(Vehicle *v) |
|
214 { |
|
215 v->cur_image = SPR_EXPLOSION_LARGE_0; |
|
216 v->progress = 0; |
|
217 } |
|
218 |
|
219 static void ExplosionLargeTick(Vehicle *v) |
|
220 { |
|
221 v->progress++; |
|
222 if ((v->progress & 3) == 0) { |
|
223 BeginVehicleMove(v); |
|
224 if (v->cur_image != SPR_EXPLOSION_LARGE_F) { |
|
225 v->cur_image++; |
|
226 VehiclePositionChanged(v); |
|
227 EndVehicleMove(v); |
|
228 } else { |
|
229 EndVehicleMove(v); |
|
230 delete v; |
|
231 } |
|
232 } |
|
233 } |
|
234 |
|
235 static void BreakdownSmokeInit(Vehicle *v) |
|
236 { |
|
237 v->cur_image = SPR_BREAKDOWN_SMOKE_0; |
|
238 v->progress = 0; |
|
239 } |
|
240 |
|
241 static void BreakdownSmokeTick(Vehicle *v) |
|
242 { |
|
243 v->progress++; |
|
244 if ((v->progress & 7) == 0) { |
|
245 BeginVehicleMove(v); |
|
246 if (v->cur_image != SPR_BREAKDOWN_SMOKE_3) { |
|
247 v->cur_image++; |
|
248 } else { |
|
249 v->cur_image = SPR_BREAKDOWN_SMOKE_0; |
|
250 } |
|
251 VehiclePositionChanged(v); |
|
252 EndVehicleMove(v); |
|
253 } |
|
254 |
|
255 v->u.effect.animation_state--; |
|
256 if (v->u.effect.animation_state == 0) { |
|
257 BeginVehicleMove(v); |
|
258 EndVehicleMove(v); |
|
259 delete v; |
|
260 } |
|
261 } |
|
262 |
|
263 static void ExplosionSmallInit(Vehicle *v) |
|
264 { |
|
265 v->cur_image = SPR_EXPLOSION_SMALL_0; |
|
266 v->progress = 0; |
|
267 } |
|
268 |
|
269 static void ExplosionSmallTick(Vehicle *v) |
|
270 { |
|
271 v->progress++; |
|
272 if ((v->progress & 3) == 0) { |
|
273 BeginVehicleMove(v); |
|
274 if (v->cur_image != SPR_EXPLOSION_SMALL_B) { |
|
275 v->cur_image++; |
|
276 VehiclePositionChanged(v); |
|
277 EndVehicleMove(v); |
|
278 } else { |
|
279 EndVehicleMove(v); |
|
280 delete v; |
|
281 } |
|
282 } |
|
283 } |
|
284 |
|
285 static void BulldozerInit(Vehicle *v) |
|
286 { |
|
287 v->cur_image = SPR_BULLDOZER_NE; |
|
288 v->progress = 0; |
|
289 v->u.effect.animation_state = 0; |
|
290 v->u.effect.animation_substate = 0; |
|
291 } |
|
292 |
|
293 struct BulldozerMovement { |
|
294 byte direction:2; |
|
295 byte image:2; |
|
296 byte duration:3; |
|
297 }; |
|
298 |
|
299 static const BulldozerMovement _bulldozer_movement[] = { |
|
300 { 0, 0, 4 }, |
|
301 { 3, 3, 4 }, |
|
302 { 2, 2, 7 }, |
|
303 { 0, 2, 7 }, |
|
304 { 1, 1, 3 }, |
|
305 { 2, 2, 7 }, |
|
306 { 0, 2, 7 }, |
|
307 { 1, 1, 3 }, |
|
308 { 2, 2, 7 }, |
|
309 { 0, 2, 7 }, |
|
310 { 3, 3, 6 }, |
|
311 { 2, 2, 6 }, |
|
312 { 1, 1, 7 }, |
|
313 { 3, 1, 7 }, |
|
314 { 0, 0, 3 }, |
|
315 { 1, 1, 7 }, |
|
316 { 3, 1, 7 }, |
|
317 { 0, 0, 3 }, |
|
318 { 1, 1, 7 }, |
|
319 { 3, 1, 7 } |
|
320 }; |
|
321 |
|
322 static const struct { |
|
323 int8 x; |
|
324 int8 y; |
|
325 } _inc_by_dir[] = { |
|
326 { -1, 0 }, |
|
327 { 0, 1 }, |
|
328 { 1, 0 }, |
|
329 { 0, -1 } |
|
330 }; |
|
331 |
|
332 static void BulldozerTick(Vehicle *v) |
|
333 { |
|
334 v->progress++; |
|
335 if ((v->progress & 7) == 0) { |
|
336 const BulldozerMovement* b = &_bulldozer_movement[v->u.effect.animation_state]; |
|
337 |
|
338 BeginVehicleMove(v); |
|
339 |
|
340 v->cur_image = SPR_BULLDOZER_NE + b->image; |
|
341 |
|
342 v->x_pos += _inc_by_dir[b->direction].x; |
|
343 v->y_pos += _inc_by_dir[b->direction].y; |
|
344 |
|
345 v->u.effect.animation_substate++; |
|
346 if (v->u.effect.animation_substate >= b->duration) { |
|
347 v->u.effect.animation_substate = 0; |
|
348 v->u.effect.animation_state++; |
|
349 if (v->u.effect.animation_state == lengthof(_bulldozer_movement)) { |
|
350 EndVehicleMove(v); |
|
351 delete v; |
|
352 return; |
|
353 } |
|
354 } |
|
355 VehiclePositionChanged(v); |
|
356 EndVehicleMove(v); |
|
357 } |
|
358 } |
|
359 |
|
360 static void BubbleInit(Vehicle *v) |
|
361 { |
|
362 v->cur_image = SPR_BUBBLE_GENERATE_0; |
|
363 v->spritenum = 0; |
|
364 v->progress = 0; |
|
365 } |
|
366 |
|
367 struct BubbleMovement { |
|
368 int8 x:4; |
|
369 int8 y:4; |
|
370 int8 z:4; |
|
371 byte image:4; |
|
372 }; |
|
373 |
|
374 #define MK(x, y, z, i) { x, y, z, i } |
|
375 #define ME(i) { i, 4, 0, 0 } |
|
376 |
|
377 static const BubbleMovement _bubble_float_sw[] = { |
|
378 MK(0, 0, 1, 0), |
|
379 MK(1, 0, 1, 1), |
|
380 MK(0, 0, 1, 0), |
|
381 MK(1, 0, 1, 2), |
|
382 ME(1) |
|
383 }; |
|
384 |
|
385 |
|
386 static const BubbleMovement _bubble_float_ne[] = { |
|
387 MK( 0, 0, 1, 0), |
|
388 MK(-1, 0, 1, 1), |
|
389 MK( 0, 0, 1, 0), |
|
390 MK(-1, 0, 1, 2), |
|
391 ME(1) |
|
392 }; |
|
393 |
|
394 static const BubbleMovement _bubble_float_se[] = { |
|
395 MK(0, 0, 1, 0), |
|
396 MK(0, 1, 1, 1), |
|
397 MK(0, 0, 1, 0), |
|
398 MK(0, 1, 1, 2), |
|
399 ME(1) |
|
400 }; |
|
401 |
|
402 static const BubbleMovement _bubble_float_nw[] = { |
|
403 MK(0, 0, 1, 0), |
|
404 MK(0, -1, 1, 1), |
|
405 MK(0, 0, 1, 0), |
|
406 MK(0, -1, 1, 2), |
|
407 ME(1) |
|
408 }; |
|
409 |
|
410 static const BubbleMovement _bubble_burst[] = { |
|
411 MK(0, 0, 1, 2), |
|
412 MK(0, 0, 1, 7), |
|
413 MK(0, 0, 1, 8), |
|
414 MK(0, 0, 1, 9), |
|
415 ME(0) |
|
416 }; |
|
417 |
|
418 static const BubbleMovement _bubble_absorb[] = { |
|
419 MK(0, 0, 1, 0), |
|
420 MK(0, 0, 1, 1), |
|
421 MK(0, 0, 1, 0), |
|
422 MK(0, 0, 1, 2), |
|
423 MK(0, 0, 1, 0), |
|
424 MK(0, 0, 1, 1), |
|
425 MK(0, 0, 1, 0), |
|
426 MK(0, 0, 1, 2), |
|
427 MK(0, 0, 1, 0), |
|
428 MK(0, 0, 1, 1), |
|
429 MK(0, 0, 1, 0), |
|
430 MK(0, 0, 1, 2), |
|
431 MK(0, 0, 1, 0), |
|
432 MK(0, 0, 1, 1), |
|
433 MK(0, 0, 1, 0), |
|
434 MK(0, 0, 1, 2), |
|
435 MK(0, 0, 1, 0), |
|
436 MK(0, 0, 1, 1), |
|
437 MK(0, 0, 1, 0), |
|
438 MK(0, 0, 1, 2), |
|
439 MK(0, 0, 1, 0), |
|
440 MK(0, 0, 1, 1), |
|
441 MK(0, 0, 1, 0), |
|
442 MK(0, 0, 1, 2), |
|
443 MK(0, 0, 1, 0), |
|
444 MK(0, 0, 1, 1), |
|
445 MK(0, 0, 1, 0), |
|
446 MK(0, 0, 1, 2), |
|
447 MK(0, 0, 1, 0), |
|
448 MK(0, 0, 1, 1), |
|
449 MK(0, 0, 1, 0), |
|
450 MK(0, 0, 1, 2), |
|
451 MK(0, 0, 1, 0), |
|
452 MK(0, 0, 1, 1), |
|
453 MK(0, 0, 1, 0), |
|
454 MK(0, 0, 1, 2), |
|
455 MK(0, 0, 1, 0), |
|
456 MK(0, 0, 1, 1), |
|
457 MK(0, 0, 1, 0), |
|
458 MK(0, 0, 1, 2), |
|
459 MK(0, 0, 1, 0), |
|
460 MK(0, 0, 1, 1), |
|
461 MK(0, 0, 1, 0), |
|
462 MK(0, 0, 1, 2), |
|
463 MK(0, 0, 1, 0), |
|
464 MK(0, 0, 1, 1), |
|
465 MK(0, 0, 1, 0), |
|
466 MK(0, 0, 1, 2), |
|
467 MK(0, 0, 1, 0), |
|
468 MK(0, 0, 1, 1), |
|
469 MK(0, 0, 1, 0), |
|
470 MK(0, 0, 1, 2), |
|
471 MK(0, 0, 1, 0), |
|
472 MK(0, 0, 1, 1), |
|
473 MK(0, 0, 1, 0), |
|
474 MK(0, 0, 1, 2), |
|
475 MK(0, 0, 1, 0), |
|
476 MK(0, 0, 1, 1), |
|
477 MK(0, 0, 1, 0), |
|
478 MK(0, 0, 1, 2), |
|
479 MK(0, 0, 1, 0), |
|
480 MK(0, 0, 1, 1), |
|
481 MK(2, 1, 3, 0), |
|
482 MK(1, 1, 3, 1), |
|
483 MK(2, 1, 3, 0), |
|
484 MK(1, 1, 3, 2), |
|
485 MK(2, 1, 3, 0), |
|
486 MK(1, 1, 3, 1), |
|
487 MK(2, 1, 3, 0), |
|
488 MK(1, 0, 1, 2), |
|
489 MK(0, 0, 1, 0), |
|
490 MK(1, 0, 1, 1), |
|
491 MK(0, 0, 1, 0), |
|
492 MK(1, 0, 1, 2), |
|
493 MK(0, 0, 1, 0), |
|
494 MK(1, 0, 1, 1), |
|
495 MK(0, 0, 1, 0), |
|
496 MK(1, 0, 1, 2), |
|
497 ME(2), |
|
498 MK(0, 0, 0, 0xA), |
|
499 MK(0, 0, 0, 0xB), |
|
500 MK(0, 0, 0, 0xC), |
|
501 MK(0, 0, 0, 0xD), |
|
502 MK(0, 0, 0, 0xE), |
|
503 ME(0) |
|
504 }; |
|
505 #undef ME |
|
506 #undef MK |
|
507 |
|
508 static const BubbleMovement * const _bubble_movement[] = { |
|
509 _bubble_float_sw, |
|
510 _bubble_float_ne, |
|
511 _bubble_float_se, |
|
512 _bubble_float_nw, |
|
513 _bubble_burst, |
|
514 _bubble_absorb, |
|
515 }; |
|
516 |
|
517 static void BubbleTick(Vehicle *v) |
|
518 { |
|
519 /* |
|
520 * Warning: those effects can NOT use Random(), and have to use |
|
521 * InteractiveRandom(), because somehow someone forgot to save |
|
522 * spritenum to the savegame, and so it will cause desyncs in |
|
523 * multiplayer!! (that is: in ToyLand) |
|
524 */ |
|
525 uint et; |
|
526 |
|
527 v->progress++; |
|
528 if ((v->progress & 3) != 0) return; |
|
529 |
|
530 BeginVehicleMove(v); |
|
531 |
|
532 if (v->spritenum == 0) { |
|
533 v->cur_image++; |
|
534 if (v->cur_image < SPR_BUBBLE_GENERATE_3) { |
|
535 VehiclePositionChanged(v); |
|
536 EndVehicleMove(v); |
|
537 return; |
|
538 } |
|
539 if (v->u.effect.animation_substate != 0) { |
|
540 v->spritenum = GB(InteractiveRandom(), 0, 2) + 1; |
|
541 } else { |
|
542 v->spritenum = 6; |
|
543 } |
|
544 et = 0; |
|
545 } else { |
|
546 et = v->engine_type + 1; |
|
547 } |
|
548 |
|
549 const BubbleMovement *b = &_bubble_movement[v->spritenum - 1][et]; |
|
550 |
|
551 if (b->y == 4 && b->x == 0) { |
|
552 EndVehicleMove(v); |
|
553 delete v; |
|
554 return; |
|
555 } |
|
556 |
|
557 if (b->y == 4 && b->x == 1) { |
|
558 if (v->z_pos > 180 || Chance16I(1, 96, InteractiveRandom())) { |
|
559 v->spritenum = 5; |
|
560 SndPlayVehicleFx(SND_2F_POP, v); |
|
561 } |
|
562 et = 0; |
|
563 } |
|
564 |
|
565 if (b->y == 4 && b->x == 2) { |
|
566 TileIndex tile; |
|
567 |
|
568 et++; |
|
569 SndPlayVehicleFx(SND_31_EXTRACT, v); |
|
570 |
|
571 tile = TileVirtXY(v->x_pos, v->y_pos); |
|
572 if (IsTileType(tile, MP_INDUSTRY) && GetIndustryGfx(tile) == GFX_BUBBLE_CATCHER) AddAnimatedTile(tile); |
|
573 } |
|
574 |
|
575 v->engine_type = et; |
|
576 b = &_bubble_movement[v->spritenum - 1][et]; |
|
577 |
|
578 v->x_pos += b->x; |
|
579 v->y_pos += b->y; |
|
580 v->z_pos += b->z; |
|
581 v->cur_image = SPR_BUBBLE_0 + b->image; |
|
582 |
|
583 VehiclePositionChanged(v); |
|
584 EndVehicleMove(v); |
|
585 } |
|
586 |
|
587 |
|
588 typedef void EffectInitProc(Vehicle *v); |
|
589 typedef void EffectTickProc(Vehicle *v); |
|
590 |
|
591 static EffectInitProc * const _effect_init_procs[] = { |
|
592 ChimneySmokeInit, |
|
593 SteamSmokeInit, |
|
594 DieselSmokeInit, |
|
595 ElectricSparkInit, |
|
596 SmokeInit, |
|
597 ExplosionLargeInit, |
|
598 BreakdownSmokeInit, |
|
599 ExplosionSmallInit, |
|
600 BulldozerInit, |
|
601 BubbleInit, |
|
602 }; |
|
603 |
|
604 static EffectTickProc * const _effect_tick_procs[] = { |
|
605 ChimneySmokeTick, |
|
606 SteamSmokeTick, |
|
607 DieselSmokeTick, |
|
608 ElectricSparkTick, |
|
609 SmokeTick, |
|
610 ExplosionLargeTick, |
|
611 BreakdownSmokeTick, |
|
612 ExplosionSmallTick, |
|
613 BulldozerTick, |
|
614 BubbleTick, |
|
615 }; |
|
616 |
|
617 |
|
618 Vehicle *CreateEffectVehicle(int x, int y, int z, EffectVehicleType type) |
|
619 { |
|
620 Vehicle *v = new EffectVehicle(); |
|
621 if (v != NULL) { |
|
622 v->subtype = type; |
|
623 v->x_pos = x; |
|
624 v->y_pos = y; |
|
625 v->z_pos = z; |
|
626 v->tile = 0; |
|
627 v->UpdateDeltaXY(INVALID_DIR); |
|
628 v->vehstatus = VS_UNCLICKABLE; |
|
629 |
|
630 _effect_init_procs[type](v); |
|
631 |
|
632 VehiclePositionChanged(v); |
|
633 BeginVehicleMove(v); |
|
634 EndVehicleMove(v); |
|
635 } |
|
636 return v; |
|
637 } |
|
638 |
|
639 Vehicle *CreateEffectVehicleAbove(int x, int y, int z, EffectVehicleType type) |
|
640 { |
|
641 int safe_x = Clamp(x, 0, MapMaxX() * TILE_SIZE); |
|
642 int safe_y = Clamp(y, 0, MapMaxY() * TILE_SIZE); |
|
643 return CreateEffectVehicle(x, y, GetSlopeZ(safe_x, safe_y) + z, type); |
|
644 } |
|
645 |
|
646 Vehicle *CreateEffectVehicleRel(const Vehicle *v, int x, int y, int z, EffectVehicleType type) |
|
647 { |
|
648 return CreateEffectVehicle(v->x_pos + x, v->y_pos + y, v->z_pos + z, type); |
|
649 } |
|
650 |
|
651 void EffectVehicle::Tick() |
|
652 { |
|
653 _effect_tick_procs[this->subtype](this); |
|
654 } |
|
655 |
|
656 void EffectVehicle::UpdateDeltaXY(Direction direction) |
|
657 { |
|
658 this->x_offs = 0; |
|
659 this->y_offs = 0; |
|
660 this->x_extent = 1; |
|
661 this->y_extent = 1; |
|
662 this->z_extent = 1; |
|
663 } |