2007-01-14 19:18:50 +00:00
/* $Id$ */
2008-05-06 15:11:33 +00:00
/** @file station.cpp Implementation of the station base class. */
2007-01-14 19:18:50 +00:00
# include "stdafx.h"
# include "openttd.h"
# include "bridge_map.h"
# include "debug.h"
# include "station_map.h"
2008-03-31 00:06:17 +00:00
# include "station_base.h"
2007-01-14 19:18:50 +00:00
# include "town.h"
# include "saveload.h"
2008-09-30 20:51:04 +00:00
# include "company_func.h"
2007-01-14 19:18:50 +00:00
# include "airport.h"
# include "sprite.h"
# include "train.h"
# include "water_map.h"
# include "industry_map.h"
# include "newgrf_callbacks.h"
# include "newgrf_station.h"
# include "yapf/yapf.h"
2007-08-24 19:19:18 +00:00
# include "cargotype.h"
# include "roadveh.h"
2008-04-24 09:55:20 +00:00
# include "window_type.h"
2007-12-05 17:08:10 +00:00
# include "station_gui.h"
2007-12-23 10:56:02 +00:00
# include "zoom_func.h"
2007-12-25 11:26:07 +00:00
# include "functions.h"
# include "window_func.h"
2007-12-26 13:50:40 +00:00
# include "date_func.h"
2008-01-07 00:57:19 +00:00
# include "variables.h"
2008-01-13 14:37:30 +00:00
# include "settings_type.h"
2008-01-13 21:41:24 +00:00
# include "command_func.h"
2008-03-30 23:24:18 +00:00
# include "order_func.h"
2008-09-13 10:19:51 +00:00
# include "news_func.h"
2008-09-16 16:07:18 +00:00
# include "aircraft.h"
2007-01-14 19:18:50 +00:00
2008-01-13 01:21:35 +00:00
# include "table/sprites.h"
# include "table/strings.h"
2007-01-14 19:18:50 +00:00
Station : : Station ( TileIndex tile )
{
DEBUG ( station , cDebugCtorLevel , " I+%3d " , index ) ;
xy = tile ;
2008-12-26 18:01:15 +00:00
airport_tile = dock_tile = train_tile = INVALID_TILE ;
2007-01-14 19:18:50 +00:00
bus_stops = truck_stops = NULL ;
had_vehicle_of_type = 0 ;
time_since_load = 255 ;
time_since_unload = 255 ;
delete_ctr = 0 ;
facilities = 0 ;
2007-03-08 16:27:54 +00:00
last_vehicle_type = VEH_INVALID ;
2008-11-19 23:55:34 +00:00
indtype = IT_INVALID ;
2007-01-14 19:18:50 +00:00
2007-01-18 09:34:44 +00:00
random_bits = 0 ; // Random() must be called when station is really built (DC_EXEC)
2007-01-14 19:18:50 +00:00
waiting_triggers = 0 ;
}
/**
2007-04-04 01:35:16 +00:00
* Clean up a station by clearing vehicle orders and invalidating windows .
* Aircraft - Hangar orders need special treatment here , as the hangars are
* actually part of a station ( tiletype is STATION ) , but the order type
* is OT_GOTO_DEPOT .
*/
2007-01-14 19:18:50 +00:00
Station : : ~ Station ( )
{
DEBUG ( station , cDebugCtorLevel , " I-%3d " , index ) ;
2008-01-12 19:58:06 +00:00
free ( this - > name ) ;
2007-08-05 21:20:55 +00:00
free ( this - > speclist ) ;
if ( CleaningPool ( ) ) return ;
2007-08-18 22:56:58 +00:00
while ( ! loading_vehicles . empty ( ) ) {
loading_vehicles . front ( ) - > LeaveStation ( ) ;
}
2008-09-16 16:07:18 +00:00
Vehicle * v ;
FOR_ALL_VEHICLES ( v ) {
if ( v - > type = = VEH_AIRCRAFT & & IsNormalAircraft ( v ) & & v - > u . air . targetairport = = this - > index ) {
v - > u . air . targetairport = INVALID_STATION ;
}
}
2007-01-14 19:18:50 +00:00
MarkDirty ( ) ;
2008-05-18 16:51:44 +00:00
InvalidateWindowData ( WC_STATION_LIST , this - > owner , 0 ) ;
2007-01-14 19:18:50 +00:00
DeleteWindowById ( WC_STATION_VIEW , index ) ;
/* Now delete all orders that go to the station */
RemoveOrderFromAllVehicles ( OT_GOTO_STATION , index ) ;
2007-01-14 23:36:25 +00:00
/* Subsidies need removal as well */
2007-01-14 19:18:50 +00:00
DeleteSubsidyWithStation ( index ) ;
2008-09-13 10:19:51 +00:00
/* Remove all news items */
DeleteStationNews ( this - > index ) ;
2008-12-26 18:01:15 +00:00
xy = INVALID_TILE ;
2007-06-22 11:58:59 +00:00
for ( CargoID c = 0 ; c < NUM_CARGO ; c + + ) {
goods [ c ] . cargo . Truncate ( 0 ) ;
}
2007-08-01 23:49:06 +00:00
}
2007-08-24 19:19:18 +00:00
/**
* Get the primary road stop ( the first road stop ) that the given vehicle can load / unload .
* @ param v the vehicle to get the first road stop for
* @ return the first roadstop that this vehicle can load at
*/
RoadStop * Station : : GetPrimaryRoadStop ( const Vehicle * v ) const
{
2008-03-31 00:06:17 +00:00
RoadStop * rs = this - > GetPrimaryRoadStop ( IsCargoInClass ( v - > cargo_type , CC_PASSENGERS ) ? ROADSTOP_BUS : ROADSTOP_TRUCK ) ;
2007-08-24 19:19:18 +00:00
for ( ; rs ! = NULL ; rs = rs - > next ) {
/* The vehicle cannot go to this roadstop (different roadtype) */
if ( ( GetRoadTypes ( rs - > xy ) & v - > u . road . compatible_roadtypes ) = = ROADTYPES_NONE ) continue ;
/* The vehicle is articulated and can therefor not go the a standard road stop */
if ( IsStandardRoadStopTile ( rs - > xy ) & & RoadVehHasArticPart ( v ) ) continue ;
/* The vehicle can actually go to this road stop. So, return it! */
break ;
}
return rs ;
}
2007-01-18 09:34:44 +00:00
/** Called when new facility is built on the station. If it is the first facility
2007-04-04 01:35:16 +00:00
* it initializes also ' xy ' and ' random_bits ' members */
2007-01-18 09:34:44 +00:00
void Station : : AddFacility ( byte new_facility_bit , TileIndex facil_xy )
{
if ( facilities = = 0 ) {
xy = facil_xy ;
random_bits = Random ( ) ;
}
facilities | = new_facility_bit ;
2008-09-30 20:39:50 +00:00
owner = _current_company ;
2007-01-18 09:34:44 +00:00
build_date = _date ;
}
2007-01-14 19:18:50 +00:00
void Station : : MarkDirty ( ) const
{
if ( sign . width_1 ! = 0 ) {
2007-12-05 17:08:10 +00:00
InvalidateWindowWidget ( WC_STATION_VIEW , index , SVW_CAPTION ) ;
2007-01-14 19:18:50 +00:00
2007-05-26 12:19:54 +00:00
/* We use ZOOM_LVL_MAX here, as every viewport can have an other zoom,
* and there is no way for us to know which is the biggest . So make the
* biggest area dirty , and we are safe for sure . */
2007-01-14 19:18:50 +00:00
MarkAllViewportsDirty (
sign . left - 6 ,
sign . top ,
2007-05-26 12:19:54 +00:00
sign . left + ScaleByZoom ( sign . width_1 + 12 , ZOOM_LVL_MAX ) ,
sign . top + ScaleByZoom ( 12 , ZOOM_LVL_MAX ) ) ;
2007-01-14 19:18:50 +00:00
}
}
2007-06-08 09:35:39 +00:00
void Station : : MarkTilesDirty ( bool cargo_change ) const
2007-01-14 19:18:50 +00:00
{
TileIndex tile = train_tile ;
int w , h ;
2008-12-26 18:01:15 +00:00
if ( tile = = INVALID_TILE ) return ;
2007-01-14 19:18:50 +00:00
2007-06-08 09:35:39 +00:00
/* cargo_change is set if we're refreshing the tiles due to cargo moving
* around . */
if ( cargo_change ) {
/* Don't waste time updating if there are no custom station graphics
* that might change . Even if there are custom graphics , they might
* not change . Unfortunately we have no way of telling . */
if ( this - > num_specs = = 0 ) return ;
}
2007-01-14 19:18:50 +00:00
for ( h = 0 ; h < trainst_h ; h + + ) {
for ( w = 0 ; w < trainst_w ; w + + ) {
if ( TileBelongsToRailStation ( tile ) ) {
MarkTileDirtyByTile ( tile ) ;
}
tile + = TileDiffXY ( 1 , 0 ) ;
}
tile + = TileDiffXY ( - w , 1 ) ;
}
}
bool Station : : TileBelongsToRailStation ( TileIndex tile ) const
{
return IsTileType ( tile , MP_STATION ) & & GetStationIndex ( tile ) = = index & & IsRailwayStation ( tile ) ;
}
2007-02-13 16:36:38 +00:00
/** Obtain the length of a platform
* @ pre tile must be a railway station tile
* @ param tile A tile that contains the platform in question
2007-04-04 01:35:16 +00:00
* @ return The length of the platform
2007-02-13 16:36:38 +00:00
*/
uint Station : : GetPlatformLength ( TileIndex tile ) const
{
TileIndex t ;
TileIndexDiff delta ;
uint len = 0 ;
assert ( TileBelongsToRailStation ( tile ) ) ;
delta = ( GetRailStationAxis ( tile ) = = AXIS_X ? TileDiffXY ( 1 , 0 ) : TileDiffXY ( 0 , 1 ) ) ;
t = tile ;
do {
t - = delta ;
len + + ;
} while ( IsCompatibleTrainStationTile ( t , tile ) ) ;
t = tile ;
do {
t + = delta ;
len + + ;
} while ( IsCompatibleTrainStationTile ( t , tile ) ) ;
return len - 1 ;
}
/** Determines the REMAINING length of a platform, starting at (and including)
* the given tile .
* @ param tile the tile from which to start searching . Must be a railway station tile
* @ param dir The direction in which to search .
* @ return The platform length
*/
uint Station : : GetPlatformLength ( TileIndex tile , DiagDirection dir ) const
{
TileIndex start_tile = tile ;
uint length = 0 ;
assert ( IsRailwayStationTile ( tile ) ) ;
assert ( dir < DIAGDIR_END ) ;
do {
length + + ;
tile + = TileOffsByDiagDir ( dir ) ;
} while ( IsCompatibleTrainStationTile ( tile , start_tile ) ) ;
return length ;
}
2007-02-01 16:48:38 +00:00
/** Determines whether a station is a buoy only.
* @ todo Ditch this encoding of buoys
*/
bool Station : : IsBuoy ( ) const
{
2007-02-13 15:44:37 +00:00
return ( had_vehicle_of_type & HVOT_BUOY ) ! = 0 ;
2007-02-01 16:48:38 +00:00
}
2008-10-25 14:19:09 +00:00
/** Determines the catchment radius of the station
* @ return The radius
*/
uint Station : : GetCatchmentRadius ( ) const
{
uint ret = CA_NONE ;
if ( _settings_game . station . modified_catchment ) {
2008-12-26 18:01:15 +00:00
if ( this - > bus_stops ! = NULL ) ret = max < uint > ( ret , CA_BUS ) ;
if ( this - > truck_stops ! = NULL ) ret = max < uint > ( ret , CA_TRUCK ) ;
if ( this - > train_tile ! = INVALID_TILE ) ret = max < uint > ( ret , CA_TRAIN ) ;
if ( this - > dock_tile ! = INVALID_TILE ) ret = max < uint > ( ret , CA_DOCK ) ;
if ( this - > airport_tile ! = INVALID_TILE ) ret = max < uint > ( ret , this - > Airport ( ) - > catchment ) ;
2008-10-25 14:19:09 +00:00
} else {
2008-12-26 18:01:15 +00:00
if ( this - > bus_stops ! = NULL | | this - > truck_stops ! = NULL | | this - > train_tile ! = INVALID_TILE | | this - > dock_tile ! = INVALID_TILE | | this - > airport_tile ! = INVALID_TILE ) {
2008-10-25 14:19:09 +00:00
ret = CA_UNMODIFIED ;
}
}
return ret ;
}
2007-01-14 23:02:12 +00:00
/************************************************************************/
/* StationRect implementation */
/************************************************************************/
StationRect : : StationRect ( )
{
MakeEmpty ( ) ;
}
void StationRect : : MakeEmpty ( )
{
left = top = right = bottom = 0 ;
}
2007-02-02 16:51:10 +00:00
/**
* Determines whether a given point ( x , y ) is within a certain distance of
* the station rectangle .
* @ note x and y are in Tile coordinates
* @ param x X coordinate
* @ param y Y coordinate
* @ param distance The maxmium distance a point may have ( L1 norm )
* @ return true if the point is within distance tiles of the station rectangle
*/
bool StationRect : : PtInExtendedRect ( int x , int y , int distance ) const
2007-01-14 23:02:12 +00:00
{
2007-02-02 16:51:10 +00:00
return ( left - distance < = x & & x < = right + distance & & top - distance < = y & & y < = bottom + distance ) ;
2007-01-14 23:02:12 +00:00
}
bool StationRect : : IsEmpty ( ) const
{
return ( left = = 0 | | left > right | | top > bottom ) ;
}
bool StationRect : : BeforeAddTile ( TileIndex tile , StationRectMode mode )
{
int x = TileX ( tile ) ;
int y = TileY ( tile ) ;
if ( IsEmpty ( ) ) {
2007-01-14 23:36:25 +00:00
/* we are adding the first station tile */
2008-10-15 21:10:43 +00:00
if ( mode ! = ADD_TEST ) {
left = right = x ;
top = bottom = y ;
}
2007-02-02 16:51:10 +00:00
} else if ( ! PtInExtendedRect ( x , y ) ) {
2007-01-14 23:36:25 +00:00
/* current rect is not empty and new point is outside this rect */
/* make new spread-out rectangle */
2007-01-14 23:02:12 +00:00
Rect new_rect = { min ( x , left ) , min ( y , top ) , max ( x , right ) , max ( y , bottom ) } ;
2007-01-14 23:36:25 +00:00
/* check new rect dimensions against preset max */
2007-01-14 23:02:12 +00:00
int w = new_rect . right - new_rect . left + 1 ;
int h = new_rect . bottom - new_rect . top + 1 ;
2008-05-29 15:13:28 +00:00
if ( mode ! = ADD_FORCE & & ( w > _settings_game . station . station_spread | | h > _settings_game . station . station_spread ) ) {
2007-01-14 23:02:12 +00:00
assert ( mode ! = ADD_TRY ) ;
_error_message = STR_306C_STATION_TOO_SPREAD_OUT ;
return false ;
}
2007-01-14 23:36:25 +00:00
/* spread-out ok, return true */
2007-01-14 23:02:12 +00:00
if ( mode ! = ADD_TEST ) {
2007-01-14 23:36:25 +00:00
/* we should update the station rect */
2007-01-14 23:02:12 +00:00
* this = new_rect ;
}
} else {
; // new point is inside the rect, we don't need to do anything
}
return true ;
}
bool StationRect : : BeforeAddRect ( TileIndex tile , int w , int h , StationRectMode mode )
{
2008-10-15 21:10:43 +00:00
return ( mode = = ADD_FORCE | | ( w < = _settings_game . station . station_spread & & h < = _settings_game . station . station_spread ) ) & & // important when the old rect is completely inside the new rect, resp. the old one was empty
BeforeAddTile ( tile , mode ) & & BeforeAddTile ( TILE_ADDXY ( tile , w - 1 , h - 1 ) , mode ) ;
2007-01-14 23:02:12 +00:00
}
2008-10-19 15:39:12 +00:00
/**
* Check whether station tiles of the given station id exist in the given rectangle
* @ param st_id Station ID to look for in the rectangle
* @ param left_a Minimal tile X edge of the rectangle
* @ param top_a Minimal tile Y edge of the rectangle
* @ param right_a Maximal tile X edge of the rectangle ( inclusive )
* @ param bottom_a Maximal tile Y edge of the rectangle ( inclusive )
* @ return \ c true if a station tile with the given \ a st_id exists in the rectangle , \ c false otherwise
*/
2007-01-14 23:02:12 +00:00
/*static*/ bool StationRect : : ScanForStationTiles ( StationID st_id , int left_a , int top_a , int right_a , int bottom_a )
{
TileIndex top_left = TileXY ( left_a , top_a ) ;
int width = right_a - left_a + 1 ;
int height = bottom_a - top_a + 1 ;
2007-01-14 23:36:25 +00:00
2007-01-14 23:02:12 +00:00
BEGIN_TILE_LOOP ( tile , width , height , top_left )
if ( IsTileType ( tile , MP_STATION ) & & GetStationIndex ( tile ) = = st_id ) return true ;
END_TILE_LOOP ( tile , width , height , top_left ) ;
2007-01-14 23:36:25 +00:00
2007-01-14 23:02:12 +00:00
return false ;
}
bool StationRect : : AfterRemoveTile ( Station * st , TileIndex tile )
{
int x = TileX ( tile ) ;
int y = TileY ( tile ) ;
2007-01-14 23:36:25 +00:00
/* look if removed tile was on the bounding rect edge
* and try to reduce the rect by this edge
* do it until we have empty rect or nothing to do */
2007-01-14 23:02:12 +00:00
for ( ; ; ) {
2007-01-14 23:36:25 +00:00
/* check if removed tile is on rect edge */
2007-01-14 23:02:12 +00:00
bool left_edge = ( x = = left ) ;
bool right_edge = ( x = = right ) ;
bool top_edge = ( y = = top ) ;
bool bottom_edge = ( y = = bottom ) ;
2007-01-14 23:36:25 +00:00
/* can we reduce the rect in either direction? */
bool reduce_x = ( ( left_edge | | right_edge ) & & ! ScanForStationTiles ( st - > index , x , top , x , bottom ) ) ;
bool reduce_y = ( ( top_edge | | bottom_edge ) & & ! ScanForStationTiles ( st - > index , left , y , right , y ) ) ;
2007-01-14 23:02:12 +00:00
if ( ! ( reduce_x | | reduce_y ) ) break ; // nothing to do (can't reduce)
2007-01-14 23:36:25 +00:00
2007-01-14 23:02:12 +00:00
if ( reduce_x ) {
2007-01-14 23:36:25 +00:00
/* reduce horizontally */
2007-01-14 23:02:12 +00:00
if ( left_edge ) {
2007-01-14 23:36:25 +00:00
/* move left edge right */
2007-01-14 23:02:12 +00:00
left = x = x + 1 ;
} else {
2007-01-14 23:36:25 +00:00
/* move right edge left */
2007-01-14 23:02:12 +00:00
right = x = x - 1 ;
}
}
if ( reduce_y ) {
2007-01-14 23:36:25 +00:00
/* reduce vertically */
2007-01-14 23:02:12 +00:00
if ( top_edge ) {
2007-01-14 23:36:25 +00:00
/* move top edge down */
2007-01-14 23:02:12 +00:00
top = y = y + 1 ;
} else {
2007-01-14 23:36:25 +00:00
/* move bottom edge up */
2007-01-14 23:02:12 +00:00
bottom = y = y - 1 ;
}
}
2007-01-14 23:36:25 +00:00
2007-01-14 23:02:12 +00:00
if ( left > right | | top > bottom ) {
2007-01-14 23:36:25 +00:00
/* can't continue, if the remaining rectangle is empty */
2007-01-14 23:02:12 +00:00
MakeEmpty ( ) ;
return true ; // empty remaining rect
}
}
return false ; // non-empty remaining rect
}
bool StationRect : : AfterRemoveRect ( Station * st , TileIndex tile , int w , int h )
{
2007-02-02 16:51:10 +00:00
assert ( PtInExtendedRect ( TileX ( tile ) , TileY ( tile ) ) ) ;
assert ( PtInExtendedRect ( TileX ( tile ) + w - 1 , TileY ( tile ) + h - 1 ) ) ;
2007-01-14 23:36:25 +00:00
bool empty = AfterRemoveTile ( st , tile ) ;
2007-01-14 23:02:12 +00:00
if ( w ! = 1 | | h ! = 1 ) empty = empty | | AfterRemoveTile ( st , TILE_ADDXY ( tile , w - 1 , h - 1 ) ) ;
return empty ;
}
StationRect & StationRect : : operator = ( Rect src )
{
left = src . left ;
top = src . top ;
right = src . right ;
bottom = src . bottom ;
return * this ;
}
2007-01-17 11:15:51 +00:00
/************************************************************************/
/* RoadStop implementation */
/************************************************************************/
/** Initializes a RoadStop */
2007-01-17 21:14:17 +00:00
RoadStop : : RoadStop ( TileIndex tile ) :
2007-01-17 20:34:29 +00:00
xy ( tile ) ,
status ( 3 ) , // stop is free
num_vehicles ( 0 ) ,
2007-01-28 21:54:40 +00:00
next ( NULL )
2007-01-17 11:15:51 +00:00
{
2007-01-17 21:14:17 +00:00
DEBUG ( ms , cDebugCtorLevel , " I+ at %d[0x%x] " , tile , tile ) ;
2007-01-17 11:15:51 +00:00
}
/** De-Initializes a RoadStops. This includes clearing all slots that vehicles might
* have and unlinks it from the linked list of road stops at the given station
*/
RoadStop : : ~ RoadStop ( )
{
2007-08-06 14:08:25 +00:00
if ( CleaningPool ( ) ) return ;
2007-01-17 11:15:51 +00:00
/* Clear the slot assignment of all vehicles heading for this road stop */
if ( num_vehicles ! = 0 ) {
2007-01-17 20:34:29 +00:00
Vehicle * v ;
2007-01-17 11:15:51 +00:00
FOR_ALL_VEHICLES ( v ) {
2007-03-08 16:27:54 +00:00
if ( v - > type = = VEH_ROAD & & v - > u . road . slot = = this ) ClearSlot ( v ) ;
2007-01-17 11:15:51 +00:00
}
}
assert ( num_vehicles = = 0 ) ;
2007-01-17 21:14:17 +00:00
DEBUG ( ms , cDebugCtorLevel , " I- at %d[0x%x] " , xy , xy ) ;
2007-01-17 11:15:51 +00:00
2008-12-26 18:01:15 +00:00
xy = INVALID_TILE ;
2007-01-17 11:15:51 +00:00
}
2007-01-25 08:58:09 +00:00
2007-02-13 00:25:42 +00:00
/** Checks whether there is a free bay in this road stop */
bool RoadStop : : HasFreeBay ( ) const
{
return GB ( status , 0 , MAX_BAY_COUNT ) ! = 0 ;
}
2007-02-14 16:37:16 +00:00
/** Checks whether the given bay is free in this road stop */
bool RoadStop : : IsFreeBay ( uint nr ) const
{
assert ( nr < MAX_BAY_COUNT ) ;
2007-11-19 21:02:30 +00:00
return HasBit ( status , nr ) ;
2007-02-14 16:37:16 +00:00
}
2007-02-13 00:25:42 +00:00
/**
* Allocates a bay
* @ return the allocated bay number
* @ pre this - > HasFreeBay ( )
*/
uint RoadStop : : AllocateBay ( )
{
2007-02-14 09:34:12 +00:00
assert ( HasFreeBay ( ) ) ;
2007-02-13 00:25:42 +00:00
/* Find the first free bay. If the bit is set, the bay is free. */
2007-02-14 09:34:12 +00:00
uint bay_nr = 0 ;
2007-11-19 21:02:30 +00:00
while ( ! HasBit ( status , bay_nr ) ) bay_nr + + ;
2007-02-13 00:25:42 +00:00
2007-11-19 21:32:20 +00:00
ClrBit ( status , bay_nr ) ;
2007-02-14 09:34:12 +00:00
return bay_nr ;
2007-02-13 00:25:42 +00:00
}
2007-02-14 16:37:16 +00:00
/**
* Allocates a bay in a drive - through road stop
* @ param nr the number of the bay to allocate
*/
void RoadStop : : AllocateDriveThroughBay ( uint nr )
{
assert ( nr < MAX_BAY_COUNT ) ;
2007-11-19 21:32:20 +00:00
ClrBit ( status , nr ) ;
2007-02-14 16:37:16 +00:00
}
2007-02-13 00:25:42 +00:00
/**
* Frees the given bay
* @ param nr the number of the bay to free
*/
void RoadStop : : FreeBay ( uint nr )
{
assert ( nr < MAX_BAY_COUNT ) ;
2007-11-20 13:35:54 +00:00
SetBit ( status , nr ) ;
2007-02-13 00:25:42 +00:00
}
/** Checks whether the entrance of the road stop is occupied by a vehicle */
bool RoadStop : : IsEntranceBusy ( ) const
{
2007-11-19 21:02:30 +00:00
return HasBit ( status , 7 ) ;
2007-02-13 00:25:42 +00:00
}
/** Makes an entrance occupied or free */
void RoadStop : : SetEntranceBusy ( bool busy )
{
2007-02-14 09:34:12 +00:00
SB ( status , 7 , 1 , busy ) ;
2007-02-13 00:25:42 +00:00
}
2007-08-24 19:19:18 +00:00
/**
* Get the next road stop accessible by this vehicle .
* @ param v the vehicle to get the next road stop for .
* @ return the next road stop accessible .
*/
RoadStop * RoadStop : : GetNextRoadStop ( const Vehicle * v ) const
{
for ( RoadStop * rs = this - > next ; rs ! = NULL ; rs = rs - > next ) {
/* The vehicle cannot go to this roadstop (different roadtype) */
2007-08-25 20:05:58 +00:00
if ( ( GetRoadTypes ( rs - > xy ) & v - > u . road . compatible_roadtypes ) = = ROADTYPES_NONE ) continue ;
2007-08-24 19:19:18 +00:00
/* The vehicle is articulated and can therefor not go the a standard road stop */
if ( IsStandardRoadStopTile ( rs - > xy ) & & RoadVehHasArticPart ( v ) ) continue ;
/* The vehicle can actually go to this road stop. So, return it! */
return rs ;
}
return NULL ;
}