effectvehicle.cpp

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

Generated on Mon Mar 9 23:33:46 2009 for openttd by  doxygen 1.5.6