@ -10,6 +10,7 @@
# include "command.h"
# include "player.h"
# include "engine.h"
# include "vehicle_gui.h"
int _traininfo_vehicle_pitch = 0 ;
@ -39,7 +40,7 @@ void CcBuildWagon(bool success, uint tile, uint32 p1, uint32 p2)
found = GetLastVehicleInChain ( found ) ;
// put the new wagon at the end of the loco.
DoCommandP ( 0 , _new_wagon_id | ( found - > index < < 16 ) , 0 , NULL , CMD_MOVE_RAIL_VEHICLE ) ;
_vehicle_sort_dirty [ VEHTRAIN ] = true ;
RebuildVehicleLists ( ) ;
}
}
@ -1166,155 +1167,125 @@ void ShowTrainDetailsWindow(Vehicle *v)
WP ( w , traindetails_d ) . tab = 0 ;
}
// used to get a sorted list of the vehicles
static SortStruct _train_sort [ NUM_NORMAL_VEHICLES ] ;
static uint16 _num_train_sort [ MAX_PLAYERS ] ;
static void GlobalSortTrainList ( )
{
const Vehicle * v ;
uint16 * i ;
uint32 n = 0 ;
// reset #-of trains to 0 because ++ is used for value-assignment
for ( i = _num_train_sort ; i ! = endof ( _num_train_sort ) ; i + + ) { * i = 0 ; }
FOR_ALL_VEHICLES ( v ) {
if ( v - > type = = VEH_Train & & v - > subtype = = 0 ) {
_train_sort [ n ] . index = v - > index ;
_train_sort [ n + + ] . owner = v - > owner ;
_num_train_sort [ v - > owner ] + + ; // add number of trains of player
}
}
// create cumulative train-ownership
// trains are stored as a cummulative index, eg 25, 41, 43. This means
// Player0: 25; Player1: (41-25) 16; Player2: (43-41) 2
for ( i = & _num_train_sort [ 1 ] ; i ! = endof ( _num_train_sort ) ; i + + ) { * i + = * ( i - 1 ) ; }
qsort ( _train_sort , n , sizeof ( _train_sort [ 0 ] ) , GeneralOwnerSorter ) ; // sort by owner
// since indexes are messed up after adding/removing a station, mark all lists dirty
memset ( _train_sort_dirty , true , sizeof ( _train_sort_dirty ) ) ;
_vehicle_sort_dirty [ VEHTRAIN ] = false ;
DEBUG ( misc , 1 ) ( " Resorting global trains list... " ) ;
}
static void MakeSortedTrainList ( byte owner )
{
SortStruct * firstelement ;
uint32 n = 0 ;
if ( owner = = 0 ) { // first element starts at 0th element and has n elements as described above
firstelement = & _train_sort [ 0 ] ;
n = _num_train_sort [ 0 ] ;
} else { // nth element starts at the end of the previous one, and has n elements as described above
firstelement = & _train_sort [ _num_train_sort [ owner - 1 ] ] ;
n = _num_train_sort [ owner ] - _num_train_sort [ owner - 1 ] ;
}
_internal_sort_order = _train_sort_order [ owner ] ;
_internal_name_sorter_id = STR_SV_TRAIN_NAME ;
_last_vehicle_idx = 0 ; // used for "cache" in namesorting
qsort ( firstelement , n , sizeof ( _train_sort [ 0 ] ) , _vehicle_sorter [ _train_sort_type [ owner ] ] ) ;
_train_sort_dirty [ owner ] = false ;
static Widget _player_trains_widgets [ ] = {
{ WWT_CLOSEBOX , 14 , 0 , 10 , 0 , 13 , STR_00C5 , STR_018B_CLOSE_WINDOW } ,
{ WWT_CAPTION , 14 , 11 , 324 , 0 , 13 , STR_881B_TRAINS , STR_018C_WINDOW_TITLE_DRAG_THIS } ,
{ WWT_PUSHTXTBTN , 14 , 0 , 80 , 14 , 25 , SRT_SORT_BY , STR_SORT_TIP } ,
{ WWT_PANEL , 14 , 81 , 232 , 14 , 25 , 0x0 , STR_SORT_TIP } ,
{ WWT_CLOSEBOX , 14 , 233 , 243 , 14 , 25 , STR_0225 , STR_SORT_TIP } ,
{ WWT_PANEL , 14 , 244 , 324 , 14 , 25 , 0x0 , STR_NULL } ,
{ WWT_MATRIX , 14 , 0 , 313 , 26 , 207 , 0x701 , STR_883D_TRAINS_CLICK_ON_TRAIN_FOR } ,
{ WWT_SCROLLBAR , 14 , 314 , 324 , 26 , 207 , 0x0 , STR_0190_SCROLL_BAR_SCROLLS_LIST } ,
{ WWT_PUSHTXTBTN , 14 , 0 , 161 , 208 , 219 , STR_8815_NEW_VEHICLES , STR_883E_BUILD_NEW_TRAINS_REQUIRES } ,
{ WWT_PANEL , 14 , 162 , 324 , 208 , 219 , 0x0 , STR_NULL } ,
{ WIDGETS_END } ,
} ;
DEBUG ( misc , 1 ) ( " Resorting Trains list player %d... " , owner + 1 ) ;
}
static Widget _other_player_trains_widgets [ ] = {
{ WWT_CLOSEBOX , 14 , 0 , 10 , 0 , 13 , STR_00C5 , STR_018B_CLOSE_WINDOW } ,
{ WWT_CAPTION , 14 , 11 , 324 , 0 , 13 , STR_881B_TRAINS , STR_018C_WINDOW_TITLE_DRAG_THIS } ,
{ WWT_PUSHTXTBTN , 14 , 0 , 80 , 14 , 25 , SRT_SORT_BY , STR_SORT_TIP } ,
{ WWT_PANEL , 14 , 81 , 232 , 14 , 25 , 0x0 , STR_SORT_TIP } ,
{ WWT_CLOSEBOX , 14 , 233 , 243 , 14 , 25 , STR_0225 , STR_SORT_TIP } ,
{ WWT_PANEL , 14 , 244 , 324 , 14 , 25 , 0x0 , STR_NULL } ,
{ WWT_MATRIX , 14 , 0 , 313 , 26 , 207 , 0x701 , STR_883D_TRAINS_CLICK_ON_TRAIN_FOR } ,
{ WWT_SCROLLBAR , 14 , 314 , 324 , 26 , 207 , 0x0 , STR_0190_SCROLL_BAR_SCROLLS_LIST } ,
{ WIDGETS_END } ,
} ;
static void PlayerTrainsWndProc ( Window * w , WindowEvent * e )
{
int station = ( int ) w - > window_number > > 16 ;
int owner = w - > window_number & 0xff ;
vehiclelist_d * vl = & WP ( w , vehiclelist_d ) ;
switch ( e - > event ) {
case WE_PAINT : {
uint32 i ;
const byte window_number = ( byte ) w - > window_number ;
if ( _train_sort_type [ window_number ] = = SORT_BY_UNSORTED ) // disable 'Sort By' tooltip on Unsorted sorting criteria
w - > disabled_state | = ( 1 < < 2 ) ;
int x = 2 ;
int y = PLY_WND_PRC__OFFSET_TOP_WIDGET ;
int max ;
int i ;
// resort trains window if roadvehicles have been added/removed
if ( _vehicle_sort_dirty [ VEHTRAIN ] )
GlobalSortTrainList ( ) ;
BuildVehicleList ( vl , VEH_Train , owner , station ) ;
SortVehicleList ( vl ) ;
if ( _train_sort_dirty [ window_number ] ) {
MakeSortedTrainList ( window_number ) ;
/* reset sorting timeout */
w - > custom [ 0 ] = DAY_TICKS ;
w - > custom [ 1 ] = PERIODIC_RESORT_DAYS ;
}
SetVScrollCount ( w , vl - > list_length ) ;
// Trains are stored as a cummulative index, eg 25, 41, 43. This means
// Player0: 25; Player1: (41-25) 16; Player2: (43-41) 2 trains
i = ( window_number = = 0 ) ? 0 : _num_train_sort [ window_number - 1 ] ;
SetVScrollCount ( w , _num_train_sort [ window_number ] - i ) ;
// disable 'Sort By' tooltip on Unsorted sorting criteria
if ( vl - > sort_type = = SORT_BY_UNSORTED )
w - > disabled_state | = ( 1 < < 2 ) ;
/* draw the widgets */
{
Player * p = DEREF_PLAYER ( window_number ) ;
/* Company Name -- (###) Trains */
SetDParam ( 0 , p - > name_1 ) ;
SetDParam ( 1 , p - > name_2 ) ;
SetDParam ( 2 , w - > vscroll . count ) ;
const Player * p = DEREF_PLAYER ( owner ) ;
/* XXX hack */
if ( station = = - 1 ) {
/* Company Name -- (###) Trains */
SetDParam ( 0 , p - > name_1 ) ;
SetDParam ( 1 , p - > name_2 ) ;
SetDParam ( 2 , w - > vscroll . count ) ;
_player_trains_widgets [ 1 ] . unkA = STR_881B_TRAINS ;
_other_player_trains_widgets [ 1 ] . unkA = STR_881B_TRAINS ;
} else {
/* Station Name -- (###) Trains */
SetDParam ( 0 , DEREF_STATION ( station ) - > index ) ;
SetDParam ( 1 , w - > vscroll . count ) ;
_player_trains_widgets [ 1 ] . unkA = STR_SCHEDULED_TRAINS ;
_other_player_trains_widgets [ 1 ] . unkA = STR_SCHEDULED_TRAINS ;
}
DrawWindowWidgets ( w ) ;
}
/* draw sorting criteria string */
DrawString ( 85 , 15 , _vehicle_sort_listing [ _train_sort_type [ window_number ] ] , 0x10 ) ;
/* draw arrow pointing up/down for ascending/descending soring */
DoDrawString ( _train_sort_order [ window_number ] & 1 ? " \xAA " : " \xA0 " , 69 , 15 , 0x10 ) ;
DrawString ( 85 , 15 , _vehicle_sort_listing [ vl - > sort_type ] , 0x10 ) ;
/* draw arrow pointing up/down for ascending/descending sorting */
DoDrawString (
vl - > flags & VL_DESC ? " \xAA " : " \xA0 " , 69 , 15 , 0x10 ) ;
/* draw the trains */
{
Vehicle * v ;
int n = 0 ;
const int x = 2 ; // offset from left side of widget
int y = PLY_WND_PRC__OFFSET_TOP_WIDGET ; // offset from top of widget
i + = w - > vscroll . pos ; // offset from sorted trains list of current player
max = min ( w - > vscroll . pos + w - > vscroll . cap , vl - > list_length ) ;
for ( i = w - > vscroll . pos ; i < max ; + + i ) {
Vehicle * v = DEREF_VEHICLE ( vl - > sort_list [ i ] . index ) ;
StringID str ;
while ( i < _num_train_sort [ window_number ] ) {
StringID str ;
v = DEREF_VEHICLE ( _train_sort [ i ] . index ) ;
assert ( v - > type = = VEH_Train & & v - > owner = = owner ) ;
assert ( v - > type = = VEH_Train & & v - > subtype = = 0 & & v - > owner = = window_number ) ;
DrawTrainImage (
v , x + 21 , y + 6 + _traininfo_vehicle_pitch , 10 , 0 , INVALID_VEHICLE ) ;
DrawVehicleProfitButton ( v , x , y + 13 ) ;
DrawTrainImage ( v , x + 21 , y + 6 + _traininfo_vehicle_pitch , 10 , 0 , INVALID_VEHICLE ) ;
DrawVehicleProfitButton ( v , x , y + 13 ) ;
SetDParam ( 0 , v - > unitnumber ) ;
if ( IsTrainDepotTile ( v - > tile ) ) {
str = STR_021F ;
} else {
str = v - > age > v - > max_age - 366 ? STR_00E3 : STR_00E2 ;
}
DrawString ( x , y + 2 , str , 0 ) ;
SetDParam ( 0 , v - > profit_this_year ) ;
SetDParam ( 1 , v - > profit_last_year ) ;
DrawString ( x + 21 , y + 18 , STR_0198_PROFIT_THIS_YEAR_LAST_YEAR , 0 ) ;
if ( v - > string_id ! = STR_SV_TRAIN_NAME ) {
SetDParam ( 0 , v - > string_id ) ;
DrawString ( x + 21 , y , STR_01AB , 0 ) ;
}
y + = PLY_WND_PRC__SIZE_OF_ROW_SMALL ;
i + + ; // next train
if ( + + n = = w - > vscroll . cap ) { break ; } // max number of trains in the window
SetDParam ( 0 , v - > unitnumber ) ;
if ( IsTrainDepotTile ( v - > tile ) )
str = STR_021F ;
else
str = v - > age > v - > max_age - 366 ? STR_00E3 : STR_00E2 ;
DrawString ( x , y + 2 , str , 0 ) ;
SetDParam ( 0 , v - > profit_this_year ) ;
SetDParam ( 1 , v - > profit_last_year ) ;
DrawString ( x + 21 , y + 18 , STR_0198_PROFIT_THIS_YEAR_LAST_YEAR , 0 ) ;
if ( v - > string_id ! = STR_SV_TRAIN_NAME ) {
SetDParam ( 0 , v - > string_id ) ;
DrawString ( x + 21 , y , STR_01AB , 0 ) ;
}
y + = PLY_WND_PRC__SIZE_OF_ROW_SMALL ;
}
} break ;
break ;
}
case WE_CLICK : {
switch ( e - > click . widget ) {
case 2 : /* Flip sorting method ascending/descending */
_train_sort_order[ ( byte ) w - > window_number ] ^ = 1 ;
_train_sort_dirty[ ( byte ) w - > window_number ] = true ;
vl- > flags ^ = VL_DESC ;
vl- > flags | = VL_RESORT ;
SetWindowDirty ( w ) ;
break ;
case 3 : case 4 : /* Select sorting criteria dropdown menu */
ShowDropDownMenu ( w , _vehicle_sort_listing , _train_sort_type[ ( byte ) w - > window_number ] , 4 , 0 ) ; // do it for widget 4
ShowDropDownMenu ( w , _vehicle_sort_listing , vl- > sort_type , 4 , 0 ) ;
return ;
case 6 : { /* Matrix to show vehicles */
uint32 id_v = ( e - > click . pt . y - PLY_WND_PRC__OFFSET_TOP_WIDGET ) / PLY_WND_PRC__SIZE_OF_ROW_SMALL ;
@ -1323,13 +1294,11 @@ static void PlayerTrainsWndProc(Window *w, WindowEvent *e)
id_v + = w - > vscroll . pos ;
{
const byte owner = ( byte ) w - > window_number ;
Vehicle * v ;
id_v + = ( owner = = 0 ) ? 0 : _num_train_sort [ owner - 1 ] ; // first element in list
if ( id_v > = _num_train_sort[ owner ] ) { return ; } // click out of vehicle bound
if ( id_v > = vl- > list_length ) return ; // click out of list bound
v = DEREF_VEHICLE ( _train_sor t[ id_v ] . index ) ; // add the offset id_x to that
v = DEREF_VEHICLE ( vl- > sort_lis t[ id_v ] . index ) ;
assert ( v - > type = = VEH_Train & & v - > subtype = = 0 & & v - > owner = = owner ) ;
@ -1357,48 +1326,37 @@ static void PlayerTrainsWndProc(Window *w, WindowEvent *e)
} break ;
case WE_DROPDOWN_SELECT : /* we have selected a dropdown item in the list */
if ( _train_sort_type [ ( byte ) w - > window_number ] ! = e - > dropdown . index ) // if value hasn't changed, dont resort list
_train_sort_dirty [ ( byte ) w - > window_number ] = true ;
_train_sort_type [ ( byte ) w - > window_number ] = e - > dropdown . index ;
if ( _train_sort_type [ ( byte ) w - > window_number ] ! = SORT_BY_UNSORTED ) // enable 'Sort By' if a sorter criteria is chosen
w - > disabled_state & = ~ ( 1 < < 2 ) ;
if ( vl - > sort_type ! = e - > dropdown . index ) {
// value has changed -> resort
vl - > flags | = VL_RESORT ;
vl - > sort_type = e - > dropdown . index ;
// enable 'Sort By' if a sorter criteria is chosen
if ( vl - > sort_type ! = SORT_BY_UNSORTED )
w - > disabled_state & = ~ ( 1 < < 2 ) ;
}
SetWindowDirty ( w ) ;
break ;
case WE_CREATE : /* set up resort timer */
w - > custom [ 0 ] = DAY_TICKS ;
w - > custom [ 1 ] = PERIODIC_RESORT_DAYS ;
vl - > sort_list = NULL ;
vl - > flags = VL_REBUILD ;
vl - > sort_type = SORT_BY_UNSORTED ;
vl - > resort_timer = DAY_TICKS * PERIODIC_RESORT_DAYS ;
break ;
case WE_TICK : /* resort the list every 20 seconds orso (10 days) */
if ( - - w - > custom [ 0 ] = = 0 ) {
w - > custom [ 0 ] = DAY_TICKS ;
if ( - - w - > custom [ 1 ] = = 0 ) {
w - > custom [ 1 ] = PERIODIC_RESORT_DAYS ;
_train_sort_dirty [ ( byte ) w - > window_number ] = true ;
DEBUG ( misc , 1 ) ( " Periodic resort Trains list player %d... " , w - > window_number + 1 ) ;
SetWindowDirty ( w ) ;
}
if ( - - vl - > resort_timer = = 0 ) {
DEBUG ( misc , 1 ) ( " Periodic resort trains list player %d station %d " ,
owner , station ) ;
vl - > resort_timer = DAY_TICKS * PERIODIC_RESORT_DAYS ;
vl - > flags | = VL_RESORT ;
SetWindowDirty ( w ) ;
}
break ;
}
}
static const Widget _player_trains_widgets [ ] = {
{ WWT_CLOSEBOX , 14 , 0 , 10 , 0 , 13 , STR_00C5 , STR_018B_CLOSE_WINDOW } ,
{ WWT_CAPTION , 14 , 11 , 324 , 0 , 13 , STR_881B_TRAINS , STR_018C_WINDOW_TITLE_DRAG_THIS } ,
{ WWT_PUSHTXTBTN , 14 , 0 , 80 , 14 , 25 , SRT_SORT_BY , STR_SORT_TIP } ,
{ WWT_PANEL , 14 , 81 , 232 , 14 , 25 , 0x0 , STR_SORT_TIP } ,
{ WWT_CLOSEBOX , 14 , 233 , 243 , 14 , 25 , STR_0225 , STR_SORT_TIP } ,
{ WWT_PANEL , 14 , 244 , 324 , 14 , 25 , 0x0 , STR_NULL } ,
{ WWT_MATRIX , 14 , 0 , 313 , 26 , 207 , 0x701 , STR_883D_TRAINS_CLICK_ON_TRAIN_FOR } ,
{ WWT_SCROLLBAR , 14 , 314 , 324 , 26 , 207 , 0x0 , STR_0190_SCROLL_BAR_SCROLLS_LIST } ,
{ WWT_PUSHTXTBTN , 14 , 0 , 161 , 208 , 219 , STR_8815_NEW_VEHICLES , STR_883E_BUILD_NEW_TRAINS_REQUIRES } ,
{ WWT_PANEL , 14 , 162 , 324 , 208 , 219 , 0x0 , STR_NULL } ,
{ WIDGETS_END } ,
} ;
static const WindowDesc _player_trains_desc = {
- 1 , - 1 , 325 , 220 ,
WC_TRAINS_LIST , 0 ,
@ -1407,18 +1365,6 @@ static const WindowDesc _player_trains_desc = {
PlayerTrainsWndProc
} ;
static const Widget _other_player_trains_widgets [ ] = {
{ WWT_CLOSEBOX , 14 , 0 , 10 , 0 , 13 , STR_00C5 , STR_018B_CLOSE_WINDOW } ,
{ WWT_CAPTION , 14 , 11 , 324 , 0 , 13 , STR_881B_TRAINS , STR_018C_WINDOW_TITLE_DRAG_THIS } ,
{ WWT_PUSHTXTBTN , 14 , 0 , 80 , 14 , 25 , SRT_SORT_BY , STR_SORT_TIP } ,
{ WWT_PANEL , 14 , 81 , 232 , 14 , 25 , 0x0 , STR_SORT_TIP } ,
{ WWT_CLOSEBOX , 14 , 233 , 243 , 14 , 25 , STR_0225 , STR_SORT_TIP } ,
{ WWT_PANEL , 14 , 244 , 324 , 14 , 25 , 0x0 , STR_NULL } ,
{ WWT_MATRIX , 14 , 0 , 313 , 26 , 207 , 0x701 , STR_883D_TRAINS_CLICK_ON_TRAIN_FOR } ,
{ WWT_SCROLLBAR , 14 , 314 , 324 , 26 , 207 , 0x0 , STR_0190_SCROLL_BAR_SCROLLS_LIST } ,
{ WIDGETS_END } ,
} ;
static const WindowDesc _other_player_trains_desc = {
- 1 , - 1 , 325 , 208 ,
WC_TRAINS_LIST , 0 ,
@ -1427,14 +1373,14 @@ static const WindowDesc _other_player_trains_desc = {
PlayerTrainsWndProc
} ;
void ShowPlayerTrains ( int player )
void ShowPlayerTrains ( int player , int station )
{
Window * w ;
if ( player = = _local_player ) {
w = AllocateWindowDescFront ( & _player_trains_desc , player ) ;
w = AllocateWindowDescFront ( & _player_trains_desc , ( station < < 16 ) | player ) ;
} else {
w = AllocateWindowDescFront ( & _other_player_trains_desc , player ) ;
w = AllocateWindowDescFront ( & _other_player_trains_desc , ( station < < 16 ) | player ) ;
}
if ( w ) {
w - > caption_color = w - > window_number ;