src/vehicle_gui.cpp
branchnoai
changeset 10776 07203fc29812
parent 10715 6bdf79ffb022
child 11044 097ea3e7ec56
equal deleted inserted replaced
10774:2c882f0468f2 10776:07203fc29812
    34 #include "string_func.h"
    34 #include "string_func.h"
    35 #include "settings_type.h"
    35 #include "settings_type.h"
    36 #include "widgets/dropdown_func.h"
    36 #include "widgets/dropdown_func.h"
    37 #include "order_func.h"
    37 #include "order_func.h"
    38 #include "timetable.h"
    38 #include "timetable.h"
       
    39 #include "vehiclelist.h"
    39 
    40 
    40 #include "table/sprites.h"
    41 #include "table/sprites.h"
    41 #include "table/strings.h"
    42 #include "table/strings.h"
    42 
    43 
    43 Sorting _sorting;
    44 Sorting _sorting;
    90 {
    91 {
    91 	if (!(vl->vehicles.flags & VL_REBUILD)) return;
    92 	if (!(vl->vehicles.flags & VL_REBUILD)) return;
    92 
    93 
    93 	DEBUG(misc, 3, "Building vehicle list for player %d at station %d", owner, index);
    94 	DEBUG(misc, 3, "Building vehicle list for player %d at station %d", owner, index);
    94 
    95 
    95 	vl->vehicles.list_length = GenerateVehicleSortList(&vl->vehicles.sort_list, &vl->vehicles.list_length, vl->vehicle_type, owner, index, window_type);
    96 	GenerateVehicleSortList(&vl->vehicles, vl->vehicle_type, owner, index, window_type);
    96 
    97 
    97 	vl->vehicles.flags &= ~VL_REBUILD;
    98 	vl->vehicles.flags &= ~VL_REBUILD;
    98 	vl->vehicles.flags |= VL_RESORT;
    99 	vl->vehicles.flags |= VL_RESORT;
    99 }
   100 }
   100 
   101 
   108 
   109 
   109 	/* invalidate cached values for name sorter - vehicle names could change */
   110 	/* invalidate cached values for name sorter - vehicle names could change */
   110 	_last_vehicle[0] = _last_vehicle[1] = NULL;
   111 	_last_vehicle[0] = _last_vehicle[1] = NULL;
   111 
   112 
   112 	_internal_sort_order = (vl->vehicles.flags & VL_DESC) != 0;
   113 	_internal_sort_order = (vl->vehicles.flags & VL_DESC) != 0;
   113 	qsort((void*)vl->vehicles.sort_list, vl->vehicles.list_length, sizeof(vl->vehicles.sort_list[0]),
   114 	qsort((void*)vl->vehicles.Begin(), vl->vehicles.Length(), sizeof(*vl->vehicles.Begin()),
   114 		_vehicle_sorter[vl->vehicles.sort_type]);
   115 		_vehicle_sorter[vl->vehicles.sort_type]);
   115 
   116 
   116 	vl->vehicles.resort_timer = DAY_TICKS * PERIODIC_RESORT_DAYS;
   117 	vl->vehicles.resort_timer = DAY_TICKS * PERIODIC_RESORT_DAYS;
   117 	vl->vehicles.flags &= ~VL_RESORT;
   118 	vl->vehicles.flags &= ~VL_RESORT;
   118 }
   119 }
   119 
   120 
   120 void DepotSortList(VehicleList *list)
   121 void DepotSortList(VehicleList *list)
   121 {
   122 {
   122 	_internal_sort_order = 0;
   123 	_internal_sort_order = 0;
   123 	if (list->Length() < 2) return;
   124 	if (list->Length() < 2) return;
   124 	qsort((void*)list->Begin(), list->Length(), sizeof(list->Begin()), _vehicle_sorter[0]);
   125 	qsort((void*)list->Begin(), list->Length(), sizeof(*list->Begin()), _vehicle_sorter[0]);
   125 }
   126 }
   126 
   127 
   127 /** draw the vehicle profit button in the vehicle list window. */
   128 /** draw the vehicle profit button in the vehicle list window. */
   128 void DrawVehicleProfitButton(const Vehicle *v, int x, int y)
   129 void DrawVehicleProfitButton(const Vehicle *v, int x, int y)
   129 {
   130 {
   804 	{
   805 	{
   805 		uint16 window_type = this->window_number & VLW_MASK;
   806 		uint16 window_type = this->window_number & VLW_MASK;
   806 		PlayerID player = (PlayerID)GB(this->window_number, 0, 8);
   807 		PlayerID player = (PlayerID)GB(this->window_number, 0, 8);
   807 
   808 
   808 		this->vehicle_type = (VehicleType)GB(this->window_number, 11, 5);
   809 		this->vehicle_type = (VehicleType)GB(this->window_number, 11, 5);
   809 		this->vehicles.list_length = 0;
       
   810 		this->vehicles.sort_list = NULL;
       
   811 		this->caption_color = player;
   810 		this->caption_color = player;
   812 
   811 
   813 		/* Hide the widgets that we will not use in this window
   812 		/* Hide the widgets that we will not use in this window
   814 		* Some windows contains actions only fit for the owner */
   813 		* Some windows contains actions only fit for the owner */
   815 		if (player == _local_player) {
   814 		if (player == _local_player) {
   923 		this->FindWindowPlacementAndResize(desc);
   922 		this->FindWindowPlacementAndResize(desc);
   924 	}
   923 	}
   925 
   924 
   926 	~VehicleListWindow()
   925 	~VehicleListWindow()
   927 	{
   926 	{
   928 		free((void*)this->vehicles.sort_list);
       
   929 	}
   927 	}
   930 
   928 
   931 	virtual void OnPaint()
   929 	virtual void OnPaint()
   932 	{
   930 	{
   933 		int x = 2;
   931 		int x = 2;
   938 		const uint16 window_type = this->window_number & VLW_MASK;
   936 		const uint16 window_type = this->window_number & VLW_MASK;
   939 		const uint16 index = GB(this->window_number, 16, 16);
   937 		const uint16 index = GB(this->window_number, 16, 16);
   940 
   938 
   941 		BuildVehicleList(this, owner, index, window_type);
   939 		BuildVehicleList(this, owner, index, window_type);
   942 		SortVehicleList(this);
   940 		SortVehicleList(this);
   943 		SetVScrollCount(this, this->vehicles.list_length);
   941 		SetVScrollCount(this, this->vehicles.Length());
   944 
   942 
   945 		/* draw the widgets */
   943 		/* draw the widgets */
   946 		switch (window_type) {
   944 		switch (window_type) {
   947 			case VLW_SHARED_ORDERS: /* Shared Orders */
   945 			case VLW_SHARED_ORDERS: /* Shared Orders */
   948 				if (this->vehicles.list_length == 0) {
   946 				if (this->vehicles.Length() == 0) {
   949 					/* We can't open this window without vehicles using this order
   947 					/* We can't open this window without vehicles using this order
   950 					* and we should close the window when deleting the order      */
   948 					* and we should close the window when deleting the order      */
   951 					NOT_REACHED();
   949 					NOT_REACHED();
   952 				}
   950 				}
   953 				SetDParam(0, this->vscroll.count);
   951 				SetDParam(0, this->vscroll.count);
   979 				SetDParam(2, this->vscroll.count);
   977 				SetDParam(2, this->vscroll.count);
   980 				break;
   978 				break;
   981 			default: NOT_REACHED(); break;
   979 			default: NOT_REACHED(); break;
   982 		}
   980 		}
   983 
   981 
   984 		this->SetWidgetsDisabledState(this->vehicles.list_length == 0,
   982 		this->SetWidgetsDisabledState(this->vehicles.Length() == 0,
   985 			VLW_WIDGET_MANAGE_VEHICLES_DROPDOWN,
   983 			VLW_WIDGET_MANAGE_VEHICLES_DROPDOWN,
   986 			VLW_WIDGET_STOP_ALL,
   984 			VLW_WIDGET_STOP_ALL,
   987 			VLW_WIDGET_START_ALL,
   985 			VLW_WIDGET_START_ALL,
   988 			WIDGET_LIST_END);
   986 			WIDGET_LIST_END);
   989 
   987 
   992 		/* draw sorting criteria string */
   990 		/* draw sorting criteria string */
   993 		DrawString(85, 15, _vehicle_sort_listing[this->vehicles.sort_type], TC_BLACK);
   991 		DrawString(85, 15, _vehicle_sort_listing[this->vehicles.sort_type], TC_BLACK);
   994 		/* draw arrow pointing up/down for ascending/descending sorting */
   992 		/* draw arrow pointing up/down for ascending/descending sorting */
   995 		this->DrawSortButtonState(VLW_WIDGET_SORT_ORDER, this->vehicles.flags & VL_DESC ? SBS_DOWN : SBS_UP);
   993 		this->DrawSortButtonState(VLW_WIDGET_SORT_ORDER, this->vehicles.flags & VL_DESC ? SBS_DOWN : SBS_UP);
   996 
   994 
   997 		max = min(this->vscroll.pos + this->vscroll.cap, this->vehicles.list_length);
   995 		max = min(this->vscroll.pos + this->vscroll.cap, this->vehicles.Length());
   998 		for (i = this->vscroll.pos; i < max; ++i) {
   996 		for (i = this->vscroll.pos; i < max; ++i) {
   999 			const Vehicle *v = this->vehicles.sort_list[i];
   997 			const Vehicle *v = this->vehicles[i];
  1000 			StringID str;
   998 			StringID str;
  1001 
   999 
  1002 			SetDParam(0, v->GetDisplayProfitThisYear());
  1000 			SetDParam(0, v->GetDisplayProfitThisYear());
  1003 			SetDParam(1, v->GetDisplayProfitLastYear());
  1001 			SetDParam(1, v->GetDisplayProfitLastYear());
  1004 
  1002 
  1047 
  1045 
  1048 				if (id_v >= this->vscroll.cap) return; // click out of bounds
  1046 				if (id_v >= this->vscroll.cap) return; // click out of bounds
  1049 
  1047 
  1050 				id_v += this->vscroll.pos;
  1048 				id_v += this->vscroll.pos;
  1051 
  1049 
  1052 				if (id_v >= this->vehicles.list_length) return; // click out of list bound
  1050 				if (id_v >= this->vehicles.Length()) return; // click out of list bound
  1053 
  1051 
  1054 				v = this->vehicles.sort_list[id_v];
  1052 				v = this->vehicles[id_v];
  1055 
  1053 
  1056 				ShowVehicleViewWindow(v);
  1054 				ShowVehicleViewWindow(v);
  1057 			} break;
  1055 			} break;
  1058 
  1056 
  1059 			case VLW_WIDGET_AVAILABLE_VEHICLES:
  1057 			case VLW_WIDGET_AVAILABLE_VEHICLES:
  1098 					this->vehicles.sort_type = index;
  1096 					this->vehicles.sort_type = index;
  1099 					this->sorting->criteria = this->vehicles.sort_type;
  1097 					this->sorting->criteria = this->vehicles.sort_type;
  1100 				}
  1098 				}
  1101 				break;
  1099 				break;
  1102 			case VLW_WIDGET_MANAGE_VEHICLES_DROPDOWN:
  1100 			case VLW_WIDGET_MANAGE_VEHICLES_DROPDOWN:
  1103 				assert(this->vehicles.list_length != 0);
  1101 				assert(this->vehicles.Length() != 0);
  1104 
  1102 
  1105 				switch (index) {
  1103 				switch (index) {
  1106 					case 0: /* Replace window */
  1104 					case 0: /* Replace window */
  1107 						ShowReplaceGroupVehicleWindow(DEFAULT_GROUP, this->vehicle_type);
  1105 						ShowReplaceGroupVehicleWindow(DEFAULT_GROUP, this->vehicle_type);
  1108 						break;
  1106 						break;
  1218 	}
  1216 	}
  1219 }
  1217 }
  1220 
  1218 
  1221 void ShowVehicleListWindow(PlayerID player, VehicleType vehicle_type)
  1219 void ShowVehicleListWindow(PlayerID player, VehicleType vehicle_type)
  1222 {
  1220 {
  1223 	/* If _settings.gui.advanced_vehicle_list > 1, display the Advanced list
  1221 	/* If _settings_client.gui.advanced_vehicle_list > 1, display the Advanced list
  1224 	 * if _settings.gui.advanced_vehicle_list == 1, display Advanced list only for local player
  1222 	 * if _settings_client.gui.advanced_vehicle_list == 1, display Advanced list only for local player
  1225 	 * if _ctrl_pressed, do the opposite action (Advanced list x Normal list)
  1223 	 * if _ctrl_pressed, do the opposite action (Advanced list x Normal list)
  1226 	 */
  1224 	 */
  1227 
  1225 
  1228 	if ((_settings.gui.advanced_vehicle_list > (uint)(player != _local_player)) != _ctrl_pressed) {
  1226 	if ((_settings_client.gui.advanced_vehicle_list > (uint)(player != _local_player)) != _ctrl_pressed) {
  1229 		ShowPlayerGroup(player, vehicle_type);
  1227 		ShowPlayerGroup(player, vehicle_type);
  1230 	} else {
  1228 	} else {
  1231 		ShowVehicleListWindowLocal(player, VLW_STANDARD, vehicle_type, 0);
  1229 		ShowVehicleListWindowLocal(player, VLW_STANDARD, vehicle_type, 0);
  1232 	}
  1230 	}
  1233 }
  1231 }
  1409 	/** Checks whether service interval is enabled for the vehicle. */
  1407 	/** Checks whether service interval is enabled for the vehicle. */
  1410 	static bool IsVehicleServiceIntervalEnabled(const VehicleType vehicle_type)
  1408 	static bool IsVehicleServiceIntervalEnabled(const VehicleType vehicle_type)
  1411 	{
  1409 	{
  1412 		switch (vehicle_type) {
  1410 		switch (vehicle_type) {
  1413 			default: NOT_REACHED();
  1411 			default: NOT_REACHED();
  1414 			case VEH_TRAIN:    return _settings.vehicle.servint_trains   != 0; break;
  1412 			case VEH_TRAIN:    return _settings_game.vehicle.servint_trains   != 0; break;
  1415 			case VEH_ROAD:     return _settings.vehicle.servint_roadveh  != 0; break;
  1413 			case VEH_ROAD:     return _settings_game.vehicle.servint_roadveh  != 0; break;
  1416 			case VEH_SHIP:     return _settings.vehicle.servint_ships    != 0; break;
  1414 			case VEH_SHIP:     return _settings_game.vehicle.servint_ships    != 0; break;
  1417 			case VEH_AIRCRAFT: return _settings.vehicle.servint_aircraft != 0; break;
  1415 			case VEH_AIRCRAFT: return _settings_game.vehicle.servint_aircraft != 0; break;
  1418 		}
  1416 		}
  1419 		return false; // kill a compiler warning
  1417 		return false; // kill a compiler warning
  1420 	}
  1418 	}
  1421 
  1419 
  1422 	/**
  1420 	/**
  1484 			case VEH_TRAIN:
  1482 			case VEH_TRAIN:
  1485 				SetDParam(2, v->GetDisplayMaxSpeed());
  1483 				SetDParam(2, v->GetDisplayMaxSpeed());
  1486 				SetDParam(1, v->u.rail.cached_power);
  1484 				SetDParam(1, v->u.rail.cached_power);
  1487 				SetDParam(0, v->u.rail.cached_weight);
  1485 				SetDParam(0, v->u.rail.cached_weight);
  1488 				SetDParam(3, v->u.rail.cached_max_te / 1000);
  1486 				SetDParam(3, v->u.rail.cached_max_te / 1000);
  1489 				DrawString(2, 25, (_settings.vehicle.realistic_acceleration && v->u.rail.railtype != RAILTYPE_MAGLEV) ?
  1487 				DrawString(2, 25, (_settings_game.vehicle.realistic_acceleration && v->u.rail.railtype != RAILTYPE_MAGLEV) ?
  1490 					STR_VEHICLE_INFO_WEIGHT_POWER_MAX_SPEED_MAX_TE :
  1488 					STR_VEHICLE_INFO_WEIGHT_POWER_MAX_SPEED_MAX_TE :
  1491 					STR_VEHICLE_INFO_WEIGHT_POWER_MAX_SPEED, TC_FROMSTRING);
  1489 					STR_VEHICLE_INFO_WEIGHT_POWER_MAX_SPEED, TC_FROMSTRING);
  1492 				break;
  1490 				break;
  1493 
  1491 
  1494 			case VEH_ROAD:
  1492 			case VEH_ROAD:
  1512 		DrawString(2, 45, _vehicle_translation_table[VST_VEHICLE_RELIABILITY_BREAKDOWNS][v->type], TC_FROMSTRING);
  1510 		DrawString(2, 45, _vehicle_translation_table[VST_VEHICLE_RELIABILITY_BREAKDOWNS][v->type], TC_FROMSTRING);
  1513 
  1511 
  1514 		/* Draw service interval text */
  1512 		/* Draw service interval text */
  1515 		SetDParam(0, v->service_interval);
  1513 		SetDParam(0, v->service_interval);
  1516 		SetDParam(1, v->date_of_last_service);
  1514 		SetDParam(1, v->date_of_last_service);
  1517 		DrawString(13, this->height - (v->type != VEH_TRAIN ? 11 : 23), _settings.vehicle.servint_ispercent ? STR_SERVICING_INTERVAL_PERCENT : STR_883C_SERVICING_INTERVAL_DAYS, TC_FROMSTRING);
  1515 		DrawString(13, this->height - (v->type != VEH_TRAIN ? 11 : 23), _settings_game.vehicle.servint_ispercent ? STR_SERVICING_INTERVAL_PERCENT : STR_883C_SERVICING_INTERVAL_DAYS, TC_FROMSTRING);
  1518 
  1516 
  1519 		switch (v->type) {
  1517 		switch (v->type) {
  1520 			case VEH_TRAIN:
  1518 			case VEH_TRAIN:
  1521 				DrawVehicleDetails(v, 2, 57, this->vscroll.pos, this->vscroll.cap, det_tab);
  1519 				DrawVehicleDetails(v, 2, 57, this->vscroll.pos, this->vscroll.cap, det_tab);
  1522 				break;
  1520 				break;
  1951 					} else {
  1949 					} else {
  1952 						str = STR_8861_STOPPED;
  1950 						str = STR_8861_STOPPED;
  1953 					}
  1951 					}
  1954 				} else {
  1952 				} else {
  1955 					SetDParam(0, v->GetDisplaySpeed());
  1953 					SetDParam(0, v->GetDisplaySpeed());
  1956 					str = STR_TRAIN_STOPPING + _settings.gui.vehicle_speed;
  1954 					str = STR_TRAIN_STOPPING + _settings_client.gui.vehicle_speed;
  1957 				}
  1955 				}
  1958 			} else { // no train
  1956 			} else { // no train
  1959 				str = STR_8861_STOPPED;
  1957 				str = STR_8861_STOPPED;
  1960 			}
  1958 			}
  1961 		} else { // vehicle is in a "normal" state, show current order
  1959 		} else { // vehicle is in a "normal" state, show current order
  1962 			switch (v->current_order.GetType()) {
  1960 			switch (v->current_order.GetType()) {
  1963 				case OT_GOTO_STATION: {
  1961 				case OT_GOTO_STATION: {
  1964 					SetDParam(0, v->current_order.GetDestination());
  1962 					SetDParam(0, v->current_order.GetDestination());
  1965 					SetDParam(1, v->GetDisplaySpeed());
  1963 					SetDParam(1, v->GetDisplaySpeed());
  1966 					str = STR_HEADING_FOR_STATION + _settings.gui.vehicle_speed;
  1964 					str = STR_HEADING_FOR_STATION + _settings_client.gui.vehicle_speed;
  1967 				} break;
  1965 				} break;
  1968 
  1966 
  1969 				case OT_GOTO_DEPOT: {
  1967 				case OT_GOTO_DEPOT: {
  1970 					if (v->type == VEH_AIRCRAFT) {
  1968 					if (v->type == VEH_AIRCRAFT) {
  1971 						/* Aircrafts always go to a station, even if you say depot */
  1969 						/* Aircrafts always go to a station, even if you say depot */
  1975 						Depot *depot = GetDepot(v->current_order.GetDestination());
  1973 						Depot *depot = GetDepot(v->current_order.GetDestination());
  1976 						SetDParam(0, depot->town_index);
  1974 						SetDParam(0, depot->town_index);
  1977 						SetDParam(1, v->GetDisplaySpeed());
  1975 						SetDParam(1, v->GetDisplaySpeed());
  1978 					}
  1976 					}
  1979 					if ((v->current_order.GetDepotActionType() & ODATFB_HALT) && !(v->current_order.GetDepotOrderType() & ODTFB_PART_OF_ORDERS)) {
  1977 					if ((v->current_order.GetDepotActionType() & ODATFB_HALT) && !(v->current_order.GetDepotOrderType() & ODTFB_PART_OF_ORDERS)) {
  1980 						str = _heading_for_depot_strings[v->type] + _settings.gui.vehicle_speed;
  1978 						str = _heading_for_depot_strings[v->type] + _settings_client.gui.vehicle_speed;
  1981 					} else {
  1979 					} else {
  1982 						str = _heading_for_depot_service_strings[v->type] + _settings.gui.vehicle_speed;
  1980 						str = _heading_for_depot_service_strings[v->type] + _settings_client.gui.vehicle_speed;
  1983 					}
  1981 					}
  1984 				} break;
  1982 				} break;
  1985 
  1983 
  1986 				case OT_LOADING:
  1984 				case OT_LOADING:
  1987 					str = STR_882F_LOADING_UNLOADING;
  1985 					str = STR_882F_LOADING_UNLOADING;
  1988 					break;
  1986 					break;
  1989 
  1987 
  1990 				case OT_GOTO_WAYPOINT: {
  1988 				case OT_GOTO_WAYPOINT: {
  1991 					assert(v->type == VEH_TRAIN);
  1989 					assert(v->type == VEH_TRAIN);
  1992 					SetDParam(0, v->current_order.GetDestination());
  1990 					SetDParam(0, v->current_order.GetDestination());
  1993 					str = STR_HEADING_FOR_WAYPOINT + _settings.gui.vehicle_speed;
  1991 					str = STR_HEADING_FOR_WAYPOINT + _settings_client.gui.vehicle_speed;
  1994 					SetDParam(1, v->GetDisplaySpeed());
  1992 					SetDParam(1, v->GetDisplaySpeed());
  1995 					break;
  1993 					break;
  1996 				}
  1994 				}
  1997 
  1995 
  1998 				case OT_LEAVESTATION:
  1996 				case OT_LEAVESTATION:
  2002 					}
  2000 					}
  2003 					/* fall-through if aircraft. Does this even happen? */
  2001 					/* fall-through if aircraft. Does this even happen? */
  2004 
  2002 
  2005 				default:
  2003 				default:
  2006 					if (v->num_orders == 0) {
  2004 					if (v->num_orders == 0) {
  2007 						str = STR_NO_ORDERS + _settings.gui.vehicle_speed;
  2005 						str = STR_NO_ORDERS + _settings_client.gui.vehicle_speed;
  2008 						SetDParam(0, v->GetDisplaySpeed());
  2006 						SetDParam(0, v->GetDisplaySpeed());
  2009 					} else {
  2007 					} else {
  2010 						str = STR_EMPTY;
  2008 						str = STR_EMPTY;
  2011 					}
  2009 					}
  2012 					break;
  2010 					break;