src/effectvehicle.cpp
changeset 10272 2014f0bdc800
parent 10271 a20997d33fe8
child 10429 1b99254f9607
equal deleted inserted replaced
10271:a20997d33fe8 10272:2014f0bdc800
       
     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 }