@ -48,6 +48,7 @@
# include "vehicle_func.h"
# include "language.h"
# include "vehicle_base.h"
# include "road.h"
# include "table/strings.h"
# include "table/build_industry.h"
@ -313,6 +314,7 @@ struct GRFTempEngineData {
uint16 cargo_allowed ;
uint16 cargo_disallowed ;
RailTypeLabel railtypelabel ;
uint8 roadtramtype ;
const GRFFile * defaultcargo_grf ; ///< GRF defining the cargo translation table to use if the default cargo is the 'first refittable'.
Refittability refittability ; ///< Did the newgrf set any refittability property? If not, default refittability will be applied.
bool prop27_set ; ///< Did the NewGRF set property 27 (misc flags)?
@ -1380,6 +1382,12 @@ static ChangeInfoResult RoadVehicleChangeInfo(uint engine, int numinfo, int prop
RoadVehicleInfo * rvi = & e - > u . road ;
switch ( prop ) {
case 0x05 : // Road/tram type
/* RoadTypeLabel is looked up later after the engine's road/tram
* flag is set , however 0 means the value has not been set . */
_gted [ e - > index ] . roadtramtype = buf - > ReadByte ( ) + 1 ;
break ;
case 0x08 : // Speed (1 unit is 0.5 kmh)
rvi - > max_speed = buf - > ReadByte ( ) ;
break ;
@ -2686,6 +2694,12 @@ static ChangeInfoResult GlobalVarChangeInfo(uint gvid, int numinfo, int prop, co
case 0x12 : // Rail type translation table; loading during both reservation and activation stage (in case it is selected depending on defined railtypes)
return LoadTranslationTable ( gvid , numinfo , buf , _cur . grffile - > railtype_list , " Rail type " ) ;
case 0x16 : // Road type translation table; loading during both reservation and activation stage (in case it is selected depending on defined railtypes)
return LoadTranslationTable ( gvid , numinfo , buf , _cur . grffile - > roadtype_list , " Road type " ) ;
case 0x17 : // Tram type translation table; loading during both reservation and activation stage (in case it is selected depending on defined railtypes)
return LoadTranslationTable ( gvid , numinfo , buf , _cur . grffile - > tramtype_list , " Tram type " ) ;
default :
break ;
}
@ -2901,6 +2915,12 @@ static ChangeInfoResult GlobalVarReserveInfo(uint gvid, int numinfo, int prop, c
case 0x12 : // Rail type translation table; loading during both reservation and activation stage (in case it is selected depending on defined railtypes)
return LoadTranslationTable ( gvid , numinfo , buf , _cur . grffile - > railtype_list , " Rail type " ) ;
case 0x16 : // Road type translation table; loading during both reservation and activation stage (in case it is selected depending on defined roadtypes)
return LoadTranslationTable ( gvid , numinfo , buf , _cur . grffile - > roadtype_list , " Road type " ) ;
case 0x17 : // Tram type translation table; loading during both reservation and activation stage (in case it is selected depending on defined tramtypes)
return LoadTranslationTable ( gvid , numinfo , buf , _cur . grffile - > tramtype_list , " Tram type " ) ;
default :
break ;
}
@ -4442,6 +4462,228 @@ static ChangeInfoResult RailTypeReserveInfo(uint id, int numinfo, int prop, cons
return ret ;
}
/**
* Define properties for roadtypes
* @ param id ID of the roadtype .
* @ param numinfo Number of subsequent IDs to change the property for .
* @ param prop The property to change .
* @ param buf The property value .
* @ return ChangeInfoResult .
*/
static ChangeInfoResult RoadTypeChangeInfo ( uint id , int numinfo , int prop , const GRFFilePropertyRemapEntry * mapping_entry , ByteReader * buf , RoadTramType rtt )
{
ChangeInfoResult ret = CIR_SUCCESS ;
extern RoadTypeInfo _roadtypes [ ROADTYPE_END ] ;
RoadType * type_map = ( rtt = = RTT_TRAM ) ? _cur . grffile - > tramtype_map : _cur . grffile - > roadtype_map ;
if ( id + numinfo > ROADTYPE_END ) {
grfmsg ( 1 , " RoadTypeChangeInfo: Road type %u is invalid, max %u, ignoring " , id + numinfo , ROADTYPE_END ) ;
return CIR_INVALID_ID ;
}
for ( int i = 0 ; i < numinfo ; i + + ) {
RoadType rt = type_map [ id + i ] ;
if ( rt = = INVALID_ROADTYPE ) return CIR_INVALID_ID ;
RoadTypeInfo * rti = & _roadtypes [ rt ] ;
switch ( prop ) {
case 0x08 : // Label of road type
/* Skipped here as this is loaded during reservation stage. */
buf - > ReadDWord ( ) ;
break ;
case 0x09 : { // Toolbar caption of roadtype (sets name as well for backwards compatibility for grf ver < 8)
uint16 str = buf - > ReadWord ( ) ;
AddStringForMapping ( str , & rti - > strings . toolbar_caption ) ;
break ;
}
case 0x0A : // Menu text of roadtype
AddStringForMapping ( buf - > ReadWord ( ) , & rti - > strings . menu_text ) ;
break ;
case 0x0B : // Build window caption
AddStringForMapping ( buf - > ReadWord ( ) , & rti - > strings . build_caption ) ;
break ;
case 0x0C : // Autoreplace text
AddStringForMapping ( buf - > ReadWord ( ) , & rti - > strings . replace_text ) ;
break ;
case 0x0D : // New engine text
AddStringForMapping ( buf - > ReadWord ( ) , & rti - > strings . new_engine ) ;
break ;
case 0x0F : // Powered roadtype list
case 0x18 : // Roadtype list required for date introduction
case 0x19 : { // Introduced roadtype list
/* Road type compatibility bits are added to the existing bits
* to allow multiple GRFs to modify compatibility with the
* default road types . */
int n = buf - > ReadByte ( ) ;
for ( int j = 0 ; j ! = n ; j + + ) {
RoadTypeLabel label = buf - > ReadDWord ( ) ;
RoadType rt = GetRoadTypeByLabel ( BSWAP32 ( label ) , false ) ;
if ( rt ! = INVALID_ROADTYPE ) {
switch ( prop ) {
case 0x0F : SetBit ( rti - > powered_roadtypes , rt ) ; break ;
case 0x18 : SetBit ( rti - > introduction_required_roadtypes , rt ) ; break ;
case 0x19 : SetBit ( rti - > introduces_roadtypes , rt ) ; break ;
}
}
}
break ;
}
case 0x10 : // Road Type flags
rti - > flags = ( RoadTypeFlags ) buf - > ReadByte ( ) ;
break ;
case 0x13 : // Construction cost factor
rti - > cost_multiplier = buf - > ReadWord ( ) ;
break ;
case 0x14 : // Speed limit
rti - > max_speed = buf - > ReadWord ( ) ;
break ;
case 0x16 : // Map colour
rti - > map_colour = buf - > ReadByte ( ) ;
break ;
case 0x17 : // Introduction date
rti - > introduction_date = buf - > ReadDWord ( ) ;
break ;
case 0x1A : // Sort order
rti - > sorting_order = buf - > ReadByte ( ) ;
break ;
case 0x1B : // Name of roadtype
AddStringForMapping ( buf - > ReadWord ( ) , & rti - > strings . name ) ;
break ;
case 0x1C : // Maintenance cost factor
rti - > maintenance_multiplier = buf - > ReadWord ( ) ;
break ;
case 0x1D : // Alternate road type label list
/* Skipped here as this is loaded during reservation stage. */
for ( int j = buf - > ReadByte ( ) ; j ! = 0 ; j - - ) buf - > ReadDWord ( ) ;
break ;
default :
ret = CIR_UNKNOWN ;
break ;
}
}
return ret ;
}
static ChangeInfoResult RoadTypeChangeInfo ( uint id , int numinfo , int prop , const GRFFilePropertyRemapEntry * mapping_entry , ByteReader * buf )
{
return RoadTypeChangeInfo ( id , numinfo , prop , mapping_entry , buf , RTT_ROAD ) ;
}
static ChangeInfoResult TramTypeChangeInfo ( uint id , int numinfo , int prop , const GRFFilePropertyRemapEntry * mapping_entry , ByteReader * buf )
{
return RoadTypeChangeInfo ( id , numinfo , prop , mapping_entry , buf , RTT_TRAM ) ;
}
static ChangeInfoResult RoadTypeReserveInfo ( uint id , int numinfo , int prop , const GRFFilePropertyRemapEntry * mapping_entry , ByteReader * buf , RoadTramType rtt )
{
ChangeInfoResult ret = CIR_SUCCESS ;
extern RoadTypeInfo _roadtypes [ ROADTYPE_END ] ;
RoadType * type_map = ( rtt = = RTT_TRAM ) ? _cur . grffile - > tramtype_map : _cur . grffile - > roadtype_map ;
if ( id + numinfo > ROADTYPE_END ) {
grfmsg ( 1 , " RoadTypeReserveInfo: Road type %u is invalid, max %u, ignoring " , id + numinfo , ROADTYPE_END ) ;
return CIR_INVALID_ID ;
}
for ( int i = 0 ; i < numinfo ; i + + ) {
switch ( prop ) {
case 0x08 : { // Label of road type
RoadTypeLabel rtl = buf - > ReadDWord ( ) ;
rtl = BSWAP32 ( rtl ) ;
RoadType rt = GetRoadTypeByLabel ( rtl , false ) ;
if ( rt = = INVALID_ROADTYPE ) {
/* Set up new road type */
rt = AllocateRoadType ( rtl , rtt ) ;
} else if ( GetRoadTramType ( rt ) ! = rtt ) {
grfmsg ( 1 , " RoadTypeReserveInfo: Road type %u is invalid type (road/tram), ignoring " , id + numinfo ) ;
return CIR_INVALID_ID ;
}
type_map [ id + i ] = rt ;
break ;
}
case 0x09 : // Toolbar caption of roadtype
case 0x0A : // Menu text
case 0x0B : // Build window caption
case 0x0C : // Autoreplace text
case 0x0D : // New loco
case 0x13 : // Construction cost
case 0x14 : // Speed limit
case 0x1B : // Name of roadtype
case 0x1C : // Maintenance cost factor
buf - > ReadWord ( ) ;
break ;
case 0x1D : // Alternate road type label list
if ( type_map [ id + i ] ! = INVALID_ROADTYPE ) {
int n = buf - > ReadByte ( ) ;
for ( int j = 0 ; j ! = n ; j + + ) {
_roadtypes [ type_map [ id + i ] ] . alternate_labels . push_back ( BSWAP32 ( buf - > ReadDWord ( ) ) ) ;
}
break ;
}
grfmsg ( 1 , " RoadTypeReserveInfo: Ignoring property 1D for road type %u because no label was set " , id + i ) ;
/* FALL THROUGH */
case 0x0F : // Powered roadtype list
case 0x18 : // Roadtype list required for date introduction
case 0x19 : // Introduced roadtype list
for ( int j = buf - > ReadByte ( ) ; j ! = 0 ; j - - ) buf - > ReadDWord ( ) ;
break ;
case 0x10 : // Road Type flags
case 0x12 : // Station graphic
case 0x15 : // Acceleration model
case 0x16 : // Map colour
case 0x1A : // Sort order
buf - > ReadByte ( ) ;
break ;
case 0x17 : // Introduction date
buf - > ReadDWord ( ) ;
break ;
default :
ret = CIR_UNKNOWN ;
break ;
}
}
return ret ;
}
static ChangeInfoResult RoadTypeReserveInfo ( uint id , int numinfo , int prop , const GRFFilePropertyRemapEntry * mapping_entry , ByteReader * buf )
{
return RoadTypeReserveInfo ( id , numinfo , prop , mapping_entry , buf , RTT_ROAD ) ;
}
static ChangeInfoResult TramTypeReserveInfo ( uint id , int numinfo , int prop , const GRFFilePropertyRemapEntry * mapping_entry , ByteReader * buf )
{
return RoadTypeReserveInfo ( id , numinfo , prop , mapping_entry , buf , RTT_TRAM ) ;
}
static ChangeInfoResult AirportTilesChangeInfo ( uint airtid , int numinfo , int prop , const GRFFilePropertyRemapEntry * mapping_entry , ByteReader * buf )
{
ChangeInfoResult ret = CIR_SUCCESS ;
@ -4626,6 +4868,8 @@ static void FeatureChangeInfo(ByteReader *buf)
/* GSF_OBJECTS */ ObjectChangeInfo ,
/* GSF_RAILTYPES */ RailTypeChangeInfo ,
/* GSF_AIRPORTTILES */ AirportTilesChangeInfo ,
/* GSF_ROADTYPES */ RoadTypeChangeInfo ,
/* GSF_TRAMTYPES */ TramTypeChangeInfo ,
} ;
static_assert ( lengthof ( handler ) = = lengthof ( _cur . grffile - > action0_property_remaps ) , " Action 0 feature list length mismatch " ) ;
@ -4700,7 +4944,7 @@ static void ReserveChangeInfo(ByteReader *buf)
{
uint8 feature = buf - > ReadByte ( ) ;
if ( feature ! = GSF_CARGOES & & feature ! = GSF_GLOBALVAR & & feature ! = GSF_RAILTYPES ) return ;
if ( feature ! = GSF_CARGOES & & feature ! = GSF_GLOBALVAR & & feature ! = GSF_RAILTYPES & & feature ! = GSF_ROADTYPES & & feature ! = GSF_TRAMTYPES ) return ;
uint8 numprops = buf - > ReadByte ( ) ;
uint8 numinfo = buf - > ReadByte ( ) ;
@ -4723,6 +4967,14 @@ static void ReserveChangeInfo(ByteReader *buf)
case GSF_RAILTYPES :
cir = RailTypeReserveInfo ( index , numinfo , desc . prop , desc . entry , buf ) ;
break ;
case GSF_ROADTYPES :
cir = RoadTypeReserveInfo ( index , numinfo , desc . prop , desc . entry , buf ) ;
break ;
case GSF_TRAMTYPES :
cir = TramTypeReserveInfo ( index , numinfo , desc . prop , desc . entry , buf ) ;
break ;
}
if ( HandleChangeInfoResult ( " ReserveChangeInfo " , cir , feature , desc . prop ) ) return ;
@ -5035,6 +5287,8 @@ static void NewSpriteGroup(ByteReader *buf)
case GSF_CARGOES :
case GSF_AIRPORTS :
case GSF_RAILTYPES :
case GSF_ROADTYPES :
case GSF_TRAMTYPES :
{
byte num_loaded = type ;
byte num_loading = buf - > ReadByte ( ) ;
@ -5612,6 +5866,39 @@ static void RailTypeMapSpriteGroup(ByteReader *buf, uint8 idcount)
buf - > ReadWord ( ) ;
}
static void RoadTypeMapSpriteGroup ( ByteReader * buf , uint8 idcount , RoadTramType rtt )
{
RoadType * type_map = ( rtt = = RTT_TRAM ) ? _cur . grffile - > tramtype_map : _cur . grffile - > roadtype_map ;
uint8 * roadtypes = AllocaM ( uint8 , idcount ) ;
for ( uint i = 0 ; i < idcount ; i + + ) {
uint8 id = buf - > ReadByte ( ) ;
roadtypes [ i ] = id < ROADTYPE_END ? type_map [ id ] : INVALID_ROADTYPE ;
}
uint8 cidcount = buf - > ReadByte ( ) ;
for ( uint c = 0 ; c < cidcount ; c + + ) {
uint8 ctype = buf - > ReadByte ( ) ;
uint16 groupid = buf - > ReadWord ( ) ;
if ( ! IsValidGroupID ( groupid , " RoadTypeMapSpriteGroup " ) ) continue ;
if ( ctype > = ROTSG_END ) continue ;
extern RoadTypeInfo _roadtypes [ ROADTYPE_END ] ;
for ( uint i = 0 ; i < idcount ; i + + ) {
if ( roadtypes [ i ] ! = INVALID_ROADTYPE ) {
RoadTypeInfo * rti = & _roadtypes [ roadtypes [ i ] ] ;
rti - > grffile [ ctype ] = _cur . grffile ;
rti - > group [ ctype ] = _cur . spritegroups [ groupid ] ;
}
}
}
/* Roadtypes do not use the default group. */
buf - > ReadWord ( ) ;
}
static void AirportMapSpriteGroup ( ByteReader * buf , uint8 idcount )
{
uint8 * airports = AllocaM ( uint8 , idcount ) ;
@ -5762,6 +6049,14 @@ static void FeatureMapSpriteGroup(ByteReader *buf)
RailTypeMapSpriteGroup ( buf , idcount ) ;
break ;
case GSF_ROADTYPES :
RoadTypeMapSpriteGroup ( buf , idcount , RTT_ROAD ) ;
break ;
case GSF_TRAMTYPES :
RoadTypeMapSpriteGroup ( buf , idcount , RTT_TRAM ) ;
break ;
case GSF_AIRPORTTILES :
AirportTileMapSpriteGroup ( buf , idcount ) ;
return ;
@ -6030,6 +6325,15 @@ static void GraphicsNew(ByteReader *buf)
/* Load <num> sprites starting from <replace>, then skip <skip_num> sprites. */
grfmsg ( 2 , " GraphicsNew: Replacing sprites %d to %d of %s (type 0x%02X) at SpriteID 0x%04X " , offset , offset + num - 1 , action5_type - > name , type , replace ) ;
if ( type = = 0x0D ) _loaded_newgrf_features . shore = SHORE_REPLACE_ACTION_5 ;
if ( type = = 0x0B ) {
static const SpriteID depot_with_track_offset = SPR_TRAMWAY_DEPOT_WITH_TRACK - SPR_TRAMWAY_BASE ;
static const SpriteID depot_no_track_offset = SPR_TRAMWAY_DEPOT_NO_TRACK - SPR_TRAMWAY_BASE ;
if ( offset < = depot_with_track_offset & & offset + num > depot_with_track_offset ) _loaded_newgrf_features . tram = TRAMWAY_REPLACE_DEPOT_WITH_TRACK ;
if ( offset < = depot_no_track_offset & & offset + num > depot_no_track_offset ) _loaded_newgrf_features . tram = TRAMWAY_REPLACE_DEPOT_NO_TRACK ;
}
for ( uint16 n = num ; n > 0 ; n - - ) {
_cur . nfo_line + + ;
LoadNextSprite ( replace = = 0 ? _cur . spriteid + + : replace + + , _cur . file_index , _cur . nfo_line , _cur . grf_container_ver ) ;
@ -6043,8 +6347,6 @@ static void GraphicsNew(ByteReader *buf)
}
}
if ( type = = 0x0D ) _loaded_newgrf_features . shore = SHORE_REPLACE_ACTION_5 ;
_cur . skip_sprites = skip_num ;
}
@ -6468,6 +6770,14 @@ static void SkipIf(ByteReader *buf)
break ;
case 0x0E : result = GetRailTypeByLabel ( BSWAP32 ( cond_val ) ) ! = INVALID_RAILTYPE ;
break ;
case 0x0F : result = GetRoadTypeByLabel ( BSWAP32 ( cond_val ) ) = = INVALID_ROADTYPE ;
break ;
case 0x10 : result = GetRoadTypeByLabel ( BSWAP32 ( cond_val ) ) ! = INVALID_ROADTYPE ;
break ;
case 0x11 : result = GetRoadTypeByLabel ( BSWAP32 ( cond_val ) ) = = INVALID_ROADTYPE ;
break ;
case 0x12 : result = GetRoadTypeByLabel ( BSWAP32 ( cond_val ) ) ! = INVALID_ROADTYPE ;
break ;
default : grfmsg ( 1 , " SkipIf: Unsupported condition type %02X. Ignoring " , condtype ) ; return ;
}
@ -8830,6 +9140,9 @@ void ResetNewGRFData()
/* Reset rail type information */
ResetRailTypes ( ) ;
/* Copy/reset original road type info data */
ResetRoadTypes ( ) ;
/* Allocate temporary refit/cargo class data */
_gted = CallocT < GRFTempEngineData > ( Engine : : GetPoolSize ( ) ) ;
@ -8898,6 +9211,7 @@ void ResetNewGRFData()
_loaded_newgrf_features . has_newhouses = false ;
_loaded_newgrf_features . has_newindustries = false ;
_loaded_newgrf_features . shore = SHORE_REPLACE_NONE ;
_loaded_newgrf_features . tram = TRAMWAY_REPLACE_DEPOT_NONE ;
/* Clear all GRF overrides */
_grf_id_overrides . clear ( ) ;
@ -8985,6 +9299,14 @@ GRFFile::GRFFile(const GRFConfig *config)
this - > railtype_map [ 2 ] = RAILTYPE_MONO ;
this - > railtype_map [ 3 ] = RAILTYPE_MAGLEV ;
/* Initialise road type map with default road types */
memset ( this - > roadtype_map , INVALID_ROADTYPE , sizeof ( this - > roadtype_map ) ) ;
this - > roadtype_map [ 0 ] = ROADTYPE_ROAD ;
/* Initialise tram type map with default tram types */
memset ( this - > tramtype_map , INVALID_ROADTYPE , sizeof ( this - > tramtype_map ) ) ;
this - > tramtype_map [ 0 ] = ROADTYPE_TRAM ;
/* Copy the initial parameter list
* ' Uninitialised ' parameters are zeroed as that is their default value when dynamically creating them . */
assert_compile ( lengthof ( this - > param ) = = lengthof ( config - > param ) & & lengthof ( this - > param ) = = 0x80 ) ;
@ -9754,6 +10076,21 @@ static void ActivateOldShore()
}
}
/**
* Replocate the old tram depot sprites to the new position , if no new ones were loaded .
*/
static void ActivateOldTramDepot ( )
{
if ( _loaded_newgrf_features . tram = = TRAMWAY_REPLACE_DEPOT_WITH_TRACK ) {
DupSprite ( SPR_ROAD_DEPOT + 0 , SPR_TRAMWAY_DEPOT_NO_TRACK + 0 ) ; // use road depot graphics for "no tracks"
DupSprite ( SPR_TRAMWAY_DEPOT_WITH_TRACK + 1 , SPR_TRAMWAY_DEPOT_NO_TRACK + 1 ) ;
DupSprite ( SPR_ROAD_DEPOT + 2 , SPR_TRAMWAY_DEPOT_NO_TRACK + 2 ) ; // use road depot graphics for "no tracks"
DupSprite ( SPR_TRAMWAY_DEPOT_WITH_TRACK + 3 , SPR_TRAMWAY_DEPOT_NO_TRACK + 3 ) ;
DupSprite ( SPR_TRAMWAY_DEPOT_WITH_TRACK + 4 , SPR_TRAMWAY_DEPOT_NO_TRACK + 4 ) ;
DupSprite ( SPR_TRAMWAY_DEPOT_WITH_TRACK + 5 , SPR_TRAMWAY_DEPOT_NO_TRACK + 5 ) ;
}
}
/**
* Decide whether price base multipliers of grfs shall apply globally or only to the grf specifying them
*/
@ -9932,8 +10269,12 @@ static void AfterLoadGRFs()
/* Load old shore sprites in new position, if they were replaced by ActionA */
ActivateOldShore ( ) ;
/* Load old tram depot sprites in new position, if no new ones are present */
ActivateOldTramDepot ( ) ;
/* Set up custom rail types */
InitRailTypes ( ) ;
InitRoadTypes ( ) ;
Engine * e ;
FOR_ALL_ENGINES_OF_TYPE ( e , VEH_ROAD ) {
@ -9941,6 +10282,31 @@ static void AfterLoadGRFs()
/* Set RV maximum speed from the mph/0.8 unit value */
e - > u . road . max_speed = _gted [ e - > index ] . rv_max_speed * 4 ;
}
RoadTramType rtt = HasBit ( e - > info . misc_flags , EF_ROAD_TRAM ) ? RTT_TRAM : RTT_ROAD ;
const GRFFile * file = e - > GetGRF ( ) ;
if ( file = = nullptr | | _gted [ e - > index ] . roadtramtype = = 0 ) {
e - > u . road . roadtype = ( rtt = = RTT_TRAM ) ? ROADTYPE_TRAM : ROADTYPE_ROAD ;
continue ;
}
/* Remove +1 offset. */
_gted [ e - > index ] . roadtramtype - - ;
const std : : vector < RoadTypeLabel > * list = ( rtt = = RTT_TRAM ) ? & file - > tramtype_list : & file - > roadtype_list ;
if ( _gted [ e - > index ] . roadtramtype < list - > size ( ) )
{
RoadTypeLabel rtl = ( * list ) [ _gted [ e - > index ] . roadtramtype ] ;
RoadType rt = GetRoadTypeByLabel ( rtl ) ;
if ( rt ! = INVALID_ROADTYPE & & GetRoadTramType ( rt ) = = rtt ) {
e - > u . road . roadtype = rt ;
continue ;
}
}
/* Road type is not available, so disable this engine */
e - > info . climates = 0 ;
}
FOR_ALL_ENGINES_OF_TYPE ( e , VEH_TRAIN ) {