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