changeset 15935:a4fa352275f4 draft

(svn r20623) -Codechange: unify the storing of animation related information
author rubidium <rubidium@openttd.org>
date Thu, 26 Aug 2010 15:31:40 +0000
parents 3172190fa127
children a14b2cc58625
files projects/openttd_vs100.vcxproj projects/openttd_vs100.vcxproj.filters projects/openttd_vs80.vcproj projects/openttd_vs90.vcproj source.list src/economy.cpp src/house.h src/industry_cmd.cpp src/industrytype.h src/newgrf.cpp src/newgrf_airporttiles.cpp src/newgrf_airporttiles.h src/newgrf_animation_type.h src/newgrf_house.cpp src/newgrf_industrytiles.cpp src/newgrf_industrytiles.h src/newgrf_station.cpp src/newgrf_station.h src/station_cmd.cpp src/table/airporttiles.h src/table/build_industry.h src/table/town_land.h src/train_cmd.cpp src/vehicle.cpp
diffstat 24 files changed, 129 insertions(+), 88 deletions(-) [+]
line wrap: on
line diff
--- a/projects/openttd_vs100.vcxproj
+++ b/projects/openttd_vs100.vcxproj
@@ -470,6 +470,7 @@
     <ClInclude Include="..\src\newgrf.h" />
     <ClInclude Include="..\src\newgrf_airport.h" />
     <ClInclude Include="..\src\newgrf_airporttiles.h" />
+    <ClInclude Include="..\src\newgrf_animation_type.h" />
     <ClInclude Include="..\src\newgrf_callbacks.h" />
     <ClInclude Include="..\src\newgrf_canal.h" />
     <ClInclude Include="..\src\newgrf_cargo.h" />
--- a/projects/openttd_vs100.vcxproj.filters
+++ b/projects/openttd_vs100.vcxproj.filters
@@ -630,6 +630,9 @@
     <ClInclude Include="..\src\newgrf_airporttiles.h">
       <Filter>Header Files</Filter>
     </ClInclude>
+    <ClInclude Include="..\src\newgrf_animation_type.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
     <ClInclude Include="..\src\newgrf_callbacks.h">
       <Filter>Header Files</Filter>
     </ClInclude>
--- a/projects/openttd_vs80.vcproj
+++ b/projects/openttd_vs80.vcproj
@@ -1155,6 +1155,10 @@
 				>
 			</File>
 			<File
+				RelativePath=".\..\src\newgrf_animation_type.h"
+				>
+			</File>
+			<File
 				RelativePath=".\..\src\newgrf_callbacks.h"
 				>
 			</File>
--- a/projects/openttd_vs90.vcproj
+++ b/projects/openttd_vs90.vcproj
@@ -1152,6 +1152,10 @@
 				>
 			</File>
 			<File
+				RelativePath=".\..\src\newgrf_animation_type.h"
+				>
+			</File>
+			<File
 				RelativePath=".\..\src\newgrf_callbacks.h"
 				>
 			</File>
--- a/source.list
+++ b/source.list
@@ -203,6 +203,7 @@
 newgrf.h
 newgrf_airport.h
 newgrf_airporttiles.h
+newgrf_animation_type.h
 newgrf_callbacks.h
 newgrf_canal.h
 newgrf_cargo.h
--- a/src/economy.cpp
+++ b/src/economy.cpp
@@ -1302,7 +1302,7 @@
 			st->time_since_load = 0;
 			st->last_vehicle_type = v->type;
 
-			StationAnimationTrigger(st, st->xy, STAT_ANIM_CARGO_TAKEN, v->cargo_type);
+			TriggerStationAnimation(st, st->xy, SAT_CARGO_TAKEN, v->cargo_type);
 			AirportAnimationTrigger(st, AAT_STATION_CARGO_TAKEN, v->cargo_type);
 
 			unloading_time += cap;
--- a/src/house.h
+++ b/src/house.h
@@ -17,6 +17,7 @@
 #include "economy_type.h"
 #include "date_type.h"
 #include "house_type.h"
+#include "newgrf_animation_type.h"
 #include "newgrf_commons.h"
 
 /**
@@ -115,8 +116,7 @@
 	byte probability;                  ///< Relative probability of appearing (16 is the standard value)
 	HouseExtraFlags extra_flags;       ///< some more flags
 	HouseClassID class_id;             ///< defines the class this house has (not grf file based)
-	byte animation_frames;             ///< number of animation frames
-	byte animation_speed;              ///< amount of time between each of those frames
+	AnimationInfo animation;           ///< information about the animation.
 	byte processing_time;              ///< Periodic refresh multiplier
 	byte minimum_life;                 ///< The minimum number of years this house will survive before the town rebuilds it
 
--- a/src/industry_cmd.cpp
+++ b/src/industry_cmd.cpp
@@ -533,7 +533,7 @@
 {
 	IndustryGfx gfx = GetIndustryGfx(tile);
 
-	if (GetIndustryTileSpec(gfx)->animation_info != 0xFFFF) {
+	if (GetIndustryTileSpec(gfx)->animation.status != ANIM_STATUS_NO_ANIMATION) {
 		AnimateNewIndustryTile(tile);
 		return;
 	}
@@ -1667,7 +1667,7 @@
 			/* it->gfx is stored in the map. But the translated ID cur_gfx is the interesting one */
 			IndustryGfx cur_gfx = GetTranslatedIndustryTileID(it->gfx);
 			const IndustryTileSpec *its = GetIndustryTileSpec(cur_gfx);
-			if (its->animation_info != 0xFFFF) AddAnimatedTile(cur_tile);
+			if (its->animation.status != ANIM_STATUS_NO_ANIMATION) AddAnimatedTile(cur_tile);
 		}
 	} while ((++it)->ti.x != -0x80);
 
--- a/src/industrytype.h
+++ b/src/industrytype.h
@@ -19,6 +19,7 @@
 #include "landscape_type.h"
 #include "strings_type.h"
 #include "cargo_type.h"
+#include "newgrf_animation_type.h"
 #include "newgrf_commons.h"
 
 enum IndustryCleanupType {
@@ -167,9 +168,7 @@
 	                                      ///< state instead of the construction state
 	/* Newgrf data */
 	uint8 callback_mask;                  ///< Bitmask of industry tile callbacks that have to be called
-	uint16 animation_info;                ///< Information about the animation (is it looping, how many loops etc)
-	uint8 animation_speed;                ///< The speed of the animation
-	uint8 animation_triggers;             ///< When to start the animation
+	AnimationInfo animation;              ///< Information about the animation (is it looping, how many loops etc)
 	IndustryTileSpecialFlags special_flags; ///< Bitmask of extra flags used by the tile
 	bool enabled;                         ///< entity still avaible (by default true).newgrf can disable it, though
 	GRFFileProps grf_prop;                ///< properties related the the grf file
--- a/src/newgrf.cpp
+++ b/src/newgrf.cpp
@@ -1324,16 +1324,16 @@
 				break;
 
 			case 0x16: // Animation info
-				statspec->anim_frames = buf->ReadByte();
-				statspec->anim_status = buf->ReadByte();
+				statspec->animation.frames = buf->ReadByte();
+				statspec->animation.status = buf->ReadByte();
 				break;
 
 			case 0x17: // Animation speed
-				statspec->anim_speed = buf->ReadByte();
+				statspec->animation.speed = buf->ReadByte();
 				break;
 
 			case 0x18: // Animation triggers
-				statspec->anim_triggers = buf->ReadWord();
+				statspec->animation.triggers = buf->ReadWord();
 				break;
 
 			default:
@@ -1700,11 +1700,13 @@
 				break;
 
 			case 0x1A: // Animation frames
-				housespec->animation_frames = buf->ReadByte();
+				housespec->animation.frames = buf->ReadByte();
+				housespec->animation.status = GB(housespec->animation.frames, 7, 1);
+				SB(housespec->animation.frames, 7, 1, 0);
 				break;
 
 			case 0x1B: // Animation speed
-				housespec->animation_speed = Clamp(buf->ReadByte(), 2, 16);
+				housespec->animation.speed = Clamp(buf->ReadByte(), 2, 16);
 				break;
 
 			case 0x1C: // Class of the building type
@@ -2271,15 +2273,16 @@
 				break;
 
 			case 0x0F: // Animation information
-				tsp->animation_info = buf->ReadWord();
+				tsp->animation.frames = buf->ReadByte();
+				tsp->animation.status = buf->ReadByte();
 				break;
 
 			case 0x10: // Animation speed
-				tsp->animation_speed = buf->ReadByte();
+				tsp->animation.speed = buf->ReadByte();
 				break;
 
 			case 0x11: // Triggers for callback 25
-				tsp->animation_triggers = buf->ReadByte();
+				tsp->animation.triggers = buf->ReadByte();
 				break;
 
 			case 0x12: // Special flags
@@ -3091,7 +3094,7 @@
 					memcpy(tsp, AirportTileSpec::Get(subs_id), sizeof(AirportTileSpec));
 					tsp->enabled = true;
 
-					tsp->animation_info = 0xFFFF;
+					tsp->animation.status = ANIM_STATUS_NO_ANIMATION;
 
 					tsp->grf_prop.local_id = airtid + i;
 					tsp->grf_prop.subst_id = subs_id;
@@ -3119,15 +3122,16 @@
 				break;
 
 			case 0x0F: // Animation information
-				tsp->animation_info = buf->ReadWord();
+				tsp->animation.frames = buf->ReadByte();
+				tsp->animation.status = buf->ReadByte();
 				break;
 
 			case 0x10: // Animation speed
-				tsp->animation_speed = buf->ReadByte();
+				tsp->animation.speed = buf->ReadByte();
 				break;
 
 			case 0x11: // Animation triggers
-				tsp->animation_triggers = buf->ReadByte();
+				tsp->animation.triggers = buf->ReadByte();
 				break;
 
 			default:
--- a/src/newgrf_airporttiles.cpp
+++ b/src/newgrf_airporttiles.cpp
@@ -308,7 +308,7 @@
 	Station *st = Station::GetByTile(tile);
 	StationGfx gfx = GetAirportGfx(tile);
 	const AirportTileSpec *ats = AirportTileSpec::Get(gfx);
-	uint8 animation_speed = ats->animation_speed;
+	uint8 animation_speed = ats->animation.speed;
 
 	if (HasBit(ats->callback_mask, CBM_AIRT_ANIM_SPEED)) {
 		uint16 callback_res = GetAirportTileCallback(CBID_AIRPTILE_ANIMATION_SPEED, 0, 0, gfx, st, tile);
@@ -323,7 +323,7 @@
 
 	bool frame_set_by_callback = false;
 	uint8 frame      = GetAnimationFrame(tile);
-	uint16 num_frames = GB(ats->animation_info, 0, 8);
+	uint16 num_frames = ats->animation.frames;
 
 	if (HasBit(ats->callback_mask, CBM_AIRT_ANIM_NEXT_FRAME)) {
 		uint16 callback_res = GetAirportTileCallback(CBID_AIRPTILE_ANIM_NEXT_FRAME, HasBit(ats->animation_special_flags, 0) ? Random() : 0, 0, gfx, st, tile);
@@ -353,7 +353,7 @@
 	if (!frame_set_by_callback) {
 		if (frame < num_frames) {
 			frame++;
-		} else if (frame == num_frames && GB(ats->animation_info, 8, 8) == 1) {
+		} else if (frame == num_frames && ats->animation.status == ANIM_STATUS_LOOPING) {
 			/* This animation loops, so start again from the beginning */
 			frame = 0;
 		} else {
@@ -391,7 +391,7 @@
 	StationGfx gfx = GetAirportGfx(tile);
 	const AirportTileSpec *ats = AirportTileSpec::Get(gfx);
 
-	if (!HasBit(ats->animation_triggers, trigger)) return;
+	if (!HasBit(ats->animation.triggers, trigger)) return;
 
 	ChangeAirportTileAnimationFrame(ats, tile, trigger, gfx, st);
 	return;
--- a/src/newgrf_airporttiles.h
+++ b/src/newgrf_airporttiles.h
@@ -14,27 +14,16 @@
 
 #include "airport.h"
 #include "station_map.h"
+#include "newgrf_animation_type.h"
 #include "newgrf_commons.h"
 
-/** Animation triggers for airport tiles */
-enum AirpAnimationTrigger {
-	AAT_BUILT,               ///< Triggered when the airport it build (for all tiles at the same time)
-	AAT_TILELOOP,            ///< Triggered in the periodic tile loop
-	AAT_STATION_NEW_CARGO,   ///< Triggered when new cargo arrives at the station (for all tiles at the same time)
-	AAT_STATION_CARGO_TAKEN, ///< Triggered when a cargo type is completely removed from the station (for all tiles at the same time)
-	AAT_STATION_250_ticks,   ///< Triggered every 250 ticks (for all tiles at the same time)
-};
-
 /**
  * Defines the data structure of each indivudual tile of an airport.
  */
 struct AirportTileSpec {
-	uint16 animation_info;                ///< Information about the animation (is it looping, how many loops etc)
-	uint8 animation_speed;                ///< The speed of the animation
-
+	AnimationInfo animation;              ///< Information about the animation.
 	StringID name;                        ///< Tile Subname string, land information on this tile will give you "AirportName (TileSubname)"
 	uint8 callback_mask;                  ///< Bitmask telling which grf callback is set
-	uint8 animation_triggers;             ///< When to start the animation
 	uint8 animation_special_flags;        ///< Extra flags to influence the animation
 	bool enabled;                         ///< entity still available (by default true). newgrf can disable it, though
 	GRFFileProps grf_prop;                ///< properties related the the grf file
new file mode 100644
--- /dev/null
+++ b/src/newgrf_animation_type.h
@@ -0,0 +1,56 @@
+/* $Id$ */
+
+/*
+ * This file is part of OpenTTD.
+ * 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.
+ * 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.
+ * 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/>.
+ */
+
+/** @file newgrf_animation_type.h Definitions related to NewGRF animation. */
+
+#ifndef NEWGRF_ANIMATION_TYPE_H
+#define NEWGRF_ANIMATION_TYPE_H
+
+static const uint8 ANIM_STATUS_NON_LOOPING  = 0x00; ///< Animation is not looping.
+static const uint8 ANIM_STATUS_LOOPING      = 0x01; ///< Animation is looping.
+static const uint8 ANIM_STATUS_NO_ANIMATION = 0xFF; ///< There is no animation.
+
+/** Information about animation. */
+struct AnimationInfo {
+	uint8  frames;   ///< The number of frames.
+	uint8  status;   ///< Status; 0: no looping, 1: looping, 0xFF: no animation.
+	uint8  speed;    ///< The speed, i.e. the amount of time between frames.
+	uint16 triggers; ///< The triggers that trigger animation.
+};
+
+/** Animation triggers for station. */
+enum StationAnimationTrigger {
+	SAT_BUILT,         ///< Trigger tile when built.
+	SAT_NEW_CARGO,     ///< Trigger station on new cargo arrival.
+	SAT_CARGO_TAKEN,   ///< Trigger station when cargo is taken.
+	SAT_TRAIN_ARRIVES, ///< Trigger platform when train arrives.
+	SAT_TRAIN_DEPARTS, ///< Trigger platform when train leaves.
+	SAT_TRAIN_LOADS,   ///< Trigger platform when train loads/unloads.
+	SAT_250_TICKS,     ///< Trigger station every 250 ticks.
+};
+
+/** Animation triggers of the industries. */
+enum IndustryAnimationTrigger {
+	IAT_CONSTRUCTION_STATE_CHANGE,  ///< Trigger whenever the construction state changes.
+	IAT_TILELOOP,                   ///< Trigger in the periodic tile loop.
+	IAT_INDUSTRY_TICK,              ///< Trigger every tick.
+	IAT_INDUSTRY_RECEIVED_CARGO,    ///< Trigger when cargo is received .
+	IAT_INDUSTRY_DISTRIBUTES_CARGO, ///< Trigger when cargo is distributed.
+};
+
+/** Animation triggers for airport tiles */
+enum AirpAnimationTrigger {
+	AAT_BUILT,               ///< Triggered when the airport it build (for all tiles at the same time).
+	AAT_TILELOOP,            ///< Triggered in the periodic tile loop.
+	AAT_STATION_NEW_CARGO,   ///< Triggered when new cargo arrives at the station (for all tiles at the same time).
+	AAT_STATION_CARGO_TAKEN, ///< Triggered when a cargo type is completely removed from the station (for all tiles at the same time).
+	AAT_STATION_250_ticks,   ///< Triggered every 250 ticks (for all tiles at the same time).
+};
+
+#endif /* NEWGRF_ANIMATION_TYPE_H */
--- a/src/newgrf_house.cpp
+++ b/src/newgrf_house.cpp
@@ -474,7 +474,7 @@
 void AnimateNewHouseTile(TileIndex tile)
 {
 	const HouseSpec *hs = HouseSpec::Get(GetHouseType(tile));
-	byte animation_speed = hs->animation_speed;
+	byte animation_speed = hs->animation.speed;
 	bool frame_set_by_callback = false;
 
 	if (HasBit(hs->callback_mask, CBM_HOUSE_ANIMATION_SPEED)) {
@@ -489,7 +489,7 @@
 	if (_tick_counter % (1 << animation_speed) != 0) return;
 
 	byte frame      = GetAnimationFrame(tile);
-	byte num_frames = GB(hs->animation_frames, 0, 7);
+	byte num_frames = hs->animation.frames;
 
 	if (HasBit(hs->callback_mask, CBM_HOUSE_ANIMATION_NEXT_FRAME)) {
 		uint32 param = (hs->extra_flags & CALLBACK_1A_RANDOM_BITS) ? Random() : 0;
@@ -520,7 +520,7 @@
 	if (!frame_set_by_callback) {
 		if (frame < num_frames) {
 			frame++;
-		} else if (frame == num_frames && HasBit(hs->animation_frames, 7)) {
+		} else if (frame == num_frames && hs->animation.status == ANIM_STATUS_LOOPING) {
 			/* This animation loops, so start again from the beginning */
 			frame = 0;
 		} else {
--- a/src/newgrf_industrytiles.cpp
+++ b/src/newgrf_industrytiles.cpp
@@ -302,7 +302,7 @@
 	Industry *ind = Industry::GetByTile(tile);
 	IndustryGfx gfx = GetIndustryGfx(tile);
 	const IndustryTileSpec *itspec = GetIndustryTileSpec(gfx);
-	byte animation_speed = itspec->animation_speed;
+	byte animation_speed = itspec->animation.speed;
 
 	if (HasBit(itspec->callback_mask, CBM_INDT_ANIM_SPEED)) {
 		uint16 callback_res = GetIndustryTileCallback(CBID_INDTILE_ANIMATION_SPEED, 0, 0, gfx, ind, tile);
@@ -317,7 +317,7 @@
 
 	bool frame_set_by_callback = false;
 	byte frame = GetAnimationFrame(tile);
-	uint16 num_frames = GB(itspec->animation_info, 0, 8);
+	uint16 num_frames = itspec->animation.frames;
 
 	if (HasBit(itspec->callback_mask, CBM_INDT_ANIM_NEXT_FRAME)) {
 		uint16 callback_res = GetIndustryTileCallback(CBID_INDTILE_ANIM_NEXT_FRAME,
@@ -348,7 +348,7 @@
 	if (!frame_set_by_callback) {
 		if (frame < num_frames) {
 			frame++;
-		} else if (frame == num_frames && GB(itspec->animation_info, 8, 8) == 1) {
+		} else if (frame == num_frames && itspec->animation.status == ANIM_STATUS_LOOPING) {
 			/* This animation loops, so start again from the beginning */
 			frame = 0;
 		} else {
@@ -386,7 +386,7 @@
 	IndustryGfx gfx = GetIndustryGfx(tile);
 	const IndustryTileSpec *itspec = GetIndustryTileSpec(gfx);
 
-	if (!HasBit(itspec->animation_triggers, iat)) return false;
+	if (!HasBit(itspec->animation.triggers, iat)) return false;
 
 	Industry *ind = Industry::GetByTile(tile);
 	ChangeIndustryTileAnimationFrame(itspec, tile, iat, random, gfx, ind);
--- a/src/newgrf_industrytiles.h
+++ b/src/newgrf_industrytiles.h
@@ -14,18 +14,10 @@
 
 #include "tile_cmd.h"
 #include "industry_type.h"
+#include "newgrf_animation_type.h"
 #include "newgrf_callbacks.h"
 #include "core/random_func.hpp"
 
-/** Animation triggers of the industries. */
-enum IndustryAnimationTrigger {
-	IAT_CONSTRUCTION_STATE_CHANGE,
-	IAT_TILELOOP,
-	IAT_INDUSTRY_TICK,
-	IAT_INDUSTRY_RECEIVED_CARGO,
-	IAT_INDUSTRY_DISTRIBUTES_CARGO,
-};
-
 bool DrawNewIndustryTile(TileInfo *ti, Industry *i, IndustryGfx gfx, const IndustryTileSpec *inds);
 uint16 GetIndustryTileCallback(CallbackID callback, uint32 param1, uint32 param2, IndustryGfx gfx_id, Industry *industry, TileIndex tile);
 CommandCost PerformIndustryTileSlopeCheck(TileIndex ind_base_tile, TileIndex ind_tile, const IndustryTileSpec *its, IndustryType type, IndustryGfx gfx, uint itspec_index, uint16 initial_random_bits, Owner founder);
--- a/src/newgrf_station.cpp
+++ b/src/newgrf_station.cpp
@@ -818,7 +818,7 @@
 
 	const BaseStation *st = BaseStation::GetByTile(tile);
 
-	uint8 animation_speed = ss->anim_speed;
+	uint8 animation_speed = ss->animation.speed;
 
 	if (HasBit(ss->callback_mask, CBM_STATION_ANIMATION_SPEED)) {
 		uint16 callback = GetStationCallback(CBID_STATION_ANIMATION_SPEED, 0, 0, ss, st, tile);
@@ -828,7 +828,7 @@
 	if (_tick_counter % (1 << animation_speed) != 0) return;
 
 	uint8 frame      = GetAnimationFrame(tile);
-	uint8 num_frames = ss->anim_frames;
+	uint8 num_frames = ss->animation.frames;
 
 	bool frame_set_by_callback = false;
 
@@ -862,7 +862,7 @@
 	if (!frame_set_by_callback) {
 		if (frame < num_frames) {
 			frame++;
-		} else if (frame == num_frames && HasBit(ss->anim_status, 0)) {
+		} else if (frame == num_frames && ss->animation.status == ANIM_STATUS_LOOPING) {
 			/* This animation loops, so start again from the beginning */
 			frame = 0;
 		} else {
@@ -876,7 +876,7 @@
 }
 
 
-static void ChangeStationAnimationFrame(const StationSpec *ss, const BaseStation *st, TileIndex tile, uint16 random_bits, StatAnimTrigger trigger, CargoID cargo_type)
+static void ChangeStationAnimationFrame(const StationSpec *ss, const BaseStation *st, TileIndex tile, uint16 random_bits, StationAnimationTrigger trigger, CargoID cargo_type)
 {
 	uint16 callback = GetStationCallback(CBID_STATION_ANIM_START_STOP, (random_bits << 16) | Random(), (uint8)trigger | (cargo_type << 8), ss, st, tile);
 	if (callback == CALLBACK_FAILED) return;
@@ -896,7 +896,7 @@
 	if (GB(callback, 8, 7) != 0) PlayTileSound(ss->grf_prop.grffile, GB(callback, 8, 7), tile);
 }
 
-void StationAnimationTrigger(const BaseStation *st, TileIndex tile, StatAnimTrigger trigger, CargoID cargo_type)
+void TriggerStationAnimation(const BaseStation *st, TileIndex tile, StationAnimationTrigger trigger, CargoID cargo_type)
 {
 	/* List of coverage areas for each animation trigger */
 	static const TriggerArea tas[] = {
@@ -917,7 +917,7 @@
 	TILE_AREA_LOOP(tile, area) {
 		if (st->TileBelongsToRailStation(tile)) {
 			const StationSpec *ss = GetStationSpec(tile);
-			if (ss != NULL && HasBit(ss->anim_triggers, trigger)) {
+			if (ss != NULL && HasBit(ss->animation.triggers, trigger)) {
 				CargoID cargo;
 				if (cargo_type == CT_INVALID) {
 					cargo = CT_INVALID;
@@ -942,7 +942,7 @@
 	 * of this station. */
 	for (uint i = 0; i < st->num_specs; i++) {
 		const StationSpec *ss = st->speclist[i].spec;
-		if (ss != NULL) st->cached_anim_triggers |= ss->anim_triggers;
+		if (ss != NULL) st->cached_anim_triggers |= ss->animation.triggers;
 	}
 }
 
--- a/src/newgrf_station.h
+++ b/src/newgrf_station.h
@@ -12,6 +12,7 @@
 #ifndef NEWGRF_STATION_H
 #define NEWGRF_STATION_H
 
+#include "newgrf_animation_type.h"
 #include "newgrf_callbacks.h"
 #include "newgrf_class.h"
 #include "newgrf_commons.h"
@@ -96,15 +97,12 @@
 	byte wires;   ///< Bitmask of base tiles (0 - 7) which should contain elrail wires
 	byte blocked; ///< Bitmask of base tiles (0 - 7) which are blocked to trains
 
+	AnimationInfo animation;
+
 	byte lengths;
 	byte *platforms;
 	StationLayout **layouts;
 	bool copied_layouts;
-
-	uint8  anim_frames;
-	uint8  anim_status;
-	uint8  anim_speed;
-	uint16 anim_triggers;
 };
 
 /** Struct containing information relating to station classes. */
@@ -132,18 +130,8 @@
 /* Draw representation of a station tile for GUI purposes. */
 bool DrawStationTile(int x, int y, RailType railtype, Axis axis, StationClassID sclass, uint station);
 
-enum StatAnimTrigger {
-	STAT_ANIM_BUILT,
-	STAT_ANIM_NEW_CARGO,
-	STAT_ANIM_CARGO_TAKEN,
-	STAT_ANIM_TRAIN_ARRIVES,
-	STAT_ANIM_TRAIN_DEPARTS,
-	STAT_ANIM_TRAIN_LOADS,
-	STAT_ANIM_250_TICKS,
-};
-
 void AnimateStationTile(TileIndex tile);
-void StationAnimationTrigger(const BaseStation *st, TileIndex tile, StatAnimTrigger trigger, CargoID cargo_type = CT_INVALID);
+void TriggerStationAnimation(const BaseStation *st, TileIndex tile, StationAnimationTrigger trigger, CargoID cargo_type = CT_INVALID);
 void StationUpdateAnimTriggers(BaseStation *st);
 
 #endif /* NEWGRF_STATION_H */
--- a/src/station_cmd.cpp
+++ b/src/station_cmd.cpp
@@ -1240,7 +1240,7 @@
 		if (statspec != NULL) {
 			/* Include this station spec's animation trigger bitmask
 			 * in the station's cached copy. */
-			st->cached_anim_triggers |= statspec->anim_triggers;
+			st->cached_anim_triggers |= statspec->animation.triggers;
 		}
 
 		tile_delta = (axis == AXIS_X ? TileDiffXY(1, 0) : TileDiffXY(0, 1));
@@ -1288,7 +1288,7 @@
 					if (callback != CALLBACK_FAILED && callback < 8) SetStationGfx(tile, (callback & ~1) + axis);
 
 					/* Trigger station animation -- after building? */
-					StationAnimationTrigger(st, tile, STAT_ANIM_BUILT);
+					TriggerStationAnimation(st, tile, SAT_BUILT);
 				}
 
 				tile += tile_delta;
@@ -2227,7 +2227,7 @@
 			SetStationTileRandomBits(cur_tile, GB(Random(), 0, 4));
 			st->airport.Add(cur_tile);
 
-			if (AirportTileSpec::Get(GetTranslatedAirportTileID(it->gfx))->animation_info != 0xFFFF) AddAnimatedTile(cur_tile);
+			if (AirportTileSpec::Get(GetTranslatedAirportTileID(it->gfx))->animation.status != ANIM_STATUS_NO_ANIMATION) AddAnimatedTile(cur_tile);
 		} while ((++it)->ti.x != -0x80);
 
 		/* Only call the animation trigger after all tiles have been built */
@@ -3153,7 +3153,7 @@
 		if ((_tick_counter + st->index) % 250 == 0) {
 			/* Stop processing this station if it was deleted */
 			if (!StationHandleBigTick(st)) continue;
-			StationAnimationTrigger(st, st->xy, STAT_ANIM_250_TICKS);
+			TriggerStationAnimation(st, st->xy, SAT_250_TICKS);
 			if (Station::IsExpected(st)) AirportAnimationTrigger(Station::From(st), AAT_STATION_250_ticks);
 		}
 	}
@@ -3188,7 +3188,7 @@
 	st->goods[type].cargo.Append(new CargoPacket(st->index, st->xy, amount, source_type, source_id));
 	SetBit(st->goods[type].acceptance_pickup, GoodsEntry::PICKUP);
 
-	StationAnimationTrigger(st, st->xy, STAT_ANIM_NEW_CARGO, type);
+	TriggerStationAnimation(st, st->xy, SAT_NEW_CARGO, type);
 	AirportAnimationTrigger(st, AAT_STATION_NEW_CARGO, type);
 
 	SetWindowDirty(WC_STATION_VIEW, st->index);
--- a/src/table/airporttiles.h
+++ b/src/table/airporttiles.h
@@ -13,9 +13,9 @@
 #define AIRPORTTILES_H
 
 /** Writes all airport tile properties in the AirportTile struct */
-#define AT(num_frames, anim_speed) {(1 << 8) | num_frames, anim_speed, STR_NULL, 0, 0, 0, true, GRFFileProps(INVALID_AIRPORTTILE)}
+#define AT(num_frames, anim_speed) {{num_frames, ANIM_STATUS_LOOPING, anim_speed, 0}, STR_NULL, 0, 0, true, GRFFileProps(INVALID_AIRPORTTILE)}
 /** Writes an airport tile without animation in the AirportTile struct */
-#define AT_NOANIM {0xFFFF, 2, STR_NULL, 0, 0, 0, true, GRFFileProps(INVALID_AIRPORTTILE)}
+#define AT_NOANIM {{0, ANIM_STATUS_NO_ANIMATION, 2, 0}, STR_NULL, 0, 0, true, GRFFileProps(INVALID_AIRPORTTILE)}
 
 /**
  * All default airport tiles.
--- a/src/table/build_industry.h
+++ b/src/table/build_industry.h
@@ -1581,7 +1581,7 @@
  * @param a2  next frame of animation
  * @param a3  chooses between animation or construction state
  */
-#define MT(ca1, c1, ca2, c2, ca3, c3, sl, a1, a2, a3) {{c1, c2, c3}, {ca1, ca2, ca3}, sl, a1, a2, a3, 0, 0xFFFF, 2, 0, INDTILE_SPECIAL_NONE, true, GRFFileProps(INVALID_INDUSTRYTILE)}
+#define MT(ca1, c1, ca2, c2, ca3, c3, sl, a1, a2, a3) {{c1, c2, c3}, {ca1, ca2, ca3}, sl, a1, a2, a3, 0, {0, ANIM_STATUS_NO_ANIMATION, 2, 0}, INDTILE_SPECIAL_NONE, true, GRFFileProps(INVALID_INDUSTRYTILE)}
 static const IndustryTileSpec _origin_industry_tile_specs[NEW_INDUSTRYTILEOFFSET] = {
 	/* Coal Mine */
 	MT(0, CT_INVALID,      0, CT_INVALID,      0, CT_INVALID,     SLOPE_STEEP, INDUSTRYTILE_NOANIM, INDUSTRYTILE_NOANIM, false),
--- a/src/table/town_land.h
+++ b/src/table/town_land.h
@@ -1813,7 +1813,7 @@
  */
 #define MS(mnd, mxd, p, rc, bn, rr, mg, ca1, ca2, ca3, bf, ba, cg1, cg2, cg3) \
 	{mnd, mxd, p, rc, bn, rr, mg, {ca1, ca2, ca3}, {cg1, cg2, cg3}, bf, ba, true, \
-	 GRFFileProps(INVALID_HOUSE_ID), 0, {0, 0, 0, 0}, 16, NO_EXTRA_FLAG, HOUSE_NO_CLASS, 0, 2, 0, 0}
+	 GRFFileProps(INVALID_HOUSE_ID), 0, {0, 0, 0, 0}, 16, NO_EXTRA_FLAG, HOUSE_NO_CLASS, {0, 2, 0, 0}, 0, 0}
 /** House specifications from original data */
 static const HouseSpec _original_house_specs[] = {
 	/**
--- a/src/train_cmd.cpp
+++ b/src/train_cmd.cpp
@@ -2864,7 +2864,7 @@
 
 	v->BeginLoading();
 
-	StationAnimationTrigger(st, v->tile, STAT_ANIM_TRAIN_ARRIVES);
+	TriggerStationAnimation(st, v->tile, SAT_TRAIN_ARRIVES);
 }
 
 /* Check if the vehicle is compatible with the specified tile */
--- a/src/vehicle.cpp
+++ b/src/vehicle.cpp
@@ -1684,7 +1684,7 @@
 
 	if (this->type == VEH_TRAIN && !(this->vehstatus & VS_CRASHED)) {
 		/* Trigger station animation (trains only) */
-		if (IsTileType(this->tile, MP_STATION)) StationAnimationTrigger(st, this->tile, STAT_ANIM_TRAIN_DEPARTS);
+		if (IsTileType(this->tile, MP_STATION)) TriggerStationAnimation(st, this->tile, SAT_TRAIN_DEPARTS);
 
 		SetBit(Train::From(this)->flags, VRF_LEAVING_STATION);
 	}