2007-01-14 19:18:50 +00:00
/* $Id$ */
2009-08-21 20:21:05 +00:00
/*
* 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/>.
*/
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"
2008-09-30 20:51:04 +00:00
# include "company_func.h"
2009-01-31 20:16:06 +00:00
# include "newgrf_cargo.h"
2007-08-24 19:19:18 +00:00
# include "cargotype.h"
# include "roadveh.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-13 21:41:24 +00:00
# include "command_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"
2009-01-02 20:59:04 +00:00
# include "vehicle_gui.h"
2009-05-22 15:13:50 +00:00
# include "core/pool_func.hpp"
2009-06-24 17:39:54 +00:00
# include "station_base.h"
2009-06-23 21:44:48 +00:00
# include "roadstop_base.h"
2009-08-30 11:47:41 +00:00
# include "industry.h"
2007-01-14 19:18:50 +00:00
2008-01-13 01:21:35 +00:00
# include "table/strings.h"
2009-05-22 15:13:50 +00:00
StationPool _station_pool ( " Station " ) ;
INSTANTIATE_POOL_METHODS ( Station )
2009-07-17 20:30:07 +00:00
BaseStation : : ~ BaseStation ( )
{
free ( this - > name ) ;
free ( this - > speclist ) ;
}
2009-06-23 20:32:51 +00:00
Station : : Station ( TileIndex tile ) :
2009-07-18 18:39:17 +00:00
SpecializedStation < Station , false > ( tile ) ,
2009-06-23 20:32:51 +00:00
airport_tile ( INVALID_TILE ) ,
dock_tile ( INVALID_TILE ) ,
indtype ( IT_INVALID ) ,
time_since_load ( 255 ) ,
time_since_unload ( 255 ) ,
last_vehicle_type ( VEH_INVALID )
2007-01-14 19:18:50 +00:00
{
2009-06-23 20:32:51 +00:00
/* this->random_bits is set in Station::AddFacility() */
2007-01-14 19:18:50 +00:00
}
/**
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 ( )
{
2007-08-05 21:20:55 +00:00
if ( CleaningPool ( ) ) return ;
2009-07-07 11:21:29 +00:00
while ( ! this - > loading_vehicles . empty ( ) ) {
this - > loading_vehicles . front ( ) - > LeaveStation ( ) ;
2007-08-18 22:56:58 +00:00
}
2009-05-26 22:10:13 +00:00
Aircraft * a ;
FOR_ALL_AIRCRAFT ( a ) {
2009-07-13 16:37:27 +00:00
if ( ! a - > IsNormalAircraft ( ) ) continue ;
2009-05-22 20:07:26 +00:00
if ( a - > targetairport = = this - > index ) a - > targetairport = INVALID_STATION ;
2008-09-16 16:07:18 +00:00
}
2009-05-31 09:33:12 +00:00
Vehicle * v ;
FOR_ALL_VEHICLES ( v ) {
/* Forget about this station if this station is removed */
2009-05-31 09:34:40 +00:00
if ( v - > last_station_visited = = this - > index ) {
2009-05-31 09:33:12 +00:00
v - > last_station_visited = INVALID_STATION ;
}
}
2009-07-08 12:01:26 +00:00
this - > sign . 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 ) ;
2009-07-07 11:21:29 +00:00
WindowNumber wno = ( this - > index < < 16 ) | VLW_STATION_LIST | this - > owner ;
2009-01-02 20:59:04 +00:00
DeleteWindowById ( WC_TRAINS_LIST , wno | ( VEH_TRAIN < < 11 ) ) ;
DeleteWindowById ( WC_ROADVEH_LIST , wno | ( VEH_ROAD < < 11 ) ) ;
DeleteWindowById ( WC_SHIPS_LIST , wno | ( VEH_SHIP < < 11 ) ) ;
DeleteWindowById ( WC_AIRCRAFT_LIST , wno | ( VEH_AIRCRAFT < < 11 ) ) ;
2007-01-14 19:18:50 +00:00
/* Now delete all orders that go to the station */
2009-08-07 22:23:34 +00:00
RemoveOrderFromAllVehicles ( OT_GOTO_STATION , this - > index ) ;
2007-01-14 19:18:50 +00:00
2008-09-13 10:19:51 +00:00
/* Remove all news items */
DeleteStationNews ( this - > index ) ;
2007-06-22 11:58:59 +00:00
for ( CargoID c = 0 ; c < NUM_CARGO ; c + + ) {
2009-07-07 11:21:29 +00:00
this - > goods [ c ] . cargo . Truncate ( 0 ) ;
2007-06-22 11:58:59 +00:00
}
2009-05-23 19:43:09 +00:00
CargoPacket * cp ;
FOR_ALL_CARGOPACKETS ( cp ) {
/* Don't allow cargo packets with invalid source station */
if ( cp - > source = = this - > index ) cp - > source = INVALID_STATION ;
}
2007-08-01 23:49:06 +00:00
}
2007-08-24 19:19:18 +00:00
2009-07-05 13:20:05 +00:00
/**
* Invalidating of the JoinStation window has to be done
* after removing item from the pool .
* @ param index index of deleted item
*/
2009-09-12 12:56:49 +00:00
void BaseStation : : PostDestructor ( size_t index )
2009-07-05 13:20:05 +00:00
{
InvalidateWindowData ( WC_SELECT_STATION , 0 , 0 ) ;
}
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
*/
2009-05-22 20:18:45 +00:00
RoadStop * Station : : GetPrimaryRoadStop ( const RoadVehicle * v ) const
2007-08-24 19:19:18 +00:00
{
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) */
2009-05-22 20:22:20 +00:00
if ( ( GetRoadTypes ( rs - > xy ) & v - > 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 */
2009-07-02 09:06:15 +00:00
if ( IsStandardRoadStopTile ( rs - > xy ) & & v - > HasArticulatedPart ( ) ) continue ;
2007-08-24 19:19:18 +00:00
/* 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 */
2009-07-04 11:26:57 +00:00
void Station : : AddFacility ( StationFacility new_facility_bit , TileIndex facil_xy )
2007-01-18 09:34:44 +00:00
{
2009-07-07 11:21:29 +00:00
if ( this - > facilities = = FACIL_NONE ) {
this - > xy = facil_xy ;
this - > random_bits = Random ( ) ;
2007-01-18 09:34:44 +00:00
}
2009-07-07 11:21:29 +00:00
this - > facilities | = new_facility_bit ;
this - > owner = _current_company ;
this - > build_date = _date ;
2007-01-18 09:34:44 +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
{
2009-07-25 08:54:19 +00:00
TileIndex tile = this - > train_station . tile ;
2007-01-14 19:18:50 +00:00
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 ;
}
2009-07-25 08:54:19 +00:00
for ( h = 0 ; h < train_station . h ; h + + ) {
for ( w = 0 ; w < train_station . w ; w + + ) {
2009-07-07 11:21:29 +00:00
if ( this - > TileBelongsToRailStation ( tile ) ) {
2007-01-14 19:18:50 +00:00
MarkTileDirtyByTile ( tile ) ;
}
tile + = TileDiffXY ( 1 , 0 ) ;
}
tile + = TileDiffXY ( - w , 1 ) ;
}
}
2009-07-24 15:18:25 +00:00
/* virtual */ uint Station : : GetPlatformLength ( TileIndex tile ) const
2007-02-13 16:36:38 +00:00
{
2009-07-07 11:21:29 +00:00
assert ( this - > TileBelongsToRailStation ( tile ) ) ;
2007-02-13 16:36:38 +00:00
2009-07-07 11:21:29 +00:00
TileIndexDiff delta = ( GetRailStationAxis ( tile ) = = AXIS_X ? TileDiffXY ( 1 , 0 ) : TileDiffXY ( 0 , 1 ) ) ;
2007-02-13 16:36:38 +00:00
2009-07-07 11:21:29 +00:00
TileIndex t = tile ;
uint len = 0 ;
2007-02-13 16:36:38 +00:00
do {
t - = delta ;
len + + ;
} while ( IsCompatibleTrainStationTile ( t , tile ) ) ;
t = tile ;
do {
t + = delta ;
len + + ;
} while ( IsCompatibleTrainStationTile ( t , tile ) ) ;
return len - 1 ;
}
2009-07-24 15:18:25 +00:00
/* virtual */ uint Station : : GetPlatformLength ( TileIndex tile , DiagDirection dir ) const
2007-02-13 16:36:38 +00:00
{
TileIndex start_tile = tile ;
uint length = 0 ;
2009-07-24 11:47:12 +00:00
assert ( IsRailStationTile ( tile ) ) ;
2007-02-13 16:36:38 +00:00
assert ( dir < DIAGDIR_END ) ;
do {
2009-07-24 15:18:25 +00:00
length + + ;
2007-02-13 16:36:38 +00:00
tile + = TileOffsByDiagDir ( dir ) ;
} while ( IsCompatibleTrainStationTile ( tile , start_tile ) ) ;
return length ;
}
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 ) {
2009-07-25 08:54:19 +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_station . 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 {
2009-07-25 08:54:19 +00:00
if ( this - > bus_stops ! = NULL | | this - > truck_stops ! = NULL | | this - > train_station . 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 ;
}
2009-08-07 21:11:58 +00:00
/**
* Determines catchment rectangle of this station
* @ return clamped catchment rectangle
*/
Rect Station : : GetCatchmentRect ( ) const
{
assert ( ! this - > rect . IsEmpty ( ) ) ;
/* Compute acceptance rectangle */
int catchment_radius = this - > GetCatchmentRadius ( ) ;
Rect ret = {
max < int > ( this - > rect . left - catchment_radius , 0 ) ,
max < int > ( this - > rect . top - catchment_radius , 0 ) ,
min < int > ( this - > rect . right + catchment_radius , MapMaxX ( ) ) ,
min < int > ( this - > rect . bottom + catchment_radius , MapMaxY ( ) )
} ;
return ret ;
}
2009-06-25 15:42:03 +00:00
/** Rect and pointer to IndustryVector */
struct RectAndIndustryVector {
Rect rect ;
IndustryVector * industries_near ;
} ;
/**
2009-07-07 11:21:29 +00:00
* Callback function for Station : : RecomputeIndustriesNear ( )
2009-06-25 15:42:03 +00:00
* Tests whether tile is an industry and possibly adds
* the industry to station ' s industries_near list .
* @ param ind_tile tile to check
* @ param user_data pointer to RectAndIndustryVector
* @ return always false , we want to search all tiles
*/
static bool FindIndustryToDeliver ( TileIndex ind_tile , void * user_data )
{
/* Only process industry tiles */
if ( ! IsTileType ( ind_tile , MP_INDUSTRY ) ) return false ;
RectAndIndustryVector * riv = ( RectAndIndustryVector * ) user_data ;
2009-08-30 11:47:41 +00:00
Industry * ind = Industry : : GetByTile ( ind_tile ) ;
2009-06-25 15:42:03 +00:00
/* Don't check further if this industry is already in the list */
if ( riv - > industries_near - > Contains ( ind ) ) return false ;
/* Only process tiles in the station acceptance rectangle */
int x = TileX ( ind_tile ) ;
int y = TileY ( ind_tile ) ;
if ( x < riv - > rect . left | | x > riv - > rect . right | | y < riv - > rect . top | | y > riv - > rect . bottom ) return false ;
/* Include only industries that can accept cargo */
uint cargo_index ;
for ( cargo_index = 0 ; cargo_index < lengthof ( ind - > accepts_cargo ) ; cargo_index + + ) {
if ( ind - > accepts_cargo [ cargo_index ] ! = CT_INVALID ) break ;
}
if ( cargo_index > = lengthof ( ind - > accepts_cargo ) ) return false ;
* riv - > industries_near - > Append ( ) = ind ;
return false ;
}
/**
* Recomputes Station : : industries_near , list of industries possibly
* accepting cargo in station ' s catchment radius
*/
void Station : : RecomputeIndustriesNear ( )
{
2009-08-07 20:30:38 +00:00
this - > industries_near . Clear ( ) ;
2009-06-25 15:42:03 +00:00
if ( this - > rect . IsEmpty ( ) ) return ;
RectAndIndustryVector riv = {
2009-08-07 21:11:58 +00:00
this - > GetCatchmentRect ( ) ,
2009-06-25 15:42:03 +00:00
& this - > industries_near
} ;
/* Compute maximum extent of acceptance rectangle wrt. station sign */
TileIndex start_tile = this - > xy ;
uint max_radius = max (
2009-10-02 15:13:15 +00:00
max ( DistanceManhattan ( start_tile , TileXY ( riv . rect . left , riv . rect . top ) ) , DistanceManhattan ( start_tile , TileXY ( riv . rect . left , riv . rect . bottom ) ) ) ,
2009-06-25 15:42:03 +00:00
max ( DistanceManhattan ( start_tile , TileXY ( riv . rect . right , riv . rect . top ) ) , DistanceManhattan ( start_tile , TileXY ( riv . rect . right , riv . rect . bottom ) ) )
) ;
CircularTileSearch ( & start_tile , 2 * max_radius + 1 , & FindIndustryToDeliver , & riv ) ;
}
/**
* Recomputes Station : : industries_near for all stations
*/
/* static */ void Station : : RecomputeIndustriesNearForAll ( )
{
Station * st ;
FOR_ALL_STATIONS ( st ) st - > RecomputeIndustriesNear ( ) ;
}
2007-01-14 23:02:12 +00:00
/************************************************************************/
/* StationRect implementation */
/************************************************************************/
StationRect : : StationRect ( )
{
2009-07-07 11:21:29 +00:00
this - > MakeEmpty ( ) ;
2007-01-14 23:02:12 +00:00
}
void StationRect : : MakeEmpty ( )
{
2009-07-07 11:21:29 +00:00
this - > left = this - > top = this - > right = this - > bottom = 0 ;
2007-01-14 23:02:12 +00:00
}
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
{
2009-07-07 11:21:29 +00:00
return
this - > left - distance < = x & &
x < = this - > right + distance & &
this - > top - distance < = y & &
y < = this - > bottom + distance ;
2007-01-14 23:02:12 +00:00
}
bool StationRect : : IsEmpty ( ) const
{
2009-07-07 11:21:29 +00:00
return this - > left = = 0 | | this - > left > this - > right | | this - > top > this - > bottom ;
2007-01-14 23:02:12 +00:00
}
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 ) {
2009-07-07 11:21:29 +00:00
this - > left = this - > right = x ;
this - > top = this - > bottom = y ;
2008-10-15 21:10:43 +00:00
}
2007-02-02 16:51:10 +00:00
} else if ( ! PtInExtendedRect ( x , y ) ) {
2009-03-15 00:32:18 +00:00
/* current rect is not empty and new point is outside this rect
* make new spread - out rectangle */
2009-07-07 11:21:29 +00:00
Rect new_rect = { min ( x , this - > left ) , min ( y , this - > top ) , max ( x , this - > right ) , max ( y , this - > 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 ) ;
2009-04-21 23:40:56 +00:00
_error_message = STR_ERROR_STATION_TOO_SPREAD_OUT ;
2007-01-14 23:02:12 +00:00
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
2009-07-07 11:21:29 +00:00
this - > BeforeAddTile ( tile , mode ) & & this - > 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
*/
2009-03-15 00:32:18 +00:00
/* static */ bool StationRect : : ScanForStationTiles ( StationID st_id , int left_a , int top_a , int right_a , int bottom_a )
2007-01-14 23:02:12 +00:00
{
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
2009-07-26 21:50:30 +00:00
TILE_LOOP ( tile , width , height , top_left ) {
2007-01-14 23:02:12 +00:00
if ( IsTileType ( tile , MP_STATION ) & & GetStationIndex ( tile ) = = st_id ) return true ;
2009-07-26 21:50:30 +00:00
}
2007-01-14 23:36:25 +00:00
2007-01-14 23:02:12 +00:00
return false ;
}
2009-07-26 16:17:49 +00:00
bool StationRect : : AfterRemoveTile ( BaseStation * st , TileIndex tile )
2007-01-14 23:02:12 +00:00
{
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 */
2009-07-07 11:21:29 +00:00
bool left_edge = ( x = = this - > left ) ;
bool right_edge = ( x = = this - > right ) ;
bool top_edge = ( y = = this - > top ) ;
bool bottom_edge = ( y = = this - > bottom ) ;
2007-01-14 23:36:25 +00:00
/* can we reduce the rect in either direction? */
2009-07-07 11:21:29 +00:00
bool reduce_x = ( ( left_edge | | right_edge ) & & ! ScanForStationTiles ( st - > index , x , this - > top , x , this - > bottom ) ) ;
bool reduce_y = ( ( top_edge | | bottom_edge ) & & ! ScanForStationTiles ( st - > index , this - > left , y , this - > 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 */
2009-07-07 11:21:29 +00:00
this - > left = x = x + 1 ;
2007-01-14 23:02:12 +00:00
} else {
2007-01-14 23:36:25 +00:00
/* move right edge left */
2009-07-07 11:21:29 +00:00
this - > right = x = x - 1 ;
2007-01-14 23:02:12 +00:00
}
}
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 */
2009-07-07 11:21:29 +00:00
this - > top = y = y + 1 ;
2007-01-14 23:02:12 +00:00
} else {
2007-01-14 23:36:25 +00:00
/* move bottom edge up */
2009-07-07 11:21:29 +00:00
this - > bottom = y = y - 1 ;
2007-01-14 23:02:12 +00:00
}
}
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 */
2009-07-07 11:21:29 +00:00
this - > MakeEmpty ( ) ;
2007-01-14 23:02:12 +00:00
return true ; // empty remaining rect
}
}
return false ; // non-empty remaining rect
}
2009-07-26 16:17:49 +00:00
bool StationRect : : AfterRemoveRect ( BaseStation * st , TileIndex tile , int w , int h )
2007-01-14 23:02:12 +00:00
{
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
2009-07-07 11:21:29 +00:00
bool empty = this - > 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 )
{
2009-07-07 11:21:29 +00:00
this - > left = src . left ;
this - > top = src . top ;
this - > right = src . right ;
this - > bottom = src . bottom ;
2007-01-14 23:02:12 +00:00
return * this ;
}
2009-07-26 21:07:03 +00:00
TileArea : : TileArea ( TileIndex start , TileIndex end )
{
uint sx = TileX ( start ) ;
uint sy = TileY ( start ) ;
uint ex = TileX ( end ) ;
uint ey = TileY ( end ) ;
if ( sx > ex ) Swap ( sx , ex ) ;
if ( sy > ey ) Swap ( sy , ey ) ;
this - > tile = TileXY ( sx , sy ) ;
this - > w = ex - sx + 1 ;
this - > h = ey - sy + 1 ;
}
2007-01-17 11:15:51 +00:00
2009-05-22 15:13:50 +00:00
void InitializeStations ( )
{
_station_pool . CleanPool ( ) ;
}