effectvehicle.cpp

Go to the documentation of this file.
00001 /* $Id: effectvehicle.cpp 14422 2008-09-30 20:51:04Z rubidium $ */
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 }

Generated on Fri Nov 21 19:01:32 2008 for openttd by  doxygen 1.5.6