src/build_vehicle_gui.cpp
branchNewGRF_ports
changeset 6719 4cc327ad39d5
parent 6712 d100bbf7f752
child 6720 35756db7e577
equal deleted inserted replaced
6718:5a8b295aa345 6719:4cc327ad39d5
    13 #include "table/sprites.h"
    13 #include "table/sprites.h"
    14 #include "table/strings.h"
    14 #include "table/strings.h"
    15 #include "window.h"
    15 #include "window.h"
    16 #include "gui.h"
    16 #include "gui.h"
    17 #include "vehicle.h"
    17 #include "vehicle.h"
       
    18 #include "articulated_vehicles.h"
    18 #include "gfx.h"
    19 #include "gfx.h"
    19 #include "station.h"
    20 #include "station.h"
    20 #include "command.h"
    21 #include "command.h"
    21 #include "engine.h"
    22 #include "engine.h"
    22 #include "player.h"
    23 #include "player.h"
    25 #include "vehicle_gui.h"
    26 #include "vehicle_gui.h"
    26 #include "newgrf_engine.h"
    27 #include "newgrf_engine.h"
    27 #include "date.h"
    28 #include "date.h"
    28 #include "strings.h"
    29 #include "strings.h"
    29 #include "cargotype.h"
    30 #include "cargotype.h"
       
    31 #include "group.h"
       
    32 #include "road_map.h"
    30 
    33 
    31 
    34 
    32 enum BuildVehicleWidgets {
    35 enum BuildVehicleWidgets {
    33 	BUILD_VEHICLE_WIDGET_CLOSEBOX = 0,
    36 	BUILD_VEHICLE_WIDGET_CLOSEBOX = 0,
    34 	BUILD_VEHICLE_WIDGET_CAPTION,
    37 	BUILD_VEHICLE_WIDGET_CAPTION,
   235 	int r = ListPositionOfEngine(va) - ListPositionOfEngine(vb);
   238 	int r = ListPositionOfEngine(va) - ListPositionOfEngine(vb);
   236 
   239 
   237 	return _internal_sort_order ? -r : r;
   240 	return _internal_sort_order ? -r : r;
   238 }
   241 }
   239 
   242 
       
   243 static int CDECL TrainEngineCapacitySorter(const void *a, const void *b)
       
   244 {
       
   245 	int va = RailVehInfo(*(const EngineID*)a)->capacity;
       
   246 	int vb = RailVehInfo(*(const EngineID*)b)->capacity;
       
   247 	int r = va - vb;
       
   248 
       
   249 	if (r == 0) {
       
   250 		/* Use EngineID to sort instead since we want consistent sorting */
       
   251 		return EngineNumberSorter(a, b);
       
   252 	}
       
   253 	return _internal_sort_order ? -r : r;
       
   254 }
       
   255 
   240 static int CDECL TrainEnginesThenWagonsSorter(const void *a, const void *b)
   256 static int CDECL TrainEnginesThenWagonsSorter(const void *a, const void *b)
   241 {
   257 {
   242 	EngineID va = *(const EngineID*)a;
   258 	EngineID va = *(const EngineID*)a;
   243 	EngineID vb = *(const EngineID*)b;
   259 	EngineID vb = *(const EngineID*)b;
   244 	int val_a = (RailVehInfo(va)->railveh_type == RAILVEH_WAGON ? 1 : 0);
   260 	int val_a = (RailVehInfo(va)->railveh_type == RAILVEH_WAGON ? 1 : 0);
   249 	if (r == 0) return EngineNumberSorter(a, b);
   265 	if (r == 0) return EngineNumberSorter(a, b);
   250 
   266 
   251 	return _internal_sort_order ? -r : r;
   267 	return _internal_sort_order ? -r : r;
   252 }
   268 }
   253 
   269 
       
   270 static int CDECL RoadVehEngineCapacitySorter(const void *a, const void *b)
       
   271 {
       
   272 	int va = RoadVehInfo(*(const EngineID*)a)->capacity;
       
   273 	int vb = RoadVehInfo(*(const EngineID*)b)->capacity;
       
   274 	int r = va - vb;
       
   275 
       
   276 	if (r == 0) {
       
   277 		/* Use EngineID to sort instead since we want consistent sorting */
       
   278 		return EngineNumberSorter(a, b);
       
   279 	}
       
   280 	return _internal_sort_order ? -r : r;
       
   281 }
       
   282 
       
   283 static int CDECL ShipEngineCapacitySorter(const void *a, const void *b)
       
   284 {
       
   285 	int va = ShipVehInfo(*(const EngineID*)a)->capacity;
       
   286 	int vb = ShipVehInfo(*(const EngineID*)b)->capacity;
       
   287 	int r = va - vb;
       
   288 
       
   289 	if (r == 0) {
       
   290 		/* Use EngineID to sort instead since we want consistent sorting */
       
   291 		return EngineNumberSorter(a, b);
       
   292 	}
       
   293 	return _internal_sort_order ? -r : r;
       
   294 }
       
   295 
   254 /* Aircraft sorting functions */
   296 /* Aircraft sorting functions */
   255 
   297 
   256 static int CDECL AircraftEngineCostSorter(const void *a, const void *b)
   298 static int CDECL AircraftEngineCostSorter(const void *a, const void *b)
   257 {
   299 {
   258 	const int va = AircraftVehInfo(*(const EngineID*)a)->base_cost;
   300 	const int va = AircraftVehInfo(*(const EngineID*)a)->base_cost;
   288 	return _internal_sort_order ? -r : r;
   330 	return _internal_sort_order ? -r : r;
   289 }
   331 }
   290 
   332 
   291 static int CDECL AircraftEngineCargoSorter(const void *a, const void *b)
   333 static int CDECL AircraftEngineCargoSorter(const void *a, const void *b)
   292 {
   334 {
   293 	const int va = AircraftVehInfo(*(const EngineID*)a)->passenger_capacity;
   335 	int va = AircraftVehInfo(*(const EngineID*)a)->passenger_capacity;
   294 	const int vb = AircraftVehInfo(*(const EngineID*)b)->passenger_capacity;
   336 	int vb = AircraftVehInfo(*(const EngineID*)b)->passenger_capacity;
   295 	const int r = va - vb;
   337 	int r = va - vb;
   296 
   338 
   297 	if (r == 0) {
   339 	if (r == 0) {
   298 		/* Use EngineID to sort instead since we want consistent sorting */
   340 		/* The planes has the same passenger capacity. Check mail capacity instead */
   299 		return EngineNumberSorter(a, b);
   341 		va = AircraftVehInfo(*(const EngineID*)a)->mail_capacity;
   300 	}
   342 		vb = AircraftVehInfo(*(const EngineID*)b)->mail_capacity;
   301 	return _internal_sort_order ? -r : r;
   343 		r = va - vb;
   302 }
   344 
   303 
   345 		if (r == 0) {
   304 static EngList_SortTypeFunction * const _sorter[][9] = {{
   346 			/* Use EngineID to sort instead since we want consistent sorting */
       
   347 			return EngineNumberSorter(a, b);
       
   348 		}
       
   349 	}
       
   350 	return _internal_sort_order ? -r : r;
       
   351 }
       
   352 
       
   353 static EngList_SortTypeFunction * const _sorter[][10] = {{
   305 	/* Trains */
   354 	/* Trains */
   306 	&TrainEngineNumberSorter,
   355 	&TrainEngineNumberSorter,
   307 	&TrainEngineCostSorter,
   356 	&TrainEngineCostSorter,
   308 	&TrainEngineSpeedSorter,
   357 	&TrainEngineSpeedSorter,
   309 	&TrainEnginePowerSorter,
   358 	&TrainEnginePowerSorter,
   310 	&EngineIntroDateSorter,
   359 	&EngineIntroDateSorter,
   311 	&EngineNameSorter,
   360 	&EngineNameSorter,
   312 	&TrainEngineRunningCostSorter,
   361 	&TrainEngineRunningCostSorter,
   313 	&TrainEnginePowerVsRunningCostSorter,
   362 	&TrainEnginePowerVsRunningCostSorter,
   314 	&EngineReliabilitySorter,
   363 	&EngineReliabilitySorter,
   315 },{
   364 	&TrainEngineCapacitySorter,
       
   365 }, {
   316 	/* Road vehicles */
   366 	/* Road vehicles */
   317 	&EngineNumberSorter,
   367 	&EngineNumberSorter,
   318 	&EngineIntroDateSorter,
   368 	&EngineIntroDateSorter,
   319 	&EngineNameSorter,
   369 	&EngineNameSorter,
   320 	&EngineReliabilitySorter,
   370 	&EngineReliabilitySorter,
   321 },{
   371 	&RoadVehEngineCapacitySorter,
       
   372 }, {
   322 	/* Ships */
   373 	/* Ships */
   323 	&EngineNumberSorter,
   374 	&EngineNumberSorter,
   324 	&EngineIntroDateSorter,
   375 	&EngineIntroDateSorter,
   325 	&EngineNameSorter,
   376 	&EngineNameSorter,
   326 	&EngineReliabilitySorter,
   377 	&EngineReliabilitySorter,
   327 },{
   378 	&ShipEngineCapacitySorter,
       
   379 }, {
   328 	/* Aircraft */
   380 	/* Aircraft */
   329 	&EngineNumberSorter,
   381 	&EngineNumberSorter,
   330 	&AircraftEngineCostSorter,
   382 	&AircraftEngineCostSorter,
   331 	&AircraftEngineSpeedSorter,
   383 	&AircraftEngineSpeedSorter,
   332 	&EngineIntroDateSorter,
   384 	&EngineIntroDateSorter,
   334 	&AircraftEngineRunningCostSorter,
   386 	&AircraftEngineRunningCostSorter,
   335 	&EngineReliabilitySorter,
   387 	&EngineReliabilitySorter,
   336 	&AircraftEngineCargoSorter,
   388 	&AircraftEngineCargoSorter,
   337 }};
   389 }};
   338 
   390 
   339 static const StringID _sort_listing[][10] = {{
   391 static const StringID _sort_listing[][11] = {{
   340 	/* Trains */
   392 	/* Trains */
   341 	STR_ENGINE_SORT_ENGINE_ID,
   393 	STR_ENGINE_SORT_ENGINE_ID,
   342 	STR_ENGINE_SORT_COST,
   394 	STR_ENGINE_SORT_COST,
   343 	STR_SORT_BY_MAX_SPEED,
   395 	STR_SORT_BY_MAX_SPEED,
   344 	STR_ENGINE_SORT_POWER,
   396 	STR_ENGINE_SORT_POWER,
   345 	STR_ENGINE_SORT_INTRO_DATE,
   397 	STR_ENGINE_SORT_INTRO_DATE,
   346 	STR_SORT_BY_DROPDOWN_NAME,
   398 	STR_SORT_BY_DROPDOWN_NAME,
   347 	STR_ENGINE_SORT_RUNNING_COST,
   399 	STR_ENGINE_SORT_RUNNING_COST,
   348 	STR_ENGINE_SORT_POWER_VS_RUNNING_COST,
   400 	STR_ENGINE_SORT_POWER_VS_RUNNING_COST,
   349 	STR_SORT_BY_RELIABILITY,
   401 	STR_SORT_BY_RELIABILITY,
       
   402 	STR_ENGINE_SORT_CARGO_CAPACITY,
   350 	INVALID_STRING_ID
   403 	INVALID_STRING_ID
   351 },{
   404 }, {
   352 	/* Road vehicles */
   405 	/* Road vehicles */
   353 	STR_ENGINE_SORT_ENGINE_ID,
   406 	STR_ENGINE_SORT_ENGINE_ID,
   354 	STR_ENGINE_SORT_INTRO_DATE,
   407 	STR_ENGINE_SORT_INTRO_DATE,
   355 	STR_SORT_BY_DROPDOWN_NAME,
   408 	STR_SORT_BY_DROPDOWN_NAME,
   356 	STR_SORT_BY_RELIABILITY,
   409 	STR_SORT_BY_RELIABILITY,
       
   410 	STR_ENGINE_SORT_CARGO_CAPACITY,
   357 	INVALID_STRING_ID
   411 	INVALID_STRING_ID
   358 },{
   412 }, {
   359 	/* Ships */
   413 	/* Ships */
   360 	STR_ENGINE_SORT_ENGINE_ID,
   414 	STR_ENGINE_SORT_ENGINE_ID,
   361 	STR_ENGINE_SORT_INTRO_DATE,
   415 	STR_ENGINE_SORT_INTRO_DATE,
   362 	STR_SORT_BY_DROPDOWN_NAME,
   416 	STR_SORT_BY_DROPDOWN_NAME,
   363 	STR_SORT_BY_RELIABILITY,
   417 	STR_SORT_BY_RELIABILITY,
       
   418 	STR_ENGINE_SORT_CARGO_CAPACITY,
   364 	INVALID_STRING_ID
   419 	INVALID_STRING_ID
   365 },{
   420 }, {
   366 	/* Aircraft */
   421 	/* Aircraft */
   367 	STR_ENGINE_SORT_ENGINE_ID,
   422 	STR_ENGINE_SORT_ENGINE_ID,
   368 	STR_ENGINE_SORT_COST,
   423 	STR_ENGINE_SORT_COST,
   369 	STR_SORT_BY_MAX_SPEED,
   424 	STR_SORT_BY_MAX_SPEED,
   370 	STR_ENGINE_SORT_INTRO_DATE,
   425 	STR_ENGINE_SORT_INTRO_DATE,
   377 
   432 
   378 /* Draw rail wagon specific details */
   433 /* Draw rail wagon specific details */
   379 static int DrawRailWagonPurchaseInfo(int x, int y, EngineID engine_number, const RailVehicleInfo *rvi)
   434 static int DrawRailWagonPurchaseInfo(int x, int y, EngineID engine_number, const RailVehicleInfo *rvi)
   380 {
   435 {
   381 	/* Purchase cost */
   436 	/* Purchase cost */
   382 	SetDParam(0, (rvi->base_cost * _price.build_railwagon) >> 8);
   437 	SetDParam(0, (GetEngineProperty(engine_number, 0x17, rvi->base_cost) * _price.build_railwagon) >> 8);
   383 	DrawString(x, y, STR_PURCHASE_INFO_COST, 0);
   438 	DrawString(x, y, STR_PURCHASE_INFO_COST, 0);
   384 	y += 10;
   439 	y += 10;
   385 
   440 
   386 	/* Wagon weight - (including cargo) */
   441 	/* Wagon weight - (including cargo) */
   387 	SetDParam(0, rvi->weight);
   442 	uint weight = GetEngineProperty(engine_number, 0x16, rvi->weight);
   388 	SetDParam(1, (GetCargo(rvi->cargo_type)->weight * rvi->capacity >> 4) + rvi->weight);
   443 	SetDParam(0, weight);
       
   444 	SetDParam(1, (GetCargo(rvi->cargo_type)->weight * GetEngineProperty(engine_number, 0x14, rvi->capacity) >> 4) + weight);
   389 	DrawString(x, y, STR_PURCHASE_INFO_WEIGHT_CWEIGHT, 0);
   445 	DrawString(x, y, STR_PURCHASE_INFO_WEIGHT_CWEIGHT, 0);
   390 	y += 10;
   446 	y += 10;
   391 
   447 
   392 	/* Wagon speed limit, displayed if above zero */
   448 	/* Wagon speed limit, displayed if above zero */
   393 	if (rvi->max_speed > 0 && _patches.wagon_speed_limits) {
   449 	if (_patches.wagon_speed_limits) {
   394 		SetDParam(0, rvi->max_speed * 10 / 16);
   450 		uint max_speed = GetEngineProperty(engine_number, 0x09, rvi->max_speed);
   395 		DrawString(x,y, STR_PURCHASE_INFO_SPEED, 0);
   451 		if (max_speed > 0) {
   396 		y += 10;
   452 			SetDParam(0, max_speed * 10 / 16);
       
   453 			DrawString(x, y, STR_PURCHASE_INFO_SPEED, 0);
       
   454 			y += 10;
       
   455 		}
   397 	}
   456 	}
   398 	return y;
   457 	return y;
   399 }
   458 }
   400 
   459 
   401 /* Draw locomotive specific details */
   460 /* Draw locomotive specific details */
   402 static int DrawRailEnginePurchaseInfo(int x, int y, EngineID engine_number, const RailVehicleInfo *rvi)
   461 static int DrawRailEnginePurchaseInfo(int x, int y, EngineID engine_number, const RailVehicleInfo *rvi)
   403 {
   462 {
   404 	int multihead = (rvi->railveh_type == RAILVEH_MULTIHEAD ? 1 : 0);
   463 	int multihead = (rvi->railveh_type == RAILVEH_MULTIHEAD ? 1 : 0);
       
   464 	uint weight = GetEngineProperty(engine_number, 0x16, rvi->weight);
   405 
   465 
   406 	/* Purchase Cost - Engine weight */
   466 	/* Purchase Cost - Engine weight */
   407 	SetDParam(0, rvi->base_cost * (_price.build_railvehicle >> 3) >> 5);
   467 	SetDParam(0, GetEngineProperty(engine_number, 0x17, rvi->base_cost) * (_price.build_railvehicle >> 3) >> 5);
   408 	SetDParam(1, rvi->weight << multihead);
   468 	SetDParam(1, weight << multihead);
   409 	DrawString(x,y, STR_PURCHASE_INFO_COST_WEIGHT, 0);
   469 	DrawString(x, y, STR_PURCHASE_INFO_COST_WEIGHT, 0);
   410 	y += 10;
   470 	y += 10;
   411 
   471 
   412 	/* Max speed - Engine power */
   472 	/* Max speed - Engine power */
   413 	SetDParam(0, rvi->max_speed * 10 / 16);
   473 	SetDParam(0, GetEngineProperty(engine_number, 0x09, rvi->max_speed) * 10 / 16);
   414 	SetDParam(1, rvi->power << multihead);
   474 	SetDParam(1, GetEngineProperty(engine_number, 0x0B, rvi->power) << multihead);
   415 	DrawString(x,y, STR_PURCHASE_INFO_SPEED_POWER, 0);
   475 	DrawString(x, y, STR_PURCHASE_INFO_SPEED_POWER, 0);
   416 	y += 10;
   476 	y += 10;
   417 
   477 
   418 	/* Max tractive effort - not applicable if old acceleration or maglev */
   478 	/* Max tractive effort - not applicable if old acceleration or maglev */
   419 	if (_patches.realistic_acceleration && rvi->railtype != RAILTYPE_MAGLEV) {
   479 	if (_patches.realistic_acceleration && rvi->railtype != RAILTYPE_MAGLEV) {
   420 		SetDParam(0, ((rvi->weight << multihead) * 10 * rvi->tractive_effort) / 256);
   480 		SetDParam(0, ((weight << multihead) * 10 * GetEngineProperty(engine_number, 0x1F, rvi->tractive_effort)) / 256);
   421 		DrawString(x, y, STR_PURCHASE_INFO_MAX_TE, 0);
   481 		DrawString(x, y, STR_PURCHASE_INFO_MAX_TE, 0);
   422 		y += 10;
   482 		y += 10;
   423 	}
   483 	}
   424 
   484 
   425 	/* Running cost */
   485 	/* Running cost */
   426 	SetDParam(0, (rvi->running_cost_base * _price.running_rail[rvi->running_cost_class] >> 8) << multihead);
   486 	SetDParam(0, (GetEngineProperty(engine_number, 0x0D, rvi->running_cost_base) * _price.running_rail[rvi->running_cost_class] >> 8) << multihead);
   427 	DrawString(x,y, STR_PURCHASE_INFO_RUNNINGCOST, 0);
   487 	DrawString(x, y, STR_PURCHASE_INFO_RUNNINGCOST, 0);
   428 	y += 10;
   488 	y += 10;
   429 
   489 
   430 	/* Powered wagons power - Powered wagons extra weight */
   490 	/* Powered wagons power - Powered wagons extra weight */
   431 	if (rvi->pow_wag_power != 0) {
   491 	if (rvi->pow_wag_power != 0) {
   432 		SetDParam(0, rvi->pow_wag_power);
   492 		SetDParam(0, rvi->pow_wag_power);
   433 		SetDParam(1, rvi->pow_wag_weight);
   493 		SetDParam(1, rvi->pow_wag_weight);
   434 		DrawString(x,y, STR_PURCHASE_INFO_PWAGPOWER_PWAGWEIGHT, 0);
   494 		DrawString(x, y, STR_PURCHASE_INFO_PWAGPOWER_PWAGWEIGHT, 0);
   435 		y += 10;
   495 		y += 10;
   436 	};
   496 	};
   437 
   497 
   438 	return y;
   498 	return y;
   439 }
   499 }
   442 static int DrawRoadVehPurchaseInfo(int x, int y, EngineID engine_number, const RoadVehicleInfo *rvi)
   502 static int DrawRoadVehPurchaseInfo(int x, int y, EngineID engine_number, const RoadVehicleInfo *rvi)
   443 {
   503 {
   444 	bool refittable = (_engine_info[engine_number].refit_mask != 0);
   504 	bool refittable = (_engine_info[engine_number].refit_mask != 0);
   445 
   505 
   446 	/* Purchase cost - Max speed */
   506 	/* Purchase cost - Max speed */
   447 	SetDParam(0, rvi->base_cost * (_price.roadveh_base>>3)>>5);
   507 	SetDParam(0, GetEngineProperty(engine_number, 0x11, rvi->base_cost) * (_price.roadveh_base >> 3) >> 5);
   448 	SetDParam(1, rvi->max_speed * 10 / 32);
   508 	SetDParam(1, rvi->max_speed * 10 / 32);
   449 	DrawString(x, y, STR_PURCHASE_INFO_COST_SPEED, 0);
   509 	DrawString(x, y, STR_PURCHASE_INFO_COST_SPEED, 0);
   450 	y += 10;
   510 	y += 10;
   451 
   511 
   452 	/* Running cost */
   512 	/* Running cost */
   454 	DrawString(x, y, STR_PURCHASE_INFO_RUNNINGCOST, 0);
   514 	DrawString(x, y, STR_PURCHASE_INFO_RUNNINGCOST, 0);
   455 	y += 10;
   515 	y += 10;
   456 
   516 
   457 	/* Cargo type + capacity */
   517 	/* Cargo type + capacity */
   458 	SetDParam(0, rvi->cargo_type);
   518 	SetDParam(0, rvi->cargo_type);
   459 	SetDParam(1, rvi->capacity);
   519 	SetDParam(1, GetEngineProperty(engine_number, 0x0F, rvi->capacity));
   460 	SetDParam(2, refittable ? STR_9842_REFITTABLE : STR_EMPTY);
   520 	SetDParam(2, refittable ? STR_9842_REFITTABLE : STR_EMPTY);
   461 	DrawString(x, y, STR_PURCHASE_INFO_CAPACITY, 0);
   521 	DrawString(x, y, STR_PURCHASE_INFO_CAPACITY, 0);
   462 	y += 10;
   522 	y += 10;
   463 
   523 
   464 	return y;
   524 	return y;
   466 
   526 
   467 /* Draw ship specific details */
   527 /* Draw ship specific details */
   468 static int DrawShipPurchaseInfo(int x, int y, EngineID engine_number, const ShipVehicleInfo *svi)
   528 static int DrawShipPurchaseInfo(int x, int y, EngineID engine_number, const ShipVehicleInfo *svi)
   469 {
   529 {
   470 	/* Purchase cost - Max speed */
   530 	/* Purchase cost - Max speed */
   471 	SetDParam(0, svi->base_cost * (_price.ship_base>>3)>>5);
   531 	SetDParam(0, GetEngineProperty(engine_number, 0x0A, svi->base_cost) * (_price.ship_base >> 3) >> 5);
   472 	SetDParam(1, svi->max_speed * 10 / 32);
   532 	SetDParam(1, GetEngineProperty(engine_number, 0x0B, svi->max_speed) * 10 / 32);
   473 	DrawString(x,y, STR_PURCHASE_INFO_COST_SPEED, 0);
   533 	DrawString(x, y, STR_PURCHASE_INFO_COST_SPEED, 0);
   474 	y += 10;
   534 	y += 10;
   475 
   535 
   476 	/* Cargo type + capacity */
   536 	/* Cargo type + capacity */
   477 	SetDParam(0, svi->cargo_type);
   537 	SetDParam(0, svi->cargo_type);
   478 	SetDParam(1, svi->capacity);
   538 	SetDParam(1, GetEngineProperty(engine_number, 0x0D, svi->capacity));
   479 	SetDParam(2, svi->refittable ? STR_9842_REFITTABLE : STR_EMPTY);
   539 	SetDParam(2, svi->refittable ? STR_9842_REFITTABLE : STR_EMPTY);
   480 	DrawString(x,y, STR_PURCHASE_INFO_CAPACITY, 0);
   540 	DrawString(x, y, STR_PURCHASE_INFO_CAPACITY, 0);
   481 	y += 10;
   541 	y += 10;
   482 
   542 
   483 	/* Running cost */
   543 	/* Running cost */
   484 	SetDParam(0, svi->running_cost * _price.ship_running >> 8);
   544 	SetDParam(0, GetEngineProperty(engine_number, 0x0F, svi->running_cost) * _price.ship_running >> 8);
   485 	DrawString(x,y, STR_PURCHASE_INFO_RUNNINGCOST, 0);
   545 	DrawString(x, y, STR_PURCHASE_INFO_RUNNINGCOST, 0);
   486 	y += 10;
   546 	y += 10;
   487 
   547 
   488 	return y;
   548 	return y;
   489 }
   549 }
   490 
   550 
   492 static int DrawAircraftPurchaseInfo(int x, int y, EngineID engine_number, const AircraftVehicleInfo *avi)
   552 static int DrawAircraftPurchaseInfo(int x, int y, EngineID engine_number, const AircraftVehicleInfo *avi)
   493 {
   553 {
   494 	CargoID cargo;
   554 	CargoID cargo;
   495 
   555 
   496 	/* Purchase cost - Max speed */
   556 	/* Purchase cost - Max speed */
   497 	SetDParam(0, avi->base_cost * (_price.aircraft_base>>3)>>5);
   557 	SetDParam(0, GetEngineProperty(engine_number, 0x0B, avi->base_cost) * (_price.aircraft_base >> 3) >> 5);
   498 	SetDParam(1, avi->max_speed * 10 / 16);
   558 	SetDParam(1, avi->max_speed * 10 / 16);
   499 	DrawString(x, y, STR_PURCHASE_INFO_COST_SPEED, 0);
   559 	DrawString(x, y, STR_PURCHASE_INFO_COST_SPEED, 0);
   500 	y += 10;
   560 	y += 10;
   501 
   561 
   502 	/* Cargo capacity */
   562 	/* Cargo capacity */
   514 		DrawString(x, y, STR_PURCHASE_INFO_CAPACITY, 0);
   574 		DrawString(x, y, STR_PURCHASE_INFO_CAPACITY, 0);
   515 	}
   575 	}
   516 	y += 10;
   576 	y += 10;
   517 
   577 
   518 	/* Running cost */
   578 	/* Running cost */
   519 	SetDParam(0, avi->running_cost * _price.aircraft_running >> 8);
   579 	SetDParam(0, GetEngineProperty(engine_number, 0x0E, avi->running_cost) * _price.aircraft_running >> 8);
   520 	DrawString(x, y, STR_PURCHASE_INFO_RUNNINGCOST, 0);
   580 	DrawString(x, y, STR_PURCHASE_INFO_RUNNINGCOST, 0);
   521 	y += 10;
   581 	y += 10;
   522 
   582 
   523 	return y;
   583 	return y;
   524 }
   584 }
   536 	YearMonthDay ymd;
   596 	YearMonthDay ymd;
   537 	ConvertDateToYMD(e->intro_date, &ymd);
   597 	ConvertDateToYMD(e->intro_date, &ymd);
   538 	bool refitable = false;
   598 	bool refitable = false;
   539 
   599 
   540 	switch (e->type) {
   600 	switch (e->type) {
       
   601 		default: NOT_REACHED();
   541 		case VEH_TRAIN: {
   602 		case VEH_TRAIN: {
   542 			const RailVehicleInfo *rvi = RailVehInfo(engine_number);
   603 			const RailVehicleInfo *rvi = RailVehInfo(engine_number);
   543 
   604 			uint capacity = GetEngineProperty(engine_number, 0x14, rvi->capacity);
   544 			refitable = (EngInfo(engine_number)->refit_mask != 0) && (rvi->capacity > 0);
   605 
       
   606 			refitable = (EngInfo(engine_number)->refit_mask != 0) && (capacity > 0);
   545 
   607 
   546 			if (rvi->railveh_type == RAILVEH_WAGON) {
   608 			if (rvi->railveh_type == RAILVEH_WAGON) {
   547 				y = DrawRailWagonPurchaseInfo(x, y, engine_number, rvi);
   609 				y = DrawRailWagonPurchaseInfo(x, y, engine_number, rvi);
   548 			} else {
   610 			} else {
   549 				y = DrawRailEnginePurchaseInfo(x, y, engine_number, rvi);
   611 				y = DrawRailEnginePurchaseInfo(x, y, engine_number, rvi);
   555 				SetDParam(2, STR_EMPTY);
   617 				SetDParam(2, STR_EMPTY);
   556 			} else {
   618 			} else {
   557 				int multihead = (rvi->railveh_type == RAILVEH_MULTIHEAD ? 1 : 0);
   619 				int multihead = (rvi->railveh_type == RAILVEH_MULTIHEAD ? 1 : 0);
   558 
   620 
   559 				SetDParam(0, rvi->cargo_type);
   621 				SetDParam(0, rvi->cargo_type);
   560 				SetDParam(1, (rvi->capacity * (CountArticulatedParts(engine_number) + 1)) << multihead);
   622 				SetDParam(1, (capacity * (CountArticulatedParts(engine_number) + 1)) << multihead);
   561 				SetDParam(2, refitable ? STR_9842_REFITTABLE : STR_EMPTY);
   623 				SetDParam(2, refitable ? STR_9842_REFITTABLE : STR_EMPTY);
   562 			}
   624 			}
   563 			DrawString(x,y, STR_PURCHASE_INFO_CAPACITY, 0);
   625 			DrawString(x, y, STR_PURCHASE_INFO_CAPACITY, 0);
   564 			y += 10;
   626 			y += 10;
   565 		}
   627 		}
   566 			break;
   628 			break;
   567 		case VEH_ROAD:
   629 		case VEH_ROAD:
   568 			y = DrawRoadVehPurchaseInfo(x, y, engine_number, RoadVehInfo(engine_number));
   630 			y = DrawRoadVehPurchaseInfo(x, y, engine_number, RoadVehInfo(engine_number));
   656 
   718 
   657 	sel_id = INVALID_ENGINE;
   719 	sel_id = INVALID_ENGINE;
   658 
   720 
   659 	for (eid = ROAD_ENGINES_INDEX; eid < ROAD_ENGINES_INDEX + NUM_ROAD_ENGINES; eid++) {
   721 	for (eid = ROAD_ENGINES_INDEX; eid < ROAD_ENGINES_INDEX + NUM_ROAD_ENGINES; eid++) {
   660 		if (!IsEngineBuildable(eid, VEH_ROAD, _local_player)) continue;
   722 		if (!IsEngineBuildable(eid, VEH_ROAD, _local_player)) continue;
       
   723 		if (!HASBIT(bv->filter.roadtypes, HASBIT(EngInfo(eid)->misc_flags, EF_ROAD_TRAM) ? ROADTYPE_TRAM : ROADTYPE_ROAD)) continue;
   661 		EngList_Add(&bv->eng_list, eid);
   724 		EngList_Add(&bv->eng_list, eid);
   662 
   725 
   663 		if (eid == bv->sel_engine) sel_id = eid;
   726 		if (eid == bv->sel_engine) sel_id = eid;
   664 	}
   727 	}
   665 	bv->sel_engine = sel_id;
   728 	bv->sel_engine = sel_id;
   712 static void GenerateBuildList(Window *w)
   775 static void GenerateBuildList(Window *w)
   713 {
   776 {
   714 	buildvehicle_d *bv = &WP(w, buildvehicle_d);
   777 	buildvehicle_d *bv = &WP(w, buildvehicle_d);
   715 
   778 
   716 	switch (bv->vehicle_type) {
   779 	switch (bv->vehicle_type) {
       
   780 		default: NOT_REACHED();
   717 		case VEH_TRAIN:
   781 		case VEH_TRAIN:
   718 			GenerateBuildTrainList(w);
   782 			GenerateBuildTrainList(w);
   719 			return; // trains should not reach the last sorting
   783 			return; // trains should not reach the last sorting
   720 		case VEH_ROAD:
   784 		case VEH_ROAD:
   721 			GenerateBuildRoadVehList(w);
   785 			GenerateBuildRoadVehList(w);
   749  * @param min where to start in the list
   813  * @param min where to start in the list
   750  * @param max where in the list to end
   814  * @param max where in the list to end
   751  * @param selected_id what engine to highlight as selected, if any
   815  * @param selected_id what engine to highlight as selected, if any
   752  * @param show_count Display the number of vehicles (used by autoreplace)
   816  * @param show_count Display the number of vehicles (used by autoreplace)
   753  */
   817  */
   754 void DrawEngineList(byte type, int x, int y, const EngineList eng_list, uint16 min, uint16 max, EngineID selected_id, bool show_count)
   818 void DrawEngineList(VehicleType type, int x, int y, const EngineList eng_list, uint16 min, uint16 max, EngineID selected_id, bool show_count, GroupID selected_group)
   755 {
   819 {
   756 	byte step_size = GetVehicleListHeight(type);
   820 	byte step_size = GetVehicleListHeight(type);
   757 	byte x_offset = 0;
   821 	byte x_offset = 0;
   758 	byte y_offset = 0;
   822 	byte y_offset = 0;
   759 	Player *p = GetPlayer(_local_player);
   823 	Player *p = GetPlayer(_local_player);
   785 		default: NOT_REACHED();
   849 		default: NOT_REACHED();
   786 	}
   850 	}
   787 
   851 
   788 	for (; min < max; min++, y += step_size) {
   852 	for (; min < max; min++, y += step_size) {
   789 		const EngineID engine = eng_list[min];
   853 		const EngineID engine = eng_list[min];
       
   854 		const uint num_engines = IsDefaultGroupID(selected_group) ? p->num_engines[engine] : GetGroup(selected_group)->num_engines[engine];
   790 
   855 
   791 		DrawString(x + x_offset, y, GetCustomEngineName(engine), engine == selected_id ? 0xC : 0x10);
   856 		DrawString(x + x_offset, y, GetCustomEngineName(engine), engine == selected_id ? 0xC : 0x10);
   792 		DrawVehicleEngine(type, x, y + y_offset, engine, (show_count && p->num_engines[engine] == 0) ? PALETTE_CRASH : GetEnginePalette(engine, _local_player));
   857 		DrawVehicleEngine(type, x, y + y_offset, engine, (show_count && num_engines == 0) ? PALETTE_CRASH : GetEnginePalette(engine, _local_player));
   793 		if (show_count) {
   858 		if (show_count) {
   794 			SetDParam(0, p->num_engines[engine]);
   859 			SetDParam(0, num_engines);
   795 			DrawStringRightAligned(213, y + (GetVehicleListHeight(type) == 14 ? 3 : 8), STR_TINY_BLACK, 0);
   860 			DrawStringRightAligned(213, y + (GetVehicleListHeight(type) == 14 ? 3 : 8), STR_TINY_BLACK, 0);
   796 		}
   861 		}
   797 	}
   862 	}
   798 }
   863 }
   799 
   864 
   823 
   888 
   824 	SetVScrollCount(w, EngList_Count(&bv->eng_list));
   889 	SetVScrollCount(w, EngList_Count(&bv->eng_list));
   825 	SetDParam(0, bv->filter.railtype + STR_881C_NEW_RAIL_VEHICLES); // This should only affect rail vehicles
   890 	SetDParam(0, bv->filter.railtype + STR_881C_NEW_RAIL_VEHICLES); // This should only affect rail vehicles
   826 	DrawWindowWidgets(w);
   891 	DrawWindowWidgets(w);
   827 
   892 
   828 	DrawEngineList(bv->vehicle_type, 2, 27, bv->eng_list, w->vscroll.pos, max, bv->sel_engine, false);
   893 	DrawEngineList(bv->vehicle_type, 2, 27, bv->eng_list, w->vscroll.pos, max, bv->sel_engine, false, DEFAULT_GROUP);
   829 
   894 
   830 	if (bv->sel_engine != INVALID_ENGINE) {
   895 	if (bv->sel_engine != INVALID_ENGINE) {
   831 		const Widget *wi = &w->widget[BUILD_VEHICLE_WIDGET_PANEL];
   896 		const Widget *wi = &w->widget[BUILD_VEHICLE_WIDGET_PANEL];
   832 		int text_end = DrawVehiclePurchaseInfo(2, wi->top + 1, wi->right - wi->left - 2, bv->sel_engine);
   897 		int text_end = DrawVehiclePurchaseInfo(2, wi->top + 1, wi->right - wi->left - 2, bv->sel_engine);
   833 
   898 
   864 
   929 
   865 		case BUILD_VEHICLE_WIDGET_BUILD: {
   930 		case BUILD_VEHICLE_WIDGET_BUILD: {
   866 			EngineID sel_eng = bv->sel_engine;
   931 			EngineID sel_eng = bv->sel_engine;
   867 			if (sel_eng != INVALID_ENGINE) {
   932 			if (sel_eng != INVALID_ENGINE) {
   868 				switch (bv->vehicle_type) {
   933 				switch (bv->vehicle_type) {
       
   934 					default: NOT_REACHED();
   869 					case VEH_TRAIN:
   935 					case VEH_TRAIN:
   870 						DoCommandP(w->window_number, sel_eng, 0, (RailVehInfo(sel_eng)->railveh_type == RAILVEH_WAGON) ? CcBuildWagon : CcBuildLoco,
   936 						DoCommandP(w->window_number, sel_eng, 0, (RailVehInfo(sel_eng)->railveh_type == RAILVEH_WAGON) ? CcBuildWagon : CcBuildLoco,
   871 								   CMD_BUILD_RAIL_VEHICLE | CMD_MSG(STR_882B_CAN_T_BUILD_RAILROAD_VEHICLE));
   937 								   CMD_BUILD_RAIL_VEHICLE | CMD_MSG(STR_882B_CAN_T_BUILD_RAILROAD_VEHICLE));
   872 						break;
   938 						break;
   873 					case VEH_ROAD:
   939 					case VEH_ROAD:
   889 			if (sel_eng != INVALID_ENGINE) {
   955 			if (sel_eng != INVALID_ENGINE) {
   890 				StringID str = STR_NULL;
   956 				StringID str = STR_NULL;
   891 
   957 
   892 				bv->rename_engine = sel_eng;
   958 				bv->rename_engine = sel_eng;
   893 				switch (bv->vehicle_type) {
   959 				switch (bv->vehicle_type) {
       
   960 					default: NOT_REACHED();
   894 					case VEH_TRAIN:    str = STR_886A_RENAME_TRAIN_VEHICLE_TYPE; break;
   961 					case VEH_TRAIN:    str = STR_886A_RENAME_TRAIN_VEHICLE_TYPE; break;
   895 					case VEH_ROAD:     str = STR_9036_RENAME_ROAD_VEHICLE_TYPE;  break;
   962 					case VEH_ROAD:     str = STR_9036_RENAME_ROAD_VEHICLE_TYPE;  break;
   896 					case VEH_SHIP:     str = STR_9838_RENAME_SHIP_TYPE;          break;
   963 					case VEH_SHIP:     str = STR_9838_RENAME_SHIP_TYPE;          break;
   897 					case VEH_AIRCRAFT: str = STR_A039_RENAME_AIRCRAFT_TYPE;      break;
   964 					case VEH_AIRCRAFT: str = STR_A039_RENAME_AIRCRAFT_TYPE;      break;
   898 				}
   965 				}
   932 		case WE_ON_EDIT_TEXT: {
   999 		case WE_ON_EDIT_TEXT: {
   933 			if (e->we.edittext.str[0] != '\0') {
  1000 			if (e->we.edittext.str[0] != '\0') {
   934 				StringID str = STR_NULL;
  1001 				StringID str = STR_NULL;
   935 				_cmd_text = e->we.edittext.str;
  1002 				_cmd_text = e->we.edittext.str;
   936 				switch (bv->vehicle_type) {
  1003 				switch (bv->vehicle_type) {
       
  1004 					default: NOT_REACHED();
   937 					case VEH_TRAIN:    str = STR_886B_CAN_T_RENAME_TRAIN_VEHICLE; break;
  1005 					case VEH_TRAIN:    str = STR_886B_CAN_T_RENAME_TRAIN_VEHICLE; break;
   938 					case VEH_ROAD:     str = STR_9037_CAN_T_RENAME_ROAD_VEHICLE;  break;
  1006 					case VEH_ROAD:     str = STR_9037_CAN_T_RENAME_ROAD_VEHICLE;  break;
   939 					case VEH_SHIP:     str = STR_9839_CAN_T_RENAME_SHIP_TYPE;     break;
  1007 					case VEH_SHIP:     str = STR_9839_CAN_T_RENAME_SHIP_TYPE;     break;
   940 					case VEH_AIRCRAFT: str = STR_A03A_CAN_T_RENAME_AIRCRAFT_TYPE; break;
  1008 					case VEH_AIRCRAFT: str = STR_A03A_CAN_T_RENAME_AIRCRAFT_TYPE; break;
   941 				}
  1009 				}
   969 	WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS | WDF_RESIZABLE,
  1037 	WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS | WDF_RESIZABLE,
   970 	_build_vehicle_widgets,
  1038 	_build_vehicle_widgets,
   971 	NewVehicleWndProc
  1039 	NewVehicleWndProc
   972 };
  1040 };
   973 
  1041 
   974 void ShowBuildVehicleWindow(TileIndex tile, byte type)
  1042 void ShowBuildVehicleWindow(TileIndex tile, VehicleType type)
   975 {
  1043 {
   976 	buildvehicle_d *bv;
  1044 	buildvehicle_d *bv;
   977 	Window *w;
  1045 	Window *w;
   978 
  1046 
   979 	assert(IsPlayerBuildableVehicleType(type));
  1047 	assert(IsPlayerBuildableVehicleType(type));
   998 
  1066 
   999 	bv->sort_criteria         = _last_sort_criteria[type];
  1067 	bv->sort_criteria         = _last_sort_criteria[type];
  1000 	bv->descending_sort_order = _last_sort_order[type];
  1068 	bv->descending_sort_order = _last_sort_order[type];
  1001 
  1069 
  1002 	switch (type) {
  1070 	switch (type) {
       
  1071 		default: NOT_REACHED();
  1003 		case VEH_TRAIN:
  1072 		case VEH_TRAIN:
  1004 			WP(w,buildvehicle_d).filter.railtype = (tile == 0) ? RAILTYPE_END : GetRailType(tile);
  1073 			WP(w, buildvehicle_d).filter.railtype = (tile == 0) ? RAILTYPE_END : GetRailType(tile);
  1005 			ResizeWindow(w, 0, 16);
  1074 			ResizeWindow(w, 0, 16);
  1006 			break;
  1075 			break;
  1007 		case VEH_ROAD:
  1076 		case VEH_ROAD:
       
  1077 			WP(w, buildvehicle_d).filter.roadtypes = (tile == 0) ? ROADTYPES_ALL : GetRoadTypes(tile);
  1008 			ResizeWindow(w, 0, 16);
  1078 			ResizeWindow(w, 0, 16);
  1009 		case VEH_SHIP:
  1079 		case VEH_SHIP:
  1010 			break;
  1080 			break;
  1011 		case VEH_AIRCRAFT:
  1081 		case VEH_AIRCRAFT:
  1012 			bv->filter.flags =
  1082 			bv->filter.flags =