effectvehicle.cpp

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

Generated on Mon May 9 05:18:52 2011 for OpenTTD by  doxygen 1.6.1