27 #include "aircraft.h" |
29 #include "aircraft.h" |
28 #include "roadveh.h" |
30 #include "roadveh.h" |
29 #include "depot.h" |
31 #include "depot.h" |
30 #include "helpers.hpp" |
32 #include "helpers.hpp" |
31 #include "cargotype.h" |
33 #include "cargotype.h" |
|
34 #include "group.h" |
32 |
35 |
33 struct Sorting { |
36 struct Sorting { |
34 Listing aircraft; |
37 Listing aircraft; |
35 Listing roadveh; |
38 Listing roadveh; |
36 Listing ship; |
39 Listing ship; |
37 Listing train; |
40 Listing train; |
38 }; |
41 }; |
39 |
42 |
40 static Sorting _sorting; |
43 static Sorting _sorting; |
41 |
|
42 struct vehiclelist_d { |
|
43 const Vehicle** sort_list; // List of vehicles (sorted) |
|
44 Listing *_sorting; // pointer to the appropiate subcategory of _sorting |
|
45 uint16 length_of_sort_list; // Keeps track of how many vehicle pointers sort list got space for |
|
46 byte vehicle_type; // The vehicle type that is sorted |
|
47 list_d l; // General list struct |
|
48 }; |
|
49 assert_compile(WINDOW_CUSTOM_SIZE >= sizeof(vehiclelist_d)); |
|
50 |
44 |
51 static bool _internal_sort_order; // descending/ascending |
45 static bool _internal_sort_order; // descending/ascending |
52 |
46 |
53 typedef int CDECL VehicleSortListingTypeFunction(const void*, const void*); |
47 typedef int CDECL VehicleSortListingTypeFunction(const void*, const void*); |
54 |
48 |
160 { |
154 { |
161 _internal_sort_order = 0; |
155 _internal_sort_order = 0; |
162 qsort((void*)v, length, sizeof(v[0]), _vehicle_sorter[0]); |
156 qsort((void*)v, length, sizeof(v[0]), _vehicle_sorter[0]); |
163 } |
157 } |
164 |
158 |
165 // draw the vehicle profit button in the vehicle list window. |
159 /** draw the vehicle profit button in the vehicle list window. */ |
166 void DrawVehicleProfitButton(const Vehicle *v, int x, int y) |
160 void DrawVehicleProfitButton(const Vehicle *v, int x, int y) |
167 { |
161 { |
168 SpriteID pal; |
162 SpriteID pal; |
169 |
163 |
170 // draw profit-based colored icons |
164 /* draw profit-based colored icons */ |
171 if (v->age <= 365 * 2) { |
165 if (v->age <= 365 * 2) { |
172 pal = PALETTE_TO_GREY; |
166 pal = PALETTE_TO_GREY; |
173 } else if (v->profit_last_year < 0) { |
167 } else if (v->profit_last_year < 0) { |
174 pal = PALETTE_TO_RED; |
168 pal = PALETTE_TO_RED; |
175 } else if (v->profit_last_year < 10000) { |
169 } else if (v->profit_last_year < 10000) { |
275 return list; |
269 return list; |
276 } |
270 } |
277 |
271 |
278 /** Draw the list of available refit options for a consist. |
272 /** Draw the list of available refit options for a consist. |
279 * Draw the list and highlight the selected refit option (if any) |
273 * Draw the list and highlight the selected refit option (if any) |
280 * @param *v first vehicle in consist to get the refit-options of |
274 * @param *list first vehicle in consist to get the refit-options of |
281 * @param sel selected refit cargo-type in the window |
275 * @param sel selected refit cargo-type in the window |
|
276 * @param pos position of the selected item in caller widow |
|
277 * @param rows number of rows(capacity) in caller window |
|
278 * @param delta step height in caller window |
282 * @return the refit option that is hightlighted, NULL if none |
279 * @return the refit option that is hightlighted, NULL if none |
283 */ |
280 */ |
284 static RefitOption *DrawVehicleRefitWindow(const RefitList *list, int sel, uint pos, uint rows, uint delta) |
281 static RefitOption *DrawVehicleRefitWindow(const RefitList *list, int sel, uint pos, uint rows, uint delta) |
285 { |
282 { |
286 RefitOption *refit = list->items; |
283 RefitOption *refit = list->items; |
336 |
333 |
337 SetDParam(0, v->string_id); |
334 SetDParam(0, v->string_id); |
338 SetDParam(1, v->unitnumber); |
335 SetDParam(1, v->unitnumber); |
339 DrawWindowWidgets(w); |
336 DrawWindowWidgets(w); |
340 |
337 |
341 WP(w,refit_d).cargo = DrawVehicleRefitWindow(WP(w, refit_d).list, WP(w, refit_d).sel, w->vscroll.pos, w->vscroll.cap, w->resize.step_height); |
338 WP(w, refit_d).cargo = DrawVehicleRefitWindow(WP(w, refit_d).list, WP(w, refit_d).sel, w->vscroll.pos, w->vscroll.cap, w->resize.step_height); |
342 |
339 |
343 if (WP(w,refit_d).cargo != NULL) { |
340 if (WP(w, refit_d).cargo != NULL) { |
344 int32 cost; |
341 int32 cost; |
345 |
342 |
346 cost = DoCommand(v->tile, v->index, WP(w,refit_d).cargo->cargo | WP(w,refit_d).cargo->subtype << 8, |
343 cost = DoCommand(v->tile, v->index, WP(w, refit_d).cargo->cargo | WP(w, refit_d).cargo->subtype << 8, |
347 DC_QUERY_COST, GetCmdRefitVeh(GetVehicle(w->window_number)->type)); |
344 DC_QUERY_COST, GetCmdRefitVeh(GetVehicle(w->window_number)->type)); |
348 |
345 |
349 if (!CmdFailed(cost)) { |
346 if (!CmdFailed(cost)) { |
350 SetDParam(0, WP(w,refit_d).cargo->cargo); |
347 SetDParam(0, WP(w, refit_d).cargo->cargo); |
351 SetDParam(1, _returned_refit_capacity); |
348 SetDParam(1, _returned_refit_capacity); |
352 SetDParam(2, cost); |
349 SetDParam(2, cost); |
353 DrawString(2, w->widget[5].top + 1, STR_9840_NEW_CAPACITY_COST_OF_REFIT, 0); |
350 DrawString(2, w->widget[5].top + 1, STR_9840_NEW_CAPACITY_COST_OF_REFIT, 0); |
354 } |
351 } |
355 } |
352 } |
356 } break; |
353 } break; |
357 |
354 |
358 case WE_CLICK: |
355 case WE_CLICK: |
359 switch (e->we.click.widget) { |
356 switch (e->we.click.widget) { |
360 case 3: { // listbox |
357 case 3: { // listbox |
361 int y = e->we.click.pt.y - w->widget[3].top; |
358 int y = e->we.click.pt.y - w->widget[3].top; |
362 if (y >= 0) { |
359 if (y >= 0) { |
363 WP(w,refit_d).sel = (y / (int)w->resize.step_height) + w->vscroll.pos; |
360 WP(w, refit_d).sel = (y / (int)w->resize.step_height) + w->vscroll.pos; |
364 SetWindowDirty(w); |
361 SetWindowDirty(w); |
365 } |
362 } |
366 } break; |
363 } break; |
367 case 6: // refit button |
364 case 6: // refit button |
368 if (WP(w,refit_d).cargo != NULL) { |
365 if (WP(w, refit_d).cargo != NULL) { |
369 const Vehicle *v = GetVehicle(w->window_number); |
366 const Vehicle *v = GetVehicle(w->window_number); |
370 |
367 |
371 if (WP(w, refit_d).order == INVALID_VEH_ORDER_ID) { |
368 if (WP(w, refit_d).order == INVALID_VEH_ORDER_ID) { |
372 int command = 0; |
369 int command = 0; |
373 |
370 |
374 switch (v->type) { |
371 switch (v->type) { |
|
372 default: NOT_REACHED(); |
375 case VEH_TRAIN: command = CMD_REFIT_RAIL_VEHICLE | CMD_MSG(STR_RAIL_CAN_T_REFIT_VEHICLE); break; |
373 case VEH_TRAIN: command = CMD_REFIT_RAIL_VEHICLE | CMD_MSG(STR_RAIL_CAN_T_REFIT_VEHICLE); break; |
376 case VEH_ROAD: command = CMD_REFIT_ROAD_VEH | CMD_MSG(STR_REFIT_ROAD_VEHICLE_CAN_T); break; |
374 case VEH_ROAD: command = CMD_REFIT_ROAD_VEH | CMD_MSG(STR_REFIT_ROAD_VEHICLE_CAN_T); break; |
377 case VEH_SHIP: command = CMD_REFIT_SHIP | CMD_MSG(STR_9841_CAN_T_REFIT_SHIP); break; |
375 case VEH_SHIP: command = CMD_REFIT_SHIP | CMD_MSG(STR_9841_CAN_T_REFIT_SHIP); break; |
378 case VEH_AIRCRAFT: command = CMD_REFIT_AIRCRAFT | CMD_MSG(STR_A042_CAN_T_REFIT_AIRCRAFT); break; |
376 case VEH_AIRCRAFT: command = CMD_REFIT_AIRCRAFT | CMD_MSG(STR_A042_CAN_T_REFIT_AIRCRAFT); break; |
379 } |
377 } |
380 if (DoCommandP(v->tile, v->index, WP(w,refit_d).cargo->cargo | WP(w,refit_d).cargo->subtype << 8, NULL, command)) DeleteWindow(w); |
378 if (DoCommandP(v->tile, v->index, WP(w, refit_d).cargo->cargo | WP(w, refit_d).cargo->subtype << 8, NULL, command)) DeleteWindow(w); |
381 } else { |
379 } else { |
382 if (DoCommandP(v->tile, v->index, WP(w,refit_d).cargo->cargo | WP(w,refit_d).cargo->subtype << 8 | WP(w, refit_d).order << 16, NULL, CMD_ORDER_REFIT)) DeleteWindow(w); |
380 if (DoCommandP(v->tile, v->index, WP(w, refit_d).cargo->cargo | WP(w, refit_d).cargo->subtype << 8 | WP(w, refit_d).order << 16, NULL, CMD_ORDER_REFIT)) DeleteWindow(w); |
383 } |
381 } |
384 } |
382 } |
385 break; |
383 break; |
386 } |
384 } |
387 break; |
385 break; |
411 { WIDGETS_END}, |
409 { WIDGETS_END}, |
412 }; |
410 }; |
413 |
411 |
414 static const WindowDesc _vehicle_refit_desc = { |
412 static const WindowDesc _vehicle_refit_desc = { |
415 WDP_AUTO, WDP_AUTO, 240, 174, |
413 WDP_AUTO, WDP_AUTO, 240, 174, |
416 WC_VEHICLE_REFIT,WC_VEHICLE_VIEW, |
414 WC_VEHICLE_REFIT, WC_VEHICLE_VIEW, |
417 WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS | WDF_RESIZABLE, |
415 WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS | WDF_RESIZABLE, |
418 _vehicle_refit_widgets, |
416 _vehicle_refit_widgets, |
419 VehicleRefitWndProc, |
417 VehicleRefitWndProc, |
420 }; |
418 }; |
421 |
419 |
422 /** Show the refit window for a vehicle |
420 /** Show the refit window for a vehicle |
423 * @param *v The vehicle to show the refit window for |
421 * @param *v The vehicle to show the refit window for |
|
422 * @param order of the vehicle ( ? ) |
424 */ |
423 */ |
425 void ShowVehicleRefitWindow(const Vehicle *v, VehicleOrderID order) |
424 void ShowVehicleRefitWindow(const Vehicle *v, VehicleOrderID order) |
426 { |
425 { |
427 Window *w; |
426 Window *w; |
428 |
427 |
464 default: NOT_REACHED(); |
463 default: NOT_REACHED(); |
465 } |
464 } |
466 } |
465 } |
467 } |
466 } |
468 |
467 |
469 /* Display additional text from NewGRF in the purchase information window */ |
468 /** Display additional text from NewGRF in the purchase information window */ |
470 uint ShowAdditionalText(int x, int y, uint w, EngineID engine) |
469 uint ShowAdditionalText(int x, int y, uint w, EngineID engine) |
471 { |
470 { |
472 uint16 callback = GetVehicleCallback(CBID_VEHICLE_ADDITIONAL_TEXT, 0, 0, engine, NULL); |
471 uint16 callback = GetVehicleCallback(CBID_VEHICLE_ADDITIONAL_TEXT, 0, 0, engine, NULL); |
473 if (callback == CALLBACK_FAILED) return 0; |
472 if (callback == CALLBACK_FAILED) return 0; |
474 |
473 |
475 // STR_02BD is used to start the string with {BLACK} |
474 /* STR_02BD is used to start the string with {BLACK} */ |
476 SetDParam(0, GetGRFStringID(GetEngineGRFID(engine), 0xD000 + callback)); |
475 SetDParam(0, GetGRFStringID(GetEngineGRFID(engine), 0xD000 + callback)); |
477 return DrawStringMultiLine(x, y, STR_02BD, w); |
476 return DrawStringMultiLine(x, y, STR_02BD, w); |
478 } |
477 } |
479 |
478 |
480 /* Count the number of bits that are set in a mask */ |
479 /** Count the number of bits that are set in a mask */ |
481 static uint CountBits(uint32 mask) |
480 static uint CountBits(uint32 mask) |
482 { |
481 { |
483 uint c = 0; |
482 uint c = 0; |
484 for (; mask != 0; mask >>= 1) if (HASBIT(mask, 0)) c++; |
483 for (; mask != 0; mask >>= 1) if (HASBIT(mask, 0)) c++; |
485 return c; |
484 return c; |
486 } |
485 } |
487 |
486 |
488 /* Display list of cargo types of the engine, for the purchase information window */ |
487 /** Display list of cargo types of the engine, for the purchase information window */ |
489 uint ShowRefitOptionsList(int x, int y, uint w, EngineID engine) |
488 uint ShowRefitOptionsList(int x, int y, uint w, EngineID engine) |
490 { |
489 { |
491 /* List of cargo types of this engine */ |
490 /* List of cargo types of this engine */ |
492 uint32 cmask = EngInfo(engine)->refit_mask; |
491 uint32 cmask = EngInfo(engine)->refit_mask; |
493 /* List of cargo types available in this climate */ |
492 /* List of cargo types available in this climate */ |
800 { |
789 { |
801 vehiclelist_d *vl = &WP(w, vehiclelist_d); |
790 vehiclelist_d *vl = &WP(w, vehiclelist_d); |
802 uint16 window_type = w->window_number & VLW_MASK; |
791 uint16 window_type = w->window_number & VLW_MASK; |
803 PlayerID player = (PlayerID)GB(w->window_number, 0, 8); |
792 PlayerID player = (PlayerID)GB(w->window_number, 0, 8); |
804 |
793 |
805 vl->vehicle_type = GB(w->window_number, 11, 5); |
794 vl->vehicle_type = (VehicleType)GB(w->window_number, 11, 5); |
806 vl->length_of_sort_list = 0; |
795 vl->length_of_sort_list = 0; |
807 vl->sort_list = NULL; |
796 vl->sort_list = NULL; |
808 w->caption_color = player; |
797 w->caption_color = player; |
809 |
798 |
810 /* Hide the widgets that we will not use in this window |
799 /* Hide the widgets that we will not use in this window |
1132 case VLW_WIDGET_STOP_ALL: |
1121 case VLW_WIDGET_STOP_ALL: |
1133 case VLW_WIDGET_START_ALL: |
1122 case VLW_WIDGET_START_ALL: |
1134 DoCommandP(0, GB(w->window_number, 16, 16), (w->window_number & VLW_MASK) | (1 << 6) | (e->we.click.widget == VLW_WIDGET_START_ALL ? (1 << 5) : 0) | vl->vehicle_type, NULL, CMD_MASS_START_STOP); |
1123 DoCommandP(0, GB(w->window_number, 16, 16), (w->window_number & VLW_MASK) | (1 << 6) | (e->we.click.widget == VLW_WIDGET_START_ALL ? (1 << 5) : 0) | vl->vehicle_type, NULL, CMD_MASS_START_STOP); |
1135 break; |
1124 break; |
1136 } |
1125 } |
1137 } break; |
1126 } break; |
1138 |
1127 |
1139 case WE_DROPDOWN_SELECT: /* we have selected a dropdown item in the list */ |
1128 case WE_DROPDOWN_SELECT: /* we have selected a dropdown item in the list */ |
1140 switch (e->we.dropdown.button) { |
1129 switch (e->we.dropdown.button) { |
1141 case VLW_WIDGET_SORT_BY_PULLDOWN: |
1130 case VLW_WIDGET_SORT_BY_PULLDOWN: |
1142 if (vl->l.sort_type != e->we.dropdown.index) { |
1131 if (vl->l.sort_type != e->we.dropdown.index) { |
1143 // value has changed -> resort |
1132 /* value has changed -> resort */ |
1144 vl->l.flags |= VL_RESORT; |
1133 vl->l.flags |= VL_RESORT; |
1145 vl->l.sort_type = e->we.dropdown.index; |
1134 vl->l.sort_type = e->we.dropdown.index; |
1146 vl->_sorting->criteria = vl->l.sort_type; |
1135 vl->_sorting->criteria = vl->l.sort_type; |
1147 } |
1136 } |
1148 break; |
1137 break; |
1264 w->resize.width = w->width; |
1253 w->resize.width = w->width; |
1265 w->resize.height = w->height; |
1254 w->resize.height = w->height; |
1266 } |
1255 } |
1267 } |
1256 } |
1268 |
1257 |
1269 void ShowVehicleListWindow(PlayerID player, byte vehicle_type) |
1258 void ShowVehicleListWindow(PlayerID player, VehicleType vehicle_type) |
1270 { |
1259 { |
1271 ShowVehicleListWindowLocal(player, VLW_STANDARD, vehicle_type, 0); |
1260 if (player == _local_player && _patches.advanced_vehicle_list) { |
|
1261 ShowPlayerGroup(player, vehicle_type); |
|
1262 } else { |
|
1263 ShowVehicleListWindowLocal(player, VLW_STANDARD, vehicle_type, 0); |
|
1264 } |
1272 } |
1265 } |
1273 |
1266 |
1274 void ShowVehicleListWindow(const Vehicle *v) |
1267 void ShowVehicleListWindow(const Vehicle *v) |
1275 { |
1268 { |
1276 if (v->orders == NULL) return; // no shared list to show |
1269 if (v->orders == NULL) return; // no shared list to show |
1277 ShowVehicleListWindowLocal(v->owner, VLW_SHARED_ORDERS, v->type, v->orders->index); |
1270 ShowVehicleListWindowLocal(v->owner, VLW_SHARED_ORDERS, v->type, v->orders->index); |
1278 } |
1271 } |
1279 |
1272 |
1280 void ShowVehicleListWindow(PlayerID player, byte vehicle_type, StationID station) |
1273 void ShowVehicleListWindow(PlayerID player, VehicleType vehicle_type, StationID station) |
1281 { |
1274 { |
1282 ShowVehicleListWindowLocal(player, VLW_STATION_LIST, vehicle_type, station); |
1275 ShowVehicleListWindowLocal(player, VLW_STATION_LIST, vehicle_type, station); |
1283 } |
1276 } |
1284 |
1277 |
1285 void ShowVehicleListWindow(PlayerID player, byte vehicle_type, TileIndex depot_tile) |
1278 void ShowVehicleListWindow(PlayerID player, VehicleType vehicle_type, TileIndex depot_tile) |
1286 { |
1279 { |
1287 uint16 depot_airport_index; |
1280 uint16 depot_airport_index; |
1288 |
1281 |
1289 if (vehicle_type == VEH_AIRCRAFT) { |
1282 if (vehicle_type == VEH_AIRCRAFT) { |
1290 depot_airport_index = GetStationIndex(depot_tile); |
1283 depot_airport_index = GetStationIndex(depot_tile); |