effectvehicle.cpp

Go to the documentation of this file.
00001 /* $Id: effectvehicle.cpp 15676 2009-03-11 20:43:14Z rubidium $ */
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 }

Generated on Mon May 11 15:48:03 2009 for OpenTTD by  doxygen 1.5.6