ship_gui.c
changeset 164 0cbdf3c9bde1
parent 156 8fef5e5752d6
child 168 79f9ed5b23e6
equal deleted inserted replaced
163:deb9b58db3f4 164:0cbdf3c9bde1
     7 #include "vehicle.h"
     7 #include "vehicle.h"
     8 #include "viewport.h"
     8 #include "viewport.h"
     9 #include "station.h"
     9 #include "station.h"
    10 #include "command.h"
    10 #include "command.h"
    11 #include "player.h"
    11 #include "player.h"
    12 //#include "town.h"
       
    13 #include "engine.h"
    12 #include "engine.h"
    14 
    13 
    15 
    14 
    16 static void DrawShipImage(Vehicle *v, int x, int y, VehicleID selection);
    15 static void DrawShipImage(Vehicle *v, int x, int y, VehicleID selection);
    17 
    16 
   866 			}
   865 			}
   867 		}
   866 		}
   868 	}
   867 	}
   869 }
   868 }
   870 
   869 
       
   870 // used to get a sorted list of the vehicles
       
   871 static SortStruct _ship_sort[NUM_NORMAL_VEHICLES];
       
   872 static uint16 _num_ship_sort[MAX_PLAYERS];
       
   873 
       
   874 static void MakeSortedShiptList(byte owner)
       
   875 {
       
   876 	SortStruct *firstelement;
       
   877 	Vehicle *v;
       
   878 	uint32 n = 0;
       
   879 	uint16 *i;
       
   880 
       
   881 	if (_vehicle_sort_dirty[VEHSHIP]) { // only resort the whole array if vehicles have been added/removed
       
   882 		// reset to 0 just to be sure
       
   883 		for (i = _num_ship_sort; i != endof(_num_ship_sort); i++) {*i = 0;}
       
   884 
       
   885 		FOR_ALL_VEHICLES(v) {
       
   886 			if(v->type == VEH_Ship) {
       
   887 				_ship_sort[n].index = v->index;
       
   888 				_ship_sort[n++].owner = v->owner;
       
   889 				_num_ship_sort[v->owner]++; // add number of trains of player
       
   890 			}
       
   891 		}
       
   892 
       
   893 		// create cumulative ship-ownage
       
   894 		// ships are stored as a cummulative index, eg 25, 41, 43. This means
       
   895 		// Player0: 25; Player1: (41-25) 16; Player2: (43-41) 2
       
   896 		for (i = &_num_ship_sort[1]; i != endof(_num_ship_sort); i++) {*i += *(i-1);}
       
   897 	
       
   898 
       
   899 		// sort by owner, then only subsort the requested owner-vehicles
       
   900 		qsort(_ship_sort, n, sizeof(_ship_sort[0]), GeneralOwnerSorter);
       
   901 
       
   902 		_last_vehicle_idx = 0; // used for "cache" in namesorting
       
   903 		_vehicle_sort_dirty[VEHSHIP] = false;
       
   904 	}
       
   905 
       
   906 	if (owner == 0) { // first element starts at 0th element and has n elements as described above
       
   907 		firstelement =	&_ship_sort[0];
       
   908 		n =							_num_ship_sort[0];
       
   909 	}	else { // nth element starts at the end of the previous one, and has n elements as described above
       
   910 		firstelement =	&_ship_sort[_num_ship_sort[owner-1]];
       
   911 		n =							_num_ship_sort[owner] - _num_ship_sort[owner-1];
       
   912 	}
       
   913 
       
   914 	_internal_sort_type				= _ship_sort_type[owner];
       
   915 	_internal_sort_order			= _ship_sort_order[owner];
       
   916 	_internal_name_sorter_id	= STR_SV_SHIP_NAME;
       
   917 	// only name sorting needs a different procedure, all others are handled by the general sorter
       
   918 	qsort(firstelement, n, sizeof(_ship_sort[0]), (_internal_sort_type == SORT_BY_NAME) ? VehicleNameSorter : GeneralVehicleSorter);
       
   919 
       
   920 	DEBUG(misc, 1) ("Resorting Ships list player %d...", owner+1);
       
   921 }
       
   922 
   871 static void PlayerShipsWndProc(Window *w, WindowEvent *e)
   923 static void PlayerShipsWndProc(Window *w, WindowEvent *e)
   872 {
   924 {
   873 	switch(e->event) {
   925 	switch(e->event) {
   874 	case WE_PAINT:
   926 	case WE_PAINT: {
   875 		/* determine amount of items for scroller */
   927 		uint32 i;
       
   928 		const byte window_number = (byte)w->window_number;
       
   929 
       
   930 		if (_ship_sort_type[window_number] == SORT_BY_UNSORTED) // disable 'Sort By' tooltip on Unsorted sorting criteria
       
   931 			w->disabled_state |= (1 << 3);
       
   932 
       
   933 		if (_ship_sort_dirty[window_number] || _vehicle_sort_dirty[VEHSHIP]) {
       
   934 			_ship_sort_dirty[window_number] = false;
       
   935 			MakeSortedShiptList(window_number);
       
   936 			/* reset sorting timeout */
       
   937 			w->custom[0] = DAY_TICKS;
       
   938 			w->custom[1] = PERIODIC_RESORT_DAYS;
       
   939 		}
       
   940 
       
   941 		// ships are stored as a cummulative index, eg 25, 41, 43. This means
       
   942 		// Player0: 25; Player1: (41-25) 16; Player2: (43-41) 2 ships
       
   943 		i = (window_number == 0) ? 0 : _num_ship_sort[window_number-1];
       
   944 		SetVScrollCount(w, _num_ship_sort[window_number] - i);
       
   945 		
       
   946 		/* draw the widgets */
       
   947 		{
       
   948 			Player *p = DEREF_PLAYER(window_number);
       
   949 			/* Company Name -- (###) Ships */
       
   950 			SET_DPARAM16(0, p->name_1);
       
   951 			SET_DPARAM32(1, p->name_2);
       
   952 			SET_DPARAM16(2, w->vscroll.count);
       
   953 			SET_DPARAM16(3, _vehicle_sort_listing[_ship_sort_type[window_number]]);
       
   954 			DrawWindowWidgets(w);
       
   955 		}
       
   956 		/* draw arrow pointing up/down for ascending/descending soring */
       
   957 		DoDrawString(_ship_sort_order[window_number] & 1 ? "\xAA" : "\xA0", 85, 15, 0x10);
       
   958 
       
   959 		/* draw the ship vehicles */
   876 		{
   960 		{
   877 			Vehicle *v;
   961 			Vehicle *v;
   878 			int num = 0;
   962 			int n = 0;
   879 			byte owner = (byte)w->window_number;
   963 			const int x = 2;			// offset from left side of widget
   880 
   964 			int y = PLY_WND_PRC__OFFSET_TOP_WIDGET;	// offset from top of widget
   881 			FOR_ALL_VEHICLES(v) {
   965 			i += w->vscroll.pos;	// offset from sorted ship list of current player
   882 				if (v->type == VEH_Ship && v->owner == owner)
   966 
   883 					num++;
   967 			while (i < _num_ship_sort[window_number]) {
   884 			}
   968 				StringID str;
   885 			SetVScrollCount(w, num);
   969 				v = DEREF_VEHICLE(_ship_sort[i].index);
   886 		}
   970 
   887 
   971 				DrawShipImage(v, x + 19, y + 6, INVALID_VEHICLE);
   888 		/* draw the widgets */
   972 				DrawVehicleProfitButton(v, x, y+13);
   889 		{
   973 
   890 			Player *p = DEREF_PLAYER(w->window_number);
   974 				SET_DPARAM16(0, v->unitnumber);
   891 			SET_DPARAM16(0, p->name_1);
   975 				if (IsShipDepotTile(v->tile)) {
   892 			SET_DPARAM32(1, p->name_2);
   976 					str = STR_021F;
   893 			DrawWindowWidgets(w);
   977 				} else {
   894 		}
   978 					str = v->age > v->max_age - 366 ? STR_00E3 : STR_00E2;
   895 
   979 				}
   896 		/* draw the ships vehicles */
   980 				DrawString(x, y+2, str, 0);
   897 		{
   981 
   898 			Vehicle *v;
   982 				SET_DPARAM32(0, v->profit_this_year);
   899 			int pos = w->vscroll.pos;
   983 				SET_DPARAM32(1, v->profit_last_year);
   900 			byte owner = (byte)w->window_number;
   984 				DrawString(x + 12, y + 28, STR_0198_PROFIT_THIS_YEAR_LAST_YEAR, 0);
   901 			int x = 2;
   985 				
   902 			int y = 15;
   986 				if (v->string_id != STR_SV_SHIP_NAME) {
       
   987 					SET_DPARAM16(0, v->string_id);
       
   988 					DrawString(x+12, y, STR_01AB, 0);
       
   989 				}
       
   990 
       
   991 				DrawSmallShipSchedule(v, x+138, y);
       
   992 
       
   993 
       
   994 				y += PLY_WND_PRC__SIZE_OF_ROW_BIG;
       
   995 				i++; // next ship
       
   996 				if (++n == w->vscroll.cap) { break;} // max number of ships in the window
       
   997 			}
       
   998 		}
       
   999 		}	break;
       
  1000 
       
  1001 	case WE_CLICK: {
       
  1002 		switch(e->click.widget) {
       
  1003 		case 3: /* Flip sorting method ascending/descending */
       
  1004 			_ship_sort_order[(byte)w->window_number] ^= 1;
       
  1005 			_ship_sort_dirty[(byte)w->window_number] = true;
       
  1006 			SetWindowDirty(w);
       
  1007 			break;
       
  1008 		case 4: case 5:/* Select sorting criteria dropdown menu */
       
  1009 			ShowDropDownMenu(w, _vehicle_sort_listing, _ship_sort_type[(byte)w->window_number], 5, 0); // do it for widget 5
       
  1010 			return;
       
  1011 		case 6: { /* Matrix to show vehicles */
       
  1012 			int id_v = (e->click.pt.y - PLY_WND_PRC__OFFSET_TOP_WIDGET) / PLY_WND_PRC__SIZE_OF_ROW_BIG;
   903 			
  1013 			
   904 			FOR_ALL_VEHICLES(v) {
  1014 			if ((uint)id_v >= w->vscroll.cap) { return;} // click out of bounds
   905 				if (v->type == VEH_Ship && v->owner == owner &&
  1015 
   906 						--pos < 0 && pos >= -4) {
  1016 			id_v += w->vscroll.pos;
   907 					StringID str;
  1017 
   908 					
  1018 			{
   909 					DrawShipImage(v, x + 19, y + 6, INVALID_VEHICLE);
  1019 				byte owner		= (byte)w->window_number;
   910 					DrawVehicleProfitButton(v, x, y+13);
  1020 				uint16 adder	= (owner == 0) ? 0 : _num_ship_sort[owner - 1]; // first element in list
   911 					
  1021 				Vehicle *v;
   912 					SET_DPARAM16(0, v->unitnumber);
  1022 
   913 					if (IsShipDepotTile(v->tile)) {
  1023 				if (id_v + adder >= _num_ship_sort[owner]) { return;} // click out of vehicle bound
   914 						str = STR_021F;
  1024 
   915 					} else {
  1025 				v	= DEREF_VEHICLE(_ship_sort[adder+id_v].index); // add the offset id_x to that
   916 						str = v->age > v->max_age - 366 ? STR_00E3 : STR_00E2;
  1026 
   917 					}
  1027 				assert(v->type == VEH_Ship && v->owner == owner && v->owner == _ship_sort[adder+id_v].owner);
   918 					DrawString(x, y+2, str, 0);
  1028 
   919 
  1029 				ShowShipViewWindow(v);
   920 					SET_DPARAM32(0, v->profit_this_year);
  1030 			}
   921 					SET_DPARAM32(1, v->profit_last_year);
  1031 		} break;
   922 					DrawString(x + 12, y + 28, STR_0198_PROFIT_THIS_YEAR_LAST_YEAR, 0);
  1032 
   923 					
  1033 		case 8: { /* Build new Vehicle */
   924 					if (v->string_id != STR_SV_SHIP_NAME) {
       
   925 						SET_DPARAM16(0, v->string_id);
       
   926 						DrawString(x+12, y, STR_01AB, 0);
       
   927 					}
       
   928 
       
   929 					DrawSmallShipSchedule(v, x+138, y);
       
   930 
       
   931 					y += 36;
       
   932 				}				
       
   933 			}
       
   934 		}
       
   935 		break;
       
   936 	case WE_CLICK:
       
   937 		switch(e->click.widget) {
       
   938 		case 2: { /* click ship */
       
   939 			int sel;
       
   940 			Vehicle *v;
       
   941 			byte owner;
       
   942 	
       
   943 			sel = (e->click.pt.y - 14) / 36;
       
   944 
       
   945 			if ((uint)sel >= 4)
       
   946 				break;
       
   947 			sel += w->vscroll.pos;
       
   948 			owner = (byte)w->window_number;
       
   949 			FOR_ALL_VEHICLES(v) {
       
   950 				if (v->type == VEH_Ship && v->owner == owner &&	--sel < 0) {	
       
   951 					ShowShipViewWindow(v);
       
   952 					break;
       
   953 				}
       
   954 			}
       
   955 			break;
       
   956 		}
       
   957 		case 4: {/* click buy */
       
   958 			uint tile;
  1034 			uint tile;
   959 
  1035 
   960 			tile = _last_built_ship_depot_tile;
  1036 			tile = _last_built_ship_depot_tile;
   961 			do {
  1037 			do {
   962 				if (_map_owner[tile] == _local_player &&
  1038 				if (_map_owner[tile] == _local_player && IsShipDepotTile(tile)) {					
   963 						IsShipDepotTile(tile)) {
       
   964 					
       
   965 					ShowShipDepotWindow(tile);
  1039 					ShowShipDepotWindow(tile);
   966 					ShowBuildShipWindow(tile);
  1040 					ShowBuildShipWindow(tile);
   967 					return;
  1041 					return;
   968 				}
  1042 				}
   969 				
  1043 				
   971 			} while(tile != _last_built_ship_depot_tile);
  1045 			} while(tile != _last_built_ship_depot_tile);
   972 			
  1046 			
   973 			ShowBuildShipWindow(0);
  1047 			ShowBuildShipWindow(0);
   974 		} break;
  1048 		} break;
   975 		}
  1049 		}
   976 		break;
  1050 	}	break;
   977 	}
  1051 
   978 }
  1052 	case WE_DROPDOWN_SELECT: /* we have selected a dropdown item in the list */
   979 
  1053 		if (_ship_sort_type[(byte)w->window_number] != e->dropdown.index) // if value hasn't changed, dont resort list
       
  1054 			_ship_sort_dirty[(byte)w->window_number] = true;
       
  1055 
       
  1056 		_ship_sort_type[(byte)w->window_number] = e->dropdown.index;
       
  1057 
       
  1058 		if (_ship_sort_type[(byte)w->window_number] != SORT_BY_UNSORTED) // enable 'Sort By' if a sorter criteria is chosen
       
  1059 			w->disabled_state &= ~(1 << 3);
       
  1060 
       
  1061 		SetWindowDirty(w);
       
  1062 		break;
       
  1063 	case WE_CREATE: /* set up resort timer */
       
  1064 		w->custom[0] = DAY_TICKS;
       
  1065 		w->custom[1] = PERIODIC_RESORT_DAYS;
       
  1066 		break;
       
  1067 	case WE_TICK: /* resort the list every 20 seconds orso (10 days) */
       
  1068 		if (--w->custom[0] == 0) {
       
  1069 			w->custom[0] = DAY_TICKS;
       
  1070 			if (--w->custom[1] == 0) {
       
  1071 				w->custom[1] = PERIODIC_RESORT_DAYS;
       
  1072 				_ship_sort_dirty[(byte)w->window_number] = true;
       
  1073 				DEBUG(misc, 1) ("Periodic resort Ships list player %d...", w->window_number+1);
       
  1074 				SetWindowDirty(w);
       
  1075 			}
       
  1076 		}
       
  1077 		break;
       
  1078 	}
       
  1079 }
   980 static const Widget _player_ships_widgets[] = {
  1080 static const Widget _player_ships_widgets[] = {
   981 {    WWT_TEXTBTN,    14,     0,    10,     0,    13, STR_00C5, STR_018B_CLOSE_WINDOW},
  1081 {   WWT_CLOSEBOX,    14,     0,    10,     0,    13, STR_00C5,							STR_018B_CLOSE_WINDOW},
   982 {    WWT_CAPTION,    14,    11,   259,     0,    13, STR_9805_SHIPS, STR_018C_WINDOW_TITLE_DRAG_THIS},
  1082 {    WWT_CAPTION,    14,    11,   259,     0,    13, STR_9805_SHIPS,				STR_018C_WINDOW_TITLE_DRAG_THIS},
   983 {     WWT_MATRIX,    14,     0,   248,    14,   157, 0x401, STR_9823_SHIPS_CLICK_ON_SHIP_FOR},
  1083 {      WWT_PANEL,    14,     0,    15,    14,    25, 0x0,										0},
   984 {  WWT_SCROLLBAR,    14,   249,   259,    14,   157, 0x0, STR_0190_SCROLL_BAR_SCROLLS_LIST},
  1084 { WWT_PUSHTXTBTN,    14,    16,    96,    14,    25, SRT_SORT_BY,						STR_SORT_TIP},
   985 { WWT_PUSHTXTBTN,    14,     0,   129,   158,   169, STR_9804_NEW_SHIPS, STR_9824_BUILD_NEW_SHIPS_REQUIRES},
  1085 {    WWT_TEXTBTN,    14,    97,   248,    14,    25, STR_02E7,							0},
   986 {     WWT_IMGBTN,    14,   130,   259,   158,   169, 0x0},
  1086 {   WWT_CLOSEBOX,    14,   249,   259,    14,    25, STR_0225,							STR_SORT_TIP},
       
  1087 {     WWT_MATRIX,    14,     0,   248,    26,   169, 0x401,									STR_9823_SHIPS_CLICK_ON_SHIP_FOR},
       
  1088 {  WWT_SCROLLBAR,    14,   249,   259,    26,   169, 0x0,										STR_0190_SCROLL_BAR_SCROLLS_LIST},
       
  1089 { WWT_PUSHTXTBTN,    14,     0,   129,   170,   181, STR_9804_NEW_SHIPS,		STR_9824_BUILD_NEW_SHIPS_REQUIRES},
       
  1090 {      WWT_PANEL,    14,   130,   259,   170,   181, 0x0,										0},
   987 {      WWT_LAST},
  1091 {      WWT_LAST},
   988 };
  1092 };
       
  1093 
   989 static const WindowDesc _player_ships_desc = {
  1094 static const WindowDesc _player_ships_desc = {
       
  1095 	-1, -1, 260, 182,
       
  1096 	WC_SHIPS_LIST,0,
       
  1097 	WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS | WDF_RESTORE_DPARAM,
       
  1098 	_player_ships_widgets,
       
  1099 	PlayerShipsWndProc
       
  1100 };
       
  1101 
       
  1102 static const Widget _other_player_ships_widgets[] = {
       
  1103 {   WWT_CLOSEBOX,    14,     0,    10,     0,    13, STR_00C5,							STR_018B_CLOSE_WINDOW},
       
  1104 {    WWT_CAPTION,    14,    11,   259,     0,    13, STR_9805_SHIPS,				STR_018C_WINDOW_TITLE_DRAG_THIS},
       
  1105 {      WWT_PANEL,    14,     0,    15,    14,    25, 0x0,										0},
       
  1106 { WWT_PUSHTXTBTN,    14,    16,    96,    14,    25, SRT_SORT_BY,						STR_SORT_TIP},
       
  1107 {    WWT_TEXTBTN,    14,    97,   248,    14,    25, STR_02E7,							0},
       
  1108 {   WWT_CLOSEBOX,    14,   249,   259,    14,    25, STR_0225,							STR_SORT_TIP},
       
  1109 {     WWT_MATRIX,    14,     0,   248,    26,   169, 0x401,									STR_9823_SHIPS_CLICK_ON_SHIP_FOR},
       
  1110 {  WWT_SCROLLBAR,    14,   249,   259,    26,   169, 0x0,										STR_0190_SCROLL_BAR_SCROLLS_LIST},
       
  1111 {      WWT_LAST},
       
  1112 };
       
  1113 
       
  1114 static const WindowDesc _other_player_ships_desc = {
   990 	-1, -1, 260, 170,
  1115 	-1, -1, 260, 170,
   991 	WC_SHIPS_LIST,0,
  1116 	WC_SHIPS_LIST,0,
   992 	WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS,
  1117 	WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS | WDF_RESTORE_DPARAM,
   993 	_player_ships_widgets,
       
   994 	PlayerShipsWndProc
       
   995 };
       
   996 
       
   997 static const Widget _other_player_ships_widgets[] = {
       
   998 {    WWT_TEXTBTN,    14,     0,    10,     0,    13, STR_00C5, STR_018B_CLOSE_WINDOW},
       
   999 {    WWT_CAPTION,    14,    11,   259,     0,    13, STR_9805_SHIPS, STR_018C_WINDOW_TITLE_DRAG_THIS},
       
  1000 {     WWT_MATRIX,    14,     0,   248,    14,   157, 0x401, STR_9823_SHIPS_CLICK_ON_SHIP_FOR},
       
  1001 {  WWT_SCROLLBAR,    14,   249,   259,    14,   157, 0x0, STR_0190_SCROLL_BAR_SCROLLS_LIST},
       
  1002 {      WWT_LAST},
       
  1003 };
       
  1004 static const WindowDesc _other_player_ships_desc = {
       
  1005 	-1, -1, 260, 158,
       
  1006 	WC_SHIPS_LIST,0,
       
  1007 	WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS,
       
  1008 	_other_player_ships_widgets,
  1118 	_other_player_ships_widgets,
  1009 	PlayerShipsWndProc
  1119 	PlayerShipsWndProc
  1010 };
  1120 };
  1011 
  1121 
  1012 
  1122