00001
00002
00005 #include "stdafx.h"
00006 #include "openttd.h"
00007 #include "road_map.h"
00008 #include "roadveh.h"
00009 #include "ship.h"
00010 #include "spritecache.h"
00011 #include "tile_cmd.h"
00012 #include "landscape.h"
00013 #include "timetable.h"
00014 #include "viewport_func.h"
00015 #include "gfx_func.h"
00016 #include "news_func.h"
00017 #include "command_func.h"
00018 #include "saveload.h"
00019 #include "company_func.h"
00020 #include "debug.h"
00021 #include "vehicle_gui.h"
00022 #include "rail_type.h"
00023 #include "train.h"
00024 #include "aircraft.h"
00025 #include "industry_map.h"
00026 #include "station_map.h"
00027 #include "water_map.h"
00028 #include "yapf/yapf.h"
00029 #include "newgrf_callbacks.h"
00030 #include "newgrf_engine.h"
00031 #include "newgrf_sound.h"
00032 #include "group.h"
00033 #include "order_func.h"
00034 #include "strings_func.h"
00035 #include "zoom_func.h"
00036 #include "functions.h"
00037 #include "date_func.h"
00038 #include "window_func.h"
00039 #include "vehicle_func.h"
00040 #include "signal_func.h"
00041 #include "sound_func.h"
00042 #include "variables.h"
00043 #include "autoreplace_func.h"
00044 #include "autoreplace_gui.h"
00045 #include "string_func.h"
00046 #include "settings_type.h"
00047 #include "oldpool_func.h"
00048 #include "depot_map.h"
00049 #include "animated_tile_func.h"
00050 #include "effectvehicle_base.h"
00051 #include "effectvehicle_func.h"
00052
00053 #include "table/sprites.h"
00054 #include "table/strings.h"
00055
00056 static void ChimneySmokeInit(Vehicle *v)
00057 {
00058 uint32 r = Random();
00059 v->cur_image = SPR_CHIMNEY_SMOKE_0 + GB(r, 0, 3);
00060 v->progress = GB(r, 16, 3);
00061 }
00062
00063 static void ChimneySmokeTick(Vehicle *v)
00064 {
00065 if (v->progress > 0) {
00066 v->progress--;
00067 } else {
00068 BeginVehicleMove(v);
00069
00070 TileIndex tile = TileVirtXY(v->x_pos, v->y_pos);
00071 if (!IsTileType(tile, MP_INDUSTRY)) {
00072 EndVehicleMove(v);
00073 delete v;
00074 return;
00075 }
00076
00077 if (v->cur_image != SPR_CHIMNEY_SMOKE_7) {
00078 v->cur_image++;
00079 } else {
00080 v->cur_image = SPR_CHIMNEY_SMOKE_0;
00081 }
00082 v->progress = 7;
00083 VehiclePositionChanged(v);
00084 EndVehicleMove(v);
00085 }
00086 }
00087
00088 static void SteamSmokeInit(Vehicle *v)
00089 {
00090 v->cur_image = SPR_STEAM_SMOKE_0;
00091 v->progress = 12;
00092 }
00093
00094 static void SteamSmokeTick(Vehicle *v)
00095 {
00096 bool moved = false;
00097
00098 BeginVehicleMove(v);
00099
00100 v->progress++;
00101
00102 if ((v->progress & 7) == 0) {
00103 v->z_pos++;
00104 moved = true;
00105 }
00106
00107 if ((v->progress & 0xF) == 4) {
00108 if (v->cur_image != SPR_STEAM_SMOKE_4) {
00109 v->cur_image++;
00110 } else {
00111 EndVehicleMove(v);
00112 delete v;
00113 return;
00114 }
00115 moved = true;
00116 }
00117
00118 if (moved) {
00119 VehiclePositionChanged(v);
00120 EndVehicleMove(v);
00121 }
00122 }
00123
00124 static void DieselSmokeInit(Vehicle *v)
00125 {
00126 v->cur_image = SPR_DIESEL_SMOKE_0;
00127 v->progress = 0;
00128 }
00129
00130 static void DieselSmokeTick(Vehicle *v)
00131 {
00132 v->progress++;
00133
00134 if ((v->progress & 3) == 0) {
00135 BeginVehicleMove(v);
00136 v->z_pos++;
00137 VehiclePositionChanged(v);
00138 EndVehicleMove(v);
00139 } else if ((v->progress & 7) == 1) {
00140 BeginVehicleMove(v);
00141 if (v->cur_image != SPR_DIESEL_SMOKE_5) {
00142 v->cur_image++;
00143 VehiclePositionChanged(v);
00144 EndVehicleMove(v);
00145 } else {
00146 EndVehicleMove(v);
00147 delete v;
00148 }
00149 }
00150 }
00151
00152 static void ElectricSparkInit(Vehicle *v)
00153 {
00154 v->cur_image = SPR_ELECTRIC_SPARK_0;
00155 v->progress = 1;
00156 }
00157
00158 static void ElectricSparkTick(Vehicle *v)
00159 {
00160 if (v->progress < 2) {
00161 v->progress++;
00162 } else {
00163 v->progress = 0;
00164 BeginVehicleMove(v);
00165 if (v->cur_image != SPR_ELECTRIC_SPARK_5) {
00166 v->cur_image++;
00167 VehiclePositionChanged(v);
00168 EndVehicleMove(v);
00169 } else {
00170 EndVehicleMove(v);
00171 delete v;
00172 }
00173 }
00174 }
00175
00176 static void SmokeInit(Vehicle *v)
00177 {
00178 v->cur_image = SPR_SMOKE_0;
00179 v->progress = 12;
00180 }
00181
00182 static void SmokeTick(Vehicle *v)
00183 {
00184 bool moved = false;
00185
00186 BeginVehicleMove(v);
00187
00188 v->progress++;
00189
00190 if ((v->progress & 3) == 0) {
00191 v->z_pos++;
00192 moved = true;
00193 }
00194
00195 if ((v->progress & 0xF) == 4) {
00196 if (v->cur_image != SPR_SMOKE_4) {
00197 v->cur_image++;
00198 } else {
00199 EndVehicleMove(v);
00200 delete v;
00201 return;
00202 }
00203 moved = true;
00204 }
00205
00206 if (moved) {
00207 VehiclePositionChanged(v);
00208 EndVehicleMove(v);
00209 }
00210 }
00211
00212 static void ExplosionLargeInit(Vehicle *v)
00213 {
00214 v->cur_image = SPR_EXPLOSION_LARGE_0;
00215 v->progress = 0;
00216 }
00217
00218 static void ExplosionLargeTick(Vehicle *v)
00219 {
00220 v->progress++;
00221 if ((v->progress & 3) == 0) {
00222 BeginVehicleMove(v);
00223 if (v->cur_image != SPR_EXPLOSION_LARGE_F) {
00224 v->cur_image++;
00225 VehiclePositionChanged(v);
00226 EndVehicleMove(v);
00227 } else {
00228 EndVehicleMove(v);
00229 delete v;
00230 }
00231 }
00232 }
00233
00234 static void BreakdownSmokeInit(Vehicle *v)
00235 {
00236 v->cur_image = SPR_BREAKDOWN_SMOKE_0;
00237 v->progress = 0;
00238 }
00239
00240 static void BreakdownSmokeTick(Vehicle *v)
00241 {
00242 v->progress++;
00243 if ((v->progress & 7) == 0) {
00244 BeginVehicleMove(v);
00245 if (v->cur_image != SPR_BREAKDOWN_SMOKE_3) {
00246 v->cur_image++;
00247 } else {
00248 v->cur_image = SPR_BREAKDOWN_SMOKE_0;
00249 }
00250 VehiclePositionChanged(v);
00251 EndVehicleMove(v);
00252 }
00253
00254 v->u.effect.animation_state--;
00255 if (v->u.effect.animation_state == 0) {
00256 BeginVehicleMove(v);
00257 EndVehicleMove(v);
00258 delete v;
00259 }
00260 }
00261
00262 static void ExplosionSmallInit(Vehicle *v)
00263 {
00264 v->cur_image = SPR_EXPLOSION_SMALL_0;
00265 v->progress = 0;
00266 }
00267
00268 static void ExplosionSmallTick(Vehicle *v)
00269 {
00270 v->progress++;
00271 if ((v->progress & 3) == 0) {
00272 BeginVehicleMove(v);
00273 if (v->cur_image != SPR_EXPLOSION_SMALL_B) {
00274 v->cur_image++;
00275 VehiclePositionChanged(v);
00276 EndVehicleMove(v);
00277 } else {
00278 EndVehicleMove(v);
00279 delete v;
00280 }
00281 }
00282 }
00283
00284 static void BulldozerInit(Vehicle *v)
00285 {
00286 v->cur_image = SPR_BULLDOZER_NE;
00287 v->progress = 0;
00288 v->u.effect.animation_state = 0;
00289 v->u.effect.animation_substate = 0;
00290 }
00291
00292 struct BulldozerMovement {
00293 byte direction:2;
00294 byte image:2;
00295 byte duration:3;
00296 };
00297
00298 static const BulldozerMovement _bulldozer_movement[] = {
00299 { 0, 0, 4 },
00300 { 3, 3, 4 },
00301 { 2, 2, 7 },
00302 { 0, 2, 7 },
00303 { 1, 1, 3 },
00304 { 2, 2, 7 },
00305 { 0, 2, 7 },
00306 { 1, 1, 3 },
00307 { 2, 2, 7 },
00308 { 0, 2, 7 },
00309 { 3, 3, 6 },
00310 { 2, 2, 6 },
00311 { 1, 1, 7 },
00312 { 3, 1, 7 },
00313 { 0, 0, 3 },
00314 { 1, 1, 7 },
00315 { 3, 1, 7 },
00316 { 0, 0, 3 },
00317 { 1, 1, 7 },
00318 { 3, 1, 7 }
00319 };
00320
00321 static const struct {
00322 int8 x;
00323 int8 y;
00324 } _inc_by_dir[] = {
00325 { -1, 0 },
00326 { 0, 1 },
00327 { 1, 0 },
00328 { 0, -1 }
00329 };
00330
00331 static void BulldozerTick(Vehicle *v)
00332 {
00333 v->progress++;
00334 if ((v->progress & 7) == 0) {
00335 const BulldozerMovement* b = &_bulldozer_movement[v->u.effect.animation_state];
00336
00337 BeginVehicleMove(v);
00338
00339 v->cur_image = SPR_BULLDOZER_NE + b->image;
00340
00341 v->x_pos += _inc_by_dir[b->direction].x;
00342 v->y_pos += _inc_by_dir[b->direction].y;
00343
00344 v->u.effect.animation_substate++;
00345 if (v->u.effect.animation_substate >= b->duration) {
00346 v->u.effect.animation_substate = 0;
00347 v->u.effect.animation_state++;
00348 if (v->u.effect.animation_state == lengthof(_bulldozer_movement)) {
00349 EndVehicleMove(v);
00350 delete v;
00351 return;
00352 }
00353 }
00354 VehiclePositionChanged(v);
00355 EndVehicleMove(v);
00356 }
00357 }
00358
00359 static void BubbleInit(Vehicle *v)
00360 {
00361 v->cur_image = SPR_BUBBLE_GENERATE_0;
00362 v->spritenum = 0;
00363 v->progress = 0;
00364 }
00365
00366 struct BubbleMovement {
00367 int8 x:4;
00368 int8 y:4;
00369 int8 z:4;
00370 byte image:4;
00371 };
00372
00373 #define MK(x, y, z, i) { x, y, z, i }
00374 #define ME(i) { i, 4, 0, 0 }
00375
00376 static const BubbleMovement _bubble_float_sw[] = {
00377 MK(0, 0, 1, 0),
00378 MK(1, 0, 1, 1),
00379 MK(0, 0, 1, 0),
00380 MK(1, 0, 1, 2),
00381 ME(1)
00382 };
00383
00384
00385 static const BubbleMovement _bubble_float_ne[] = {
00386 MK( 0, 0, 1, 0),
00387 MK(-1, 0, 1, 1),
00388 MK( 0, 0, 1, 0),
00389 MK(-1, 0, 1, 2),
00390 ME(1)
00391 };
00392
00393 static const BubbleMovement _bubble_float_se[] = {
00394 MK(0, 0, 1, 0),
00395 MK(0, 1, 1, 1),
00396 MK(0, 0, 1, 0),
00397 MK(0, 1, 1, 2),
00398 ME(1)
00399 };
00400
00401 static const BubbleMovement _bubble_float_nw[] = {
00402 MK(0, 0, 1, 0),
00403 MK(0, -1, 1, 1),
00404 MK(0, 0, 1, 0),
00405 MK(0, -1, 1, 2),
00406 ME(1)
00407 };
00408
00409 static const BubbleMovement _bubble_burst[] = {
00410 MK(0, 0, 1, 2),
00411 MK(0, 0, 1, 7),
00412 MK(0, 0, 1, 8),
00413 MK(0, 0, 1, 9),
00414 ME(0)
00415 };
00416
00417 static const BubbleMovement _bubble_absorb[] = {
00418 MK(0, 0, 1, 0),
00419 MK(0, 0, 1, 1),
00420 MK(0, 0, 1, 0),
00421 MK(0, 0, 1, 2),
00422 MK(0, 0, 1, 0),
00423 MK(0, 0, 1, 1),
00424 MK(0, 0, 1, 0),
00425 MK(0, 0, 1, 2),
00426 MK(0, 0, 1, 0),
00427 MK(0, 0, 1, 1),
00428 MK(0, 0, 1, 0),
00429 MK(0, 0, 1, 2),
00430 MK(0, 0, 1, 0),
00431 MK(0, 0, 1, 1),
00432 MK(0, 0, 1, 0),
00433 MK(0, 0, 1, 2),
00434 MK(0, 0, 1, 0),
00435 MK(0, 0, 1, 1),
00436 MK(0, 0, 1, 0),
00437 MK(0, 0, 1, 2),
00438 MK(0, 0, 1, 0),
00439 MK(0, 0, 1, 1),
00440 MK(0, 0, 1, 0),
00441 MK(0, 0, 1, 2),
00442 MK(0, 0, 1, 0),
00443 MK(0, 0, 1, 1),
00444 MK(0, 0, 1, 0),
00445 MK(0, 0, 1, 2),
00446 MK(0, 0, 1, 0),
00447 MK(0, 0, 1, 1),
00448 MK(0, 0, 1, 0),
00449 MK(0, 0, 1, 2),
00450 MK(0, 0, 1, 0),
00451 MK(0, 0, 1, 1),
00452 MK(0, 0, 1, 0),
00453 MK(0, 0, 1, 2),
00454 MK(0, 0, 1, 0),
00455 MK(0, 0, 1, 1),
00456 MK(0, 0, 1, 0),
00457 MK(0, 0, 1, 2),
00458 MK(0, 0, 1, 0),
00459 MK(0, 0, 1, 1),
00460 MK(0, 0, 1, 0),
00461 MK(0, 0, 1, 2),
00462 MK(0, 0, 1, 0),
00463 MK(0, 0, 1, 1),
00464 MK(0, 0, 1, 0),
00465 MK(0, 0, 1, 2),
00466 MK(0, 0, 1, 0),
00467 MK(0, 0, 1, 1),
00468 MK(0, 0, 1, 0),
00469 MK(0, 0, 1, 2),
00470 MK(0, 0, 1, 0),
00471 MK(0, 0, 1, 1),
00472 MK(0, 0, 1, 0),
00473 MK(0, 0, 1, 2),
00474 MK(0, 0, 1, 0),
00475 MK(0, 0, 1, 1),
00476 MK(0, 0, 1, 0),
00477 MK(0, 0, 1, 2),
00478 MK(0, 0, 1, 0),
00479 MK(0, 0, 1, 1),
00480 MK(2, 1, 3, 0),
00481 MK(1, 1, 3, 1),
00482 MK(2, 1, 3, 0),
00483 MK(1, 1, 3, 2),
00484 MK(2, 1, 3, 0),
00485 MK(1, 1, 3, 1),
00486 MK(2, 1, 3, 0),
00487 MK(1, 0, 1, 2),
00488 MK(0, 0, 1, 0),
00489 MK(1, 0, 1, 1),
00490 MK(0, 0, 1, 0),
00491 MK(1, 0, 1, 2),
00492 MK(0, 0, 1, 0),
00493 MK(1, 0, 1, 1),
00494 MK(0, 0, 1, 0),
00495 MK(1, 0, 1, 2),
00496 ME(2),
00497 MK(0, 0, 0, 0xA),
00498 MK(0, 0, 0, 0xB),
00499 MK(0, 0, 0, 0xC),
00500 MK(0, 0, 0, 0xD),
00501 MK(0, 0, 0, 0xE),
00502 ME(0)
00503 };
00504 #undef ME
00505 #undef MK
00506
00507 static const BubbleMovement * const _bubble_movement[] = {
00508 _bubble_float_sw,
00509 _bubble_float_ne,
00510 _bubble_float_se,
00511 _bubble_float_nw,
00512 _bubble_burst,
00513 _bubble_absorb,
00514 };
00515
00516 static void BubbleTick(Vehicle *v)
00517 {
00518 uint et;
00519
00520 v->progress++;
00521 if ((v->progress & 3) != 0) return;
00522
00523 BeginVehicleMove(v);
00524
00525 if (v->spritenum == 0) {
00526 v->cur_image++;
00527 if (v->cur_image < SPR_BUBBLE_GENERATE_3) {
00528 VehiclePositionChanged(v);
00529 EndVehicleMove(v);
00530 return;
00531 }
00532 if (v->u.effect.animation_substate != 0) {
00533 v->spritenum = GB(Random(), 0, 2) + 1;
00534 } else {
00535 v->spritenum = 6;
00536 }
00537 et = 0;
00538 } else {
00539 et = v->engine_type + 1;
00540 }
00541
00542 const BubbleMovement *b = &_bubble_movement[v->spritenum - 1][et];
00543
00544 if (b->y == 4 && b->x == 0) {
00545 EndVehicleMove(v);
00546 delete v;
00547 return;
00548 }
00549
00550 if (b->y == 4 && b->x == 1) {
00551 if (v->z_pos > 180 || Chance16I(1, 96, Random())) {
00552 v->spritenum = 5;
00553 SndPlayVehicleFx(SND_2F_POP, v);
00554 }
00555 et = 0;
00556 }
00557
00558 if (b->y == 4 && b->x == 2) {
00559 TileIndex tile;
00560
00561 et++;
00562 SndPlayVehicleFx(SND_31_EXTRACT, v);
00563
00564 tile = TileVirtXY(v->x_pos, v->y_pos);
00565 if (IsTileType(tile, MP_INDUSTRY) && GetIndustryGfx(tile) == GFX_BUBBLE_CATCHER) AddAnimatedTile(tile);
00566 }
00567
00568 v->engine_type = et;
00569 b = &_bubble_movement[v->spritenum - 1][et];
00570
00571 v->x_pos += b->x;
00572 v->y_pos += b->y;
00573 v->z_pos += b->z;
00574 v->cur_image = SPR_BUBBLE_0 + b->image;
00575
00576 VehiclePositionChanged(v);
00577 EndVehicleMove(v);
00578 }
00579
00580
00581 typedef void EffectInitProc(Vehicle *v);
00582 typedef void EffectTickProc(Vehicle *v);
00583
00584 static EffectInitProc * const _effect_init_procs[] = {
00585 ChimneySmokeInit,
00586 SteamSmokeInit,
00587 DieselSmokeInit,
00588 ElectricSparkInit,
00589 SmokeInit,
00590 ExplosionLargeInit,
00591 BreakdownSmokeInit,
00592 ExplosionSmallInit,
00593 BulldozerInit,
00594 BubbleInit,
00595 };
00596
00597 static EffectTickProc * const _effect_tick_procs[] = {
00598 ChimneySmokeTick,
00599 SteamSmokeTick,
00600 DieselSmokeTick,
00601 ElectricSparkTick,
00602 SmokeTick,
00603 ExplosionLargeTick,
00604 BreakdownSmokeTick,
00605 ExplosionSmallTick,
00606 BulldozerTick,
00607 BubbleTick,
00608 };
00609
00610
00611 Vehicle *CreateEffectVehicle(int x, int y, int z, EffectVehicleType type)
00612 {
00613 Vehicle *v = new EffectVehicle();
00614 if (v != NULL) {
00615 v->subtype = type;
00616 v->x_pos = x;
00617 v->y_pos = y;
00618 v->z_pos = z;
00619 v->tile = 0;
00620 v->UpdateDeltaXY(INVALID_DIR);
00621 v->vehstatus = VS_UNCLICKABLE;
00622
00623 _effect_init_procs[type](v);
00624
00625 VehiclePositionChanged(v);
00626 BeginVehicleMove(v);
00627 EndVehicleMove(v);
00628 }
00629 return v;
00630 }
00631
00632 Vehicle *CreateEffectVehicleAbove(int x, int y, int z, EffectVehicleType type)
00633 {
00634 int safe_x = Clamp(x, 0, MapMaxX() * TILE_SIZE);
00635 int safe_y = Clamp(y, 0, MapMaxY() * TILE_SIZE);
00636 return CreateEffectVehicle(x, y, GetSlopeZ(safe_x, safe_y) + z, type);
00637 }
00638
00639 Vehicle *CreateEffectVehicleRel(const Vehicle *v, int x, int y, int z, EffectVehicleType type)
00640 {
00641 return CreateEffectVehicle(v->x_pos + x, v->y_pos + y, v->z_pos + z, type);
00642 }
00643
00644 void EffectVehicle::Tick()
00645 {
00646 _effect_tick_procs[this->subtype](this);
00647 }
00648
00649 void EffectVehicle::UpdateDeltaXY(Direction direction)
00650 {
00651 this->x_offs = 0;
00652 this->y_offs = 0;
00653 this->x_extent = 1;
00654 this->y_extent = 1;
00655 this->z_extent = 1;
00656 }