summaryrefslogtreecommitdiff
path: root/src/effectvehicle.cpp
diff options
context:
space:
mode:
authorrubidium <rubidium@openttd.org>2008-04-20 11:12:07 +0000
committerrubidium <rubidium@openttd.org>2008-04-20 11:12:07 +0000
commitb139756e2ba70431364b21a5b49950fc991dbdef (patch)
treedd68b4e6a0cf26c8d4091dc8be264021cfb88c35 /src/effectvehicle.cpp
parentf55ffd14bdaa85f9eb7c22c442f46169f63137be (diff)
downloadopenttd-b139756e2ba70431364b21a5b49950fc991dbdef.tar.xz
(svn r12804) -Codechange: move the effect vehicle handling out of vehicle.cpp
Diffstat (limited to 'src/effectvehicle.cpp')
-rw-r--r--src/effectvehicle.cpp663
1 files changed, 663 insertions, 0 deletions
diff --git a/src/effectvehicle.cpp b/src/effectvehicle.cpp
new file mode 100644
index 000000000..4b600ea83
--- /dev/null
+++ b/src/effectvehicle.cpp
@@ -0,0 +1,663 @@
+/* $Id$ */
+
+/** @file vehicle.cpp */
+
+#include "stdafx.h"
+#include "openttd.h"
+#include "road_map.h"
+#include "roadveh.h"
+#include "ship.h"
+#include "spritecache.h"
+#include "tile_cmd.h"
+#include "landscape.h"
+#include "timetable.h"
+#include "viewport_func.h"
+#include "gfx_func.h"
+#include "news_func.h"
+#include "command_func.h"
+#include "saveload.h"
+#include "player_func.h"
+#include "debug.h"
+#include "vehicle_gui.h"
+#include "rail_type.h"
+#include "train.h"
+#include "aircraft.h"
+#include "industry_map.h"
+#include "station_map.h"
+#include "water_map.h"
+#include "network/network.h"
+#include "yapf/yapf.h"
+#include "newgrf_callbacks.h"
+#include "newgrf_engine.h"
+#include "newgrf_sound.h"
+#include "group.h"
+#include "order_func.h"
+#include "strings_func.h"
+#include "zoom_func.h"
+#include "functions.h"
+#include "date_func.h"
+#include "window_func.h"
+#include "vehicle_func.h"
+#include "signal_func.h"
+#include "sound_func.h"
+#include "variables.h"
+#include "autoreplace_func.h"
+#include "autoreplace_gui.h"
+#include "string_func.h"
+#include "settings_type.h"
+#include "oldpool_func.h"
+#include "depot_map.h"
+#include "animated_tile_func.h"
+#include "effectvehicle_base.h"
+#include "effectvehicle_func.h"
+
+#include "table/sprites.h"
+#include "table/strings.h"
+
+static void ChimneySmokeInit(Vehicle *v)
+{
+ uint32 r = Random();
+ v->cur_image = SPR_CHIMNEY_SMOKE_0 + GB(r, 0, 3);
+ v->progress = GB(r, 16, 3);
+}
+
+static void ChimneySmokeTick(Vehicle *v)
+{
+ if (v->progress > 0) {
+ v->progress--;
+ } else {
+ BeginVehicleMove(v);
+
+ TileIndex tile = TileVirtXY(v->x_pos, v->y_pos);
+ if (!IsTileType(tile, MP_INDUSTRY)) {
+ EndVehicleMove(v);
+ delete v;
+ return;
+ }
+
+ if (v->cur_image != SPR_CHIMNEY_SMOKE_7) {
+ v->cur_image++;
+ } else {
+ v->cur_image = SPR_CHIMNEY_SMOKE_0;
+ }
+ v->progress = 7;
+ VehiclePositionChanged(v);
+ EndVehicleMove(v);
+ }
+}
+
+static void SteamSmokeInit(Vehicle *v)
+{
+ v->cur_image = SPR_STEAM_SMOKE_0;
+ v->progress = 12;
+}
+
+static void SteamSmokeTick(Vehicle *v)
+{
+ bool moved = false;
+
+ BeginVehicleMove(v);
+
+ v->progress++;
+
+ if ((v->progress & 7) == 0) {
+ v->z_pos++;
+ moved = true;
+ }
+
+ if ((v->progress & 0xF) == 4) {
+ if (v->cur_image != SPR_STEAM_SMOKE_4) {
+ v->cur_image++;
+ } else {
+ EndVehicleMove(v);
+ delete v;
+ return;
+ }
+ moved = true;
+ }
+
+ if (moved) {
+ VehiclePositionChanged(v);
+ EndVehicleMove(v);
+ }
+}
+
+static void DieselSmokeInit(Vehicle *v)
+{
+ v->cur_image = SPR_DIESEL_SMOKE_0;
+ v->progress = 0;
+}
+
+static void DieselSmokeTick(Vehicle *v)
+{
+ v->progress++;
+
+ if ((v->progress & 3) == 0) {
+ BeginVehicleMove(v);
+ v->z_pos++;
+ VehiclePositionChanged(v);
+ EndVehicleMove(v);
+ } else if ((v->progress & 7) == 1) {
+ BeginVehicleMove(v);
+ if (v->cur_image != SPR_DIESEL_SMOKE_5) {
+ v->cur_image++;
+ VehiclePositionChanged(v);
+ EndVehicleMove(v);
+ } else {
+ EndVehicleMove(v);
+ delete v;
+ }
+ }
+}
+
+static void ElectricSparkInit(Vehicle *v)
+{
+ v->cur_image = SPR_ELECTRIC_SPARK_0;
+ v->progress = 1;
+}
+
+static void ElectricSparkTick(Vehicle *v)
+{
+ if (v->progress < 2) {
+ v->progress++;
+ } else {
+ v->progress = 0;
+ BeginVehicleMove(v);
+ if (v->cur_image != SPR_ELECTRIC_SPARK_5) {
+ v->cur_image++;
+ VehiclePositionChanged(v);
+ EndVehicleMove(v);
+ } else {
+ EndVehicleMove(v);
+ delete v;
+ }
+ }
+}
+
+static void SmokeInit(Vehicle *v)
+{
+ v->cur_image = SPR_SMOKE_0;
+ v->progress = 12;
+}
+
+static void SmokeTick(Vehicle *v)
+{
+ bool moved = false;
+
+ BeginVehicleMove(v);
+
+ v->progress++;
+
+ if ((v->progress & 3) == 0) {
+ v->z_pos++;
+ moved = true;
+ }
+
+ if ((v->progress & 0xF) == 4) {
+ if (v->cur_image != SPR_SMOKE_4) {
+ v->cur_image++;
+ } else {
+ EndVehicleMove(v);
+ delete v;
+ return;
+ }
+ moved = true;
+ }
+
+ if (moved) {
+ VehiclePositionChanged(v);
+ EndVehicleMove(v);
+ }
+}
+
+static void ExplosionLargeInit(Vehicle *v)
+{
+ v->cur_image = SPR_EXPLOSION_LARGE_0;
+ v->progress = 0;
+}
+
+static void ExplosionLargeTick(Vehicle *v)
+{
+ v->progress++;
+ if ((v->progress & 3) == 0) {
+ BeginVehicleMove(v);
+ if (v->cur_image != SPR_EXPLOSION_LARGE_F) {
+ v->cur_image++;
+ VehiclePositionChanged(v);
+ EndVehicleMove(v);
+ } else {
+ EndVehicleMove(v);
+ delete v;
+ }
+ }
+}
+
+static void BreakdownSmokeInit(Vehicle *v)
+{
+ v->cur_image = SPR_BREAKDOWN_SMOKE_0;
+ v->progress = 0;
+}
+
+static void BreakdownSmokeTick(Vehicle *v)
+{
+ v->progress++;
+ if ((v->progress & 7) == 0) {
+ BeginVehicleMove(v);
+ if (v->cur_image != SPR_BREAKDOWN_SMOKE_3) {
+ v->cur_image++;
+ } else {
+ v->cur_image = SPR_BREAKDOWN_SMOKE_0;
+ }
+ VehiclePositionChanged(v);
+ EndVehicleMove(v);
+ }
+
+ v->u.effect.animation_state--;
+ if (v->u.effect.animation_state == 0) {
+ BeginVehicleMove(v);
+ EndVehicleMove(v);
+ delete v;
+ }
+}
+
+static void ExplosionSmallInit(Vehicle *v)
+{
+ v->cur_image = SPR_EXPLOSION_SMALL_0;
+ v->progress = 0;
+}
+
+static void ExplosionSmallTick(Vehicle *v)
+{
+ v->progress++;
+ if ((v->progress & 3) == 0) {
+ BeginVehicleMove(v);
+ if (v->cur_image != SPR_EXPLOSION_SMALL_B) {
+ v->cur_image++;
+ VehiclePositionChanged(v);
+ EndVehicleMove(v);
+ } else {
+ EndVehicleMove(v);
+ delete v;
+ }
+ }
+}
+
+static void BulldozerInit(Vehicle *v)
+{
+ v->cur_image = SPR_BULLDOZER_NE;
+ v->progress = 0;
+ v->u.effect.animation_state = 0;
+ v->u.effect.animation_substate = 0;
+}
+
+struct BulldozerMovement {
+ byte direction:2;
+ byte image:2;
+ byte duration:3;
+};
+
+static const BulldozerMovement _bulldozer_movement[] = {
+ { 0, 0, 4 },
+ { 3, 3, 4 },
+ { 2, 2, 7 },
+ { 0, 2, 7 },
+ { 1, 1, 3 },
+ { 2, 2, 7 },
+ { 0, 2, 7 },
+ { 1, 1, 3 },
+ { 2, 2, 7 },
+ { 0, 2, 7 },
+ { 3, 3, 6 },
+ { 2, 2, 6 },
+ { 1, 1, 7 },
+ { 3, 1, 7 },
+ { 0, 0, 3 },
+ { 1, 1, 7 },
+ { 3, 1, 7 },
+ { 0, 0, 3 },
+ { 1, 1, 7 },
+ { 3, 1, 7 }
+};
+
+static const struct {
+ int8 x;
+ int8 y;
+} _inc_by_dir[] = {
+ { -1, 0 },
+ { 0, 1 },
+ { 1, 0 },
+ { 0, -1 }
+};
+
+static void BulldozerTick(Vehicle *v)
+{
+ v->progress++;
+ if ((v->progress & 7) == 0) {
+ const BulldozerMovement* b = &_bulldozer_movement[v->u.effect.animation_state];
+
+ BeginVehicleMove(v);
+
+ v->cur_image = SPR_BULLDOZER_NE + b->image;
+
+ v->x_pos += _inc_by_dir[b->direction].x;
+ v->y_pos += _inc_by_dir[b->direction].y;
+
+ v->u.effect.animation_substate++;
+ if (v->u.effect.animation_substate >= b->duration) {
+ v->u.effect.animation_substate = 0;
+ v->u.effect.animation_state++;
+ if (v->u.effect.animation_state == lengthof(_bulldozer_movement)) {
+ EndVehicleMove(v);
+ delete v;
+ return;
+ }
+ }
+ VehiclePositionChanged(v);
+ EndVehicleMove(v);
+ }
+}
+
+static void BubbleInit(Vehicle *v)
+{
+ v->cur_image = SPR_BUBBLE_GENERATE_0;
+ v->spritenum = 0;
+ v->progress = 0;
+}
+
+struct BubbleMovement {
+ int8 x:4;
+ int8 y:4;
+ int8 z:4;
+ byte image:4;
+};
+
+#define MK(x, y, z, i) { x, y, z, i }
+#define ME(i) { i, 4, 0, 0 }
+
+static const BubbleMovement _bubble_float_sw[] = {
+ MK(0, 0, 1, 0),
+ MK(1, 0, 1, 1),
+ MK(0, 0, 1, 0),
+ MK(1, 0, 1, 2),
+ ME(1)
+};
+
+
+static const BubbleMovement _bubble_float_ne[] = {
+ MK( 0, 0, 1, 0),
+ MK(-1, 0, 1, 1),
+ MK( 0, 0, 1, 0),
+ MK(-1, 0, 1, 2),
+ ME(1)
+};
+
+static const BubbleMovement _bubble_float_se[] = {
+ MK(0, 0, 1, 0),
+ MK(0, 1, 1, 1),
+ MK(0, 0, 1, 0),
+ MK(0, 1, 1, 2),
+ ME(1)
+};
+
+static const BubbleMovement _bubble_float_nw[] = {
+ MK(0, 0, 1, 0),
+ MK(0, -1, 1, 1),
+ MK(0, 0, 1, 0),
+ MK(0, -1, 1, 2),
+ ME(1)
+};
+
+static const BubbleMovement _bubble_burst[] = {
+ MK(0, 0, 1, 2),
+ MK(0, 0, 1, 7),
+ MK(0, 0, 1, 8),
+ MK(0, 0, 1, 9),
+ ME(0)
+};
+
+static const BubbleMovement _bubble_absorb[] = {
+ MK(0, 0, 1, 0),
+ MK(0, 0, 1, 1),
+ MK(0, 0, 1, 0),
+ MK(0, 0, 1, 2),
+ MK(0, 0, 1, 0),
+ MK(0, 0, 1, 1),
+ MK(0, 0, 1, 0),
+ MK(0, 0, 1, 2),
+ MK(0, 0, 1, 0),
+ MK(0, 0, 1, 1),
+ MK(0, 0, 1, 0),
+ MK(0, 0, 1, 2),
+ MK(0, 0, 1, 0),
+ MK(0, 0, 1, 1),
+ MK(0, 0, 1, 0),
+ MK(0, 0, 1, 2),
+ MK(0, 0, 1, 0),
+ MK(0, 0, 1, 1),
+ MK(0, 0, 1, 0),
+ MK(0, 0, 1, 2),
+ MK(0, 0, 1, 0),
+ MK(0, 0, 1, 1),
+ MK(0, 0, 1, 0),
+ MK(0, 0, 1, 2),
+ MK(0, 0, 1, 0),
+ MK(0, 0, 1, 1),
+ MK(0, 0, 1, 0),
+ MK(0, 0, 1, 2),
+ MK(0, 0, 1, 0),
+ MK(0, 0, 1, 1),
+ MK(0, 0, 1, 0),
+ MK(0, 0, 1, 2),
+ MK(0, 0, 1, 0),
+ MK(0, 0, 1, 1),
+ MK(0, 0, 1, 0),
+ MK(0, 0, 1, 2),
+ MK(0, 0, 1, 0),
+ MK(0, 0, 1, 1),
+ MK(0, 0, 1, 0),
+ MK(0, 0, 1, 2),
+ MK(0, 0, 1, 0),
+ MK(0, 0, 1, 1),
+ MK(0, 0, 1, 0),
+ MK(0, 0, 1, 2),
+ MK(0, 0, 1, 0),
+ MK(0, 0, 1, 1),
+ MK(0, 0, 1, 0),
+ MK(0, 0, 1, 2),
+ MK(0, 0, 1, 0),
+ MK(0, 0, 1, 1),
+ MK(0, 0, 1, 0),
+ MK(0, 0, 1, 2),
+ MK(0, 0, 1, 0),
+ MK(0, 0, 1, 1),
+ MK(0, 0, 1, 0),
+ MK(0, 0, 1, 2),
+ MK(0, 0, 1, 0),
+ MK(0, 0, 1, 1),
+ MK(0, 0, 1, 0),
+ MK(0, 0, 1, 2),
+ MK(0, 0, 1, 0),
+ MK(0, 0, 1, 1),
+ MK(2, 1, 3, 0),
+ MK(1, 1, 3, 1),
+ MK(2, 1, 3, 0),
+ MK(1, 1, 3, 2),
+ MK(2, 1, 3, 0),
+ MK(1, 1, 3, 1),
+ MK(2, 1, 3, 0),
+ MK(1, 0, 1, 2),
+ MK(0, 0, 1, 0),
+ MK(1, 0, 1, 1),
+ MK(0, 0, 1, 0),
+ MK(1, 0, 1, 2),
+ MK(0, 0, 1, 0),
+ MK(1, 0, 1, 1),
+ MK(0, 0, 1, 0),
+ MK(1, 0, 1, 2),
+ ME(2),
+ MK(0, 0, 0, 0xA),
+ MK(0, 0, 0, 0xB),
+ MK(0, 0, 0, 0xC),
+ MK(0, 0, 0, 0xD),
+ MK(0, 0, 0, 0xE),
+ ME(0)
+};
+#undef ME
+#undef MK
+
+static const BubbleMovement * const _bubble_movement[] = {
+ _bubble_float_sw,
+ _bubble_float_ne,
+ _bubble_float_se,
+ _bubble_float_nw,
+ _bubble_burst,
+ _bubble_absorb,
+};
+
+static void BubbleTick(Vehicle *v)
+{
+ /*
+ * Warning: those effects can NOT use Random(), and have to use
+ * InteractiveRandom(), because somehow someone forgot to save
+ * spritenum to the savegame, and so it will cause desyncs in
+ * multiplayer!! (that is: in ToyLand)
+ */
+ uint et;
+
+ v->progress++;
+ if ((v->progress & 3) != 0) return;
+
+ BeginVehicleMove(v);
+
+ if (v->spritenum == 0) {
+ v->cur_image++;
+ if (v->cur_image < SPR_BUBBLE_GENERATE_3) {
+ VehiclePositionChanged(v);
+ EndVehicleMove(v);
+ return;
+ }
+ if (v->u.effect.animation_substate != 0) {
+ v->spritenum = GB(InteractiveRandom(), 0, 2) + 1;
+ } else {
+ v->spritenum = 6;
+ }
+ et = 0;
+ } else {
+ et = v->engine_type + 1;
+ }
+
+ const BubbleMovement *b = &_bubble_movement[v->spritenum - 1][et];
+
+ if (b->y == 4 && b->x == 0) {
+ EndVehicleMove(v);
+ delete v;
+ return;
+ }
+
+ if (b->y == 4 && b->x == 1) {
+ if (v->z_pos > 180 || Chance16I(1, 96, InteractiveRandom())) {
+ v->spritenum = 5;
+ SndPlayVehicleFx(SND_2F_POP, v);
+ }
+ et = 0;
+ }
+
+ if (b->y == 4 && b->x == 2) {
+ TileIndex tile;
+
+ et++;
+ SndPlayVehicleFx(SND_31_EXTRACT, v);
+
+ tile = TileVirtXY(v->x_pos, v->y_pos);
+ if (IsTileType(tile, MP_INDUSTRY) && GetIndustryGfx(tile) == GFX_BUBBLE_CATCHER) AddAnimatedTile(tile);
+ }
+
+ v->engine_type = et;
+ b = &_bubble_movement[v->spritenum - 1][et];
+
+ v->x_pos += b->x;
+ v->y_pos += b->y;
+ v->z_pos += b->z;
+ v->cur_image = SPR_BUBBLE_0 + b->image;
+
+ VehiclePositionChanged(v);
+ EndVehicleMove(v);
+}
+
+
+typedef void EffectInitProc(Vehicle *v);
+typedef void EffectTickProc(Vehicle *v);
+
+static EffectInitProc * const _effect_init_procs[] = {
+ ChimneySmokeInit,
+ SteamSmokeInit,
+ DieselSmokeInit,
+ ElectricSparkInit,
+ SmokeInit,
+ ExplosionLargeInit,
+ BreakdownSmokeInit,
+ ExplosionSmallInit,
+ BulldozerInit,
+ BubbleInit,
+};
+
+static EffectTickProc * const _effect_tick_procs[] = {
+ ChimneySmokeTick,
+ SteamSmokeTick,
+ DieselSmokeTick,
+ ElectricSparkTick,
+ SmokeTick,
+ ExplosionLargeTick,
+ BreakdownSmokeTick,
+ ExplosionSmallTick,
+ BulldozerTick,
+ BubbleTick,
+};
+
+
+Vehicle *CreateEffectVehicle(int x, int y, int z, EffectVehicleType type)
+{
+ Vehicle *v = new EffectVehicle();
+ if (v != NULL) {
+ v->subtype = type;
+ v->x_pos = x;
+ v->y_pos = y;
+ v->z_pos = z;
+ v->tile = 0;
+ v->UpdateDeltaXY(INVALID_DIR);
+ v->vehstatus = VS_UNCLICKABLE;
+
+ _effect_init_procs[type](v);
+
+ VehiclePositionChanged(v);
+ BeginVehicleMove(v);
+ EndVehicleMove(v);
+ }
+ return v;
+}
+
+Vehicle *CreateEffectVehicleAbove(int x, int y, int z, EffectVehicleType type)
+{
+ int safe_x = Clamp(x, 0, MapMaxX() * TILE_SIZE);
+ int safe_y = Clamp(y, 0, MapMaxY() * TILE_SIZE);
+ return CreateEffectVehicle(x, y, GetSlopeZ(safe_x, safe_y) + z, type);
+}
+
+Vehicle *CreateEffectVehicleRel(const Vehicle *v, int x, int y, int z, EffectVehicleType type)
+{
+ return CreateEffectVehicle(v->x_pos + x, v->y_pos + y, v->z_pos + z, type);
+}
+
+void EffectVehicle::Tick()
+{
+ _effect_tick_procs[this->subtype](this);
+}
+
+void EffectVehicle::UpdateDeltaXY(Direction direction)
+{
+ this->x_offs = 0;
+ this->y_offs = 0;
+ this->x_extent = 1;
+ this->y_extent = 1;
+ this->z_extent = 1;
+}