src/vehicle.cpp
branchnoai
changeset 9722 ebf0ece7d8f6
parent 9718 f82a4facea8b
child 9723 eee46cb39750
equal deleted inserted replaced
9721:9a27928bcd5e 9722:ebf0ece7d8f6
   232 	}
   232 	}
   233 
   233 
   234 	FOR_ALL_VEHICLES(v) {
   234 	FOR_ALL_VEHICLES(v) {
   235 		switch (v->type) {
   235 		switch (v->type) {
   236 			case VEH_ROAD:
   236 			case VEH_ROAD:
   237 				v->u.road.roadtype = HASBIT(EngInfo(v->engine_type)->misc_flags, EF_ROAD_TRAM) ? ROADTYPE_TRAM : ROADTYPE_ROAD;
   237 				v->u.road.roadtype = HasBit(EngInfo(v->engine_type)->misc_flags, EF_ROAD_TRAM) ? ROADTYPE_TRAM : ROADTYPE_ROAD;
   238 				v->u.road.compatible_roadtypes = RoadTypeToRoadTypes(v->u.road.roadtype);
   238 				v->u.road.compatible_roadtypes = RoadTypeToRoadTypes(v->u.road.roadtype);
   239 				/* FALL THROUGH */
   239 				/* FALL THROUGH */
   240 			case VEH_TRAIN:
   240 			case VEH_TRAIN:
   241 			case VEH_SHIP:
   241 			case VEH_SHIP:
   242 				v->cur_image = v->GetImage(v->direction);
   242 				v->cur_image = v->GetImage(v->direction);
   272 	this->type               = VEH_INVALID;
   272 	this->type               = VEH_INVALID;
   273 	this->left_coord         = INVALID_COORD;
   273 	this->left_coord         = INVALID_COORD;
   274 	this->group_id           = DEFAULT_GROUP;
   274 	this->group_id           = DEFAULT_GROUP;
   275 	this->fill_percent_te_id = INVALID_TE_ID;
   275 	this->fill_percent_te_id = INVALID_TE_ID;
   276 	this->first              = this;
   276 	this->first              = this;
       
   277 	this->colormap           = PAL_NONE;
   277 }
   278 }
   278 
   279 
   279 /**
   280 /**
   280  * Get a value for a vehicle's random_bits.
   281  * Get a value for a vehicle's random_bits.
   281  * @return A random value from 0 to 255.
   282  * @return A random value from 0 to 255.
   455 	FOR_ALL_VEHICLES(v) { v->old_new_hash = NULL; }
   456 	FOR_ALL_VEHICLES(v) { v->old_new_hash = NULL; }
   456 	memset(_vehicle_position_hash, 0, sizeof(_vehicle_position_hash));
   457 	memset(_vehicle_position_hash, 0, sizeof(_vehicle_position_hash));
   457 	memset(_new_vehicle_position_hash, 0, sizeof(_new_vehicle_position_hash));
   458 	memset(_new_vehicle_position_hash, 0, sizeof(_new_vehicle_position_hash));
   458 }
   459 }
   459 
   460 
       
   461 void ResetVehicleColorMap()
       
   462 {
       
   463 	Vehicle *v;
       
   464 	FOR_ALL_VEHICLES(v) { v->colormap = PAL_NONE; }
       
   465 }
       
   466 
   460 void InitializeVehicles()
   467 void InitializeVehicles()
   461 {
   468 {
   462 	_Vehicle_pool.CleanPool();
   469 	_Vehicle_pool.CleanPool();
   463 	_Vehicle_pool.AddBlockToPool();
   470 	_Vehicle_pool.AddBlockToPool();
   464 
   471 
   527 	 *  destroy vehicle, which on his turn can remove any
   534 	 *  destroy vehicle, which on his turn can remove any
   528 	 *  other artic parts. */
   535 	 *  other artic parts. */
   529 	if ((this->type == VEH_TRAIN && EngineHasArticPart(this)) || (this->type == VEH_ROAD && RoadVehHasArticPart(this))) {
   536 	if ((this->type == VEH_TRAIN && EngineHasArticPart(this)) || (this->type == VEH_ROAD && RoadVehHasArticPart(this))) {
   530 		delete this->Next();
   537 		delete this->Next();
   531 	}
   538 	}
       
   539 
       
   540 	Window **wp;
       
   541 	FOR_ALL_WINDOWS(wp) {
       
   542 		Window *w = *wp;
       
   543 		if (w->viewport != NULL && WP(w, vp_d).follow_vehicle == this->index) {
       
   544 			ScrollMainWindowTo(this->x_pos, this->y_pos); // lock the main view on the vehicle's last position
       
   545 			WP(w, vp_d).follow_vehicle = INVALID_VEHICLE;
       
   546 		}
       
   547 	}
   532 }
   548 }
   533 
   549 
   534 Vehicle::~Vehicle()
   550 Vehicle::~Vehicle()
   535 {
   551 {
   536 	DeleteName(this->string_id);
   552 	DeleteName(this->string_id);
   569  * @param *v vehicle to add
   585  * @param *v vehicle to add
   570  */
   586  */
   571 void VehicleEnteredDepotThisTick(Vehicle *v)
   587 void VehicleEnteredDepotThisTick(Vehicle *v)
   572 {
   588 {
   573 	/* we need to set v->leave_depot_instantly as we have no control of it's contents at this time */
   589 	/* we need to set v->leave_depot_instantly as we have no control of it's contents at this time */
   574 	if (HASBIT(v->current_order.flags, OFB_HALT_IN_DEPOT) && !HASBIT(v->current_order.flags, OFB_PART_OF_ORDERS) && v->current_order.type == OT_GOTO_DEPOT) {
   590 	if (HasBit(v->current_order.flags, OFB_HALT_IN_DEPOT) && !HasBit(v->current_order.flags, OFB_PART_OF_ORDERS) && v->current_order.type == OT_GOTO_DEPOT) {
   575 		/* we keep the vehicle in the depot since the user ordered it to stay */
   591 		/* we keep the vehicle in the depot since the user ordered it to stay */
   576 		v->leave_depot_instantly = false;
   592 		v->leave_depot_instantly = false;
   577 	} else {
   593 	} else {
   578 		/* the vehicle do not plan on stopping in the depot, so we stop it to ensure that it will not reserve the path
   594 		/* the vehicle do not plan on stopping in the depot, so we stop it to ensure that it will not reserve the path
   579 		 * out of the depot before we might autoreplace it to a different engine. The new engine would not own the reserved path
   595 		 * out of the depot before we might autoreplace it to a different engine. The new engine would not own the reserved path
   637  * @param cid_to check refit to this cargo-type
   653  * @param cid_to check refit to this cargo-type
   638  * @return true if it is possible, false otherwise
   654  * @return true if it is possible, false otherwise
   639  */
   655  */
   640 bool CanRefitTo(EngineID engine_type, CargoID cid_to)
   656 bool CanRefitTo(EngineID engine_type, CargoID cid_to)
   641 {
   657 {
   642 	return HASBIT(EngInfo(engine_type)->refit_mask, cid_to);
   658 	return HasBit(EngInfo(engine_type)->refit_mask, cid_to);
   643 }
   659 }
   644 
   660 
   645 /** Find the first cargo type that an engine can be refitted to.
   661 /** Find the first cargo type that an engine can be refitted to.
   646  * @param engine_type Which engine to find cargo for.
   662  * @param engine_type Which engine to find cargo for.
   647  * @return A climate dependent cargo type. CT_INVALID is returned if not refittable.
   663  * @return A climate dependent cargo type. CT_INVALID is returned if not refittable.
   650 {
   666 {
   651 	uint32 refit_mask = EngInfo(engine_type)->refit_mask;
   667 	uint32 refit_mask = EngInfo(engine_type)->refit_mask;
   652 
   668 
   653 	if (refit_mask != 0) {
   669 	if (refit_mask != 0) {
   654 		for (CargoID cid = 0; cid < NUM_CARGO; cid++) {
   670 		for (CargoID cid = 0; cid < NUM_CARGO; cid++) {
   655 			if (HASBIT(refit_mask, cid)) return cid;
   671 			if (HasBit(refit_mask, cid)) return cid;
   656 		}
   672 		}
   657 	}
   673 	}
   658 
   674 
   659 	return CT_INVALID;
   675 	return CT_INVALID;
   660 }
   676 }
  1334 	return v;
  1350 	return v;
  1335 }
  1351 }
  1336 
  1352 
  1337 Vehicle *CreateEffectVehicleAbove(int x, int y, int z, EffectVehicle type)
  1353 Vehicle *CreateEffectVehicleAbove(int x, int y, int z, EffectVehicle type)
  1338 {
  1354 {
  1339 	int safe_x = clamp(x, 0, MapMaxX() * TILE_SIZE);
  1355 	int safe_x = Clamp(x, 0, MapMaxX() * TILE_SIZE);
  1340 	int safe_y = clamp(y, 0, MapMaxY() * TILE_SIZE);
  1356 	int safe_y = Clamp(y, 0, MapMaxY() * TILE_SIZE);
  1341 	return CreateEffectVehicle(x, y, GetSlopeZ(safe_x, safe_y) + z, type);
  1357 	return CreateEffectVehicle(x, y, GetSlopeZ(safe_x, safe_y) + z, type);
  1342 }
  1358 }
  1343 
  1359 
  1344 Vehicle *CreateEffectVehicleRel(const Vehicle *v, int x, int y, int z, EffectVehicle type)
  1360 Vehicle *CreateEffectVehicleRel(const Vehicle *v, int x, int y, int z, EffectVehicle type)
  1345 {
  1361 {
  1367 		if ((v->vehstatus & (VS_HIDDEN|VS_UNCLICKABLE)) == 0 &&
  1383 		if ((v->vehstatus & (VS_HIDDEN|VS_UNCLICKABLE)) == 0 &&
  1368 				x >= v->left_coord && x <= v->right_coord &&
  1384 				x >= v->left_coord && x <= v->right_coord &&
  1369 				y >= v->top_coord && y <= v->bottom_coord) {
  1385 				y >= v->top_coord && y <= v->bottom_coord) {
  1370 
  1386 
  1371 			dist = max(
  1387 			dist = max(
  1372 				myabs( ((v->left_coord + v->right_coord)>>1) - x ),
  1388 				abs( ((v->left_coord + v->right_coord)>>1) - x ),
  1373 				myabs( ((v->top_coord + v->bottom_coord)>>1) - y )
  1389 				abs( ((v->top_coord + v->bottom_coord)>>1) - y )
  1374 			);
  1390 			);
  1375 
  1391 
  1376 			if (dist < best_dist) {
  1392 			if (dist < best_dist) {
  1377 				found = v;
  1393 				found = v;
  1378 				best_dist = dist;
  1394 				best_dist = dist;
  1381 	}
  1397 	}
  1382 
  1398 
  1383 	return found;
  1399 	return found;
  1384 }
  1400 }
  1385 
  1401 
       
  1402 void CheckVehicle32Day(Vehicle *v)
       
  1403 {
       
  1404 	if ((v->day_counter & 0x1F) != 0) return;
       
  1405 
       
  1406 	uint16 callback = GetVehicleCallback(CBID_VEHICLE_32DAY_CALLBACK, 0, 0, v->engine_type, v);
       
  1407 	if (callback == CALLBACK_FAILED) return;
       
  1408 	if (HasBit(callback, 0)) TriggerVehicle(v, VEHICLE_TRIGGER_CALLBACK_32); // Trigger vehicle trigger 10
       
  1409 	if (HasBit(callback, 1)) v->colormap = PAL_NONE;                         // Update colormap via callback 2D
       
  1410 }
  1386 
  1411 
  1387 void DecreaseVehicleValue(Vehicle *v)
  1412 void DecreaseVehicleValue(Vehicle *v)
  1388 {
  1413 {
  1389 	v->value -= v->value >> 8;
  1414 	v->value -= v->value >> 8;
  1390 	InvalidateWindow(WC_VEHICLE_DETAILS, v->index);
  1415 	InvalidateWindow(WC_VEHICLE_DETAILS, v->index);
  1496 	uint16 engine_count = 0;
  1521 	uint16 engine_count = 0;
  1497 	CommandCost return_value = CMD_ERROR;
  1522 	CommandCost return_value = CMD_ERROR;
  1498 	uint i;
  1523 	uint i;
  1499 	uint stop_command;
  1524 	uint stop_command;
  1500 	VehicleType vehicle_type = (VehicleType)GB(p2, 0, 5);
  1525 	VehicleType vehicle_type = (VehicleType)GB(p2, 0, 5);
  1501 	bool start_stop = HASBIT(p2, 5);
  1526 	bool start_stop = HasBit(p2, 5);
  1502 	bool vehicle_list_window = HASBIT(p2, 6);
  1527 	bool vehicle_list_window = HasBit(p2, 6);
  1503 
  1528 
  1504 	switch (vehicle_type) {
  1529 	switch (vehicle_type) {
  1505 		case VEH_TRAIN:    stop_command = CMD_START_STOP_TRAIN;    break;
  1530 		case VEH_TRAIN:    stop_command = CMD_START_STOP_TRAIN;    break;
  1506 		case VEH_ROAD:     stop_command = CMD_START_STOP_ROADVEH;  break;
  1531 		case VEH_ROAD:     stop_command = CMD_START_STOP_ROADVEH;  break;
  1507 		case VEH_SHIP:     stop_command = CMD_START_STOP_SHIP;     break;
  1532 		case VEH_SHIP:     stop_command = CMD_START_STOP_SHIP;     break;
  1727 		total_cost.AddCost(cost);
  1752 		total_cost.AddCost(cost);
  1728 
  1753 
  1729 		if (flags & DC_EXEC) {
  1754 		if (flags & DC_EXEC) {
  1730 			w = GetVehicle(_new_vehicle_id);
  1755 			w = GetVehicle(_new_vehicle_id);
  1731 
  1756 
  1732 			if (v->type == VEH_TRAIN && HASBIT(v->u.rail.flags, VRF_REVERSE_DIRECTION)) {
  1757 			if (v->type == VEH_TRAIN && HasBit(v->u.rail.flags, VRF_REVERSE_DIRECTION)) {
  1733 				SETBIT(w->u.rail.flags, VRF_REVERSE_DIRECTION);
  1758 				SetBit(w->u.rail.flags, VRF_REVERSE_DIRECTION);
  1734 			}
  1759 			}
  1735 
  1760 
  1736 			if (v->type == VEH_TRAIN && !IsFrontEngine(v)) {
  1761 			if (v->type == VEH_TRAIN && !IsFrontEngine(v)) {
  1737 				/* this s a train car
  1762 				/* this s a train car
  1738 				 * add this unit to the end of the train */
  1763 				 * add this unit to the end of the train */
  1743 					DoCommand(w_front->tile, w_front->index, 1, flags, GetCmdSellVeh(w_front));
  1768 					DoCommand(w_front->tile, w_front->index, 1, flags, GetCmdSellVeh(w_front));
  1744 					DoCommand(w_front->tile, w->index,       1, flags, GetCmdSellVeh(w));
  1769 					DoCommand(w_front->tile, w->index,       1, flags, GetCmdSellVeh(w));
  1745 					return result; // return error and the message returned from CMD_MOVE_RAIL_VEHICLE
  1770 					return result; // return error and the message returned from CMD_MOVE_RAIL_VEHICLE
  1746 				}
  1771 				}
  1747 			} else {
  1772 			} else {
  1748 				/* this is a front engine or not a train. It need orders */
  1773 				/* this is a front engine or not a train. */
  1749 				w_front = w;
  1774 				w_front = w;
  1750 				w->service_interval = v->service_interval;
  1775 				w->service_interval = v->service_interval;
  1751 				DoCommand(0, (v->index << 16) | w->index, p2 & 1 ? CO_SHARE : CO_COPY, flags, CMD_CLONE_ORDER);
       
  1752 			}
  1776 			}
  1753 			w_rear = w; // trains needs to know the last car in the train, so they can add more in next loop
  1777 			w_rear = w; // trains needs to know the last car in the train, so they can add more in next loop
  1754 		}
  1778 		}
  1755 	} while (v->type == VEH_TRAIN && (v = GetNextVehicle(v)) != NULL);
  1779 	} while (v->type == VEH_TRAIN && (v = GetNextVehicle(v)) != NULL);
  1756 
  1780 
  1778 	do {
  1802 	do {
  1779 		do {
  1803 		do {
  1780 			if (flags & DC_EXEC) {
  1804 			if (flags & DC_EXEC) {
  1781 				assert(w != NULL);
  1805 				assert(w != NULL);
  1782 
  1806 
  1783 				if (w->cargo_type != v->cargo_type || w->cargo_subtype != v->cargo_type) {
  1807 				if (w->cargo_type != v->cargo_type || w->cargo_subtype != v->cargo_subtype) {
  1784 					cost = DoCommand(0, w->index, v->cargo_type | (v->cargo_subtype << 8) | 1U << 16 , flags, GetCmdRefitVeh(v));
  1808 					cost = DoCommand(0, w->index, v->cargo_type | (v->cargo_subtype << 8) | 1U << 16 , flags, GetCmdRefitVeh(v));
  1785 					if (CmdSucceeded(cost)) total_cost.AddCost(cost);
  1809 					if (CmdSucceeded(cost)) total_cost.AddCost(cost);
  1786 				}
  1810 				}
  1787 
  1811 
  1788 				if (w->type == VEH_TRAIN && EngineHasArticPart(w)) {
  1812 				if (w->type == VEH_TRAIN && EngineHasArticPart(w)) {
  1809 			}
  1833 			}
  1810 		} while (v != NULL);
  1834 		} while (v != NULL);
  1811 
  1835 
  1812 		if ((flags & DC_EXEC) && v->type == VEH_TRAIN) w = GetNextVehicle(w);
  1836 		if ((flags & DC_EXEC) && v->type == VEH_TRAIN) w = GetNextVehicle(w);
  1813 	} while (v->type == VEH_TRAIN && (v = GetNextVehicle(v)) != NULL);
  1837 	} while (v->type == VEH_TRAIN && (v = GetNextVehicle(v)) != NULL);
       
  1838 
       
  1839 	if (flags & DC_EXEC) {
       
  1840 		/*
       
  1841 		 * Set the orders of the vehicle. Cannot do it earlier as we need
       
  1842 		 * the vehicle refitted before doing this, otherwise the moved
       
  1843 		 * cargo types might not match (passenger vs non-passenger)
       
  1844 		 */
       
  1845 		DoCommand(0, (v_front->index << 16) | w_front->index, p2 & 1 ? CO_SHARE : CO_COPY, flags, CMD_CLONE_ORDER);
       
  1846 	}
  1814 
  1847 
  1815 	/* Since we can't estimate the cost of cloning a vehicle accurately we must
  1848 	/* Since we can't estimate the cost of cloning a vehicle accurately we must
  1816 	 * check whether the player has enough money manually. */
  1849 	 * check whether the player has enough money manually. */
  1817 	if (!CheckPlayerHasMoney(total_cost)) {
  1850 	if (!CheckPlayerHasMoney(total_cost)) {
  1818 		if (flags & DC_EXEC) {
  1851 		if (flags & DC_EXEC) {
  2082 	/* Count up max and used */
  2115 	/* Count up max and used */
  2083 	for (; v != NULL; v = v->Next()) {
  2116 	for (; v != NULL; v = v->Next()) {
  2084 		count += v->cargo.Count();
  2117 		count += v->cargo.Count();
  2085 		max += v->cargo_cap;
  2118 		max += v->cargo_cap;
  2086 		if (v->cargo_cap != 0) {
  2119 		if (v->cargo_cap != 0) {
  2087 			unloading += HASBIT(v->vehicle_flags, VF_CARGO_UNLOADING) ? 1 : 0;
  2120 			unloading += HasBit(v->vehicle_flags, VF_CARGO_UNLOADING) ? 1 : 0;
  2088 			loading |= (u->current_order.flags & OF_UNLOAD) == 0 && st->goods[v->cargo_type].days_since_pickup != 255;
  2121 			loading |= (u->current_order.flags & OF_UNLOAD) == 0 && st->goods[v->cargo_type].days_since_pickup != 255;
  2089 			cars++;
  2122 			cars++;
  2090 		}
  2123 		}
  2091 	}
  2124 	}
  2092 
  2125 
  2169 			} else if (v->owner == _local_player && cost.GetCost() != 0) {
  2202 			} else if (v->owner == _local_player && cost.GetCost() != 0) {
  2170 				ShowCostOrIncomeAnimation(v->x_pos, v->y_pos, v->z_pos, cost.GetCost());
  2203 				ShowCostOrIncomeAnimation(v->x_pos, v->y_pos, v->z_pos, cost.GetCost());
  2171 			}
  2204 			}
  2172 		}
  2205 		}
  2173 
  2206 
  2174 		if (HASBIT(t.flags, OFB_PART_OF_ORDERS)) {
  2207 		if (HasBit(t.flags, OFB_PART_OF_ORDERS)) {
  2175 			/* Part of orders */
  2208 			/* Part of orders */
  2176 			UpdateVehicleTimetable(v, true);
  2209 			UpdateVehicleTimetable(v, true);
  2177 			v->cur_order_index++;
  2210 			v->cur_order_index++;
  2178 		} else if (HASBIT(t.flags, OFB_HALT_IN_DEPOT)) {
  2211 		} else if (HasBit(t.flags, OFB_HALT_IN_DEPOT)) {
  2179 			/* Force depot visit */
  2212 			/* Force depot visit */
  2180 			v->vehstatus |= VS_STOPPED;
  2213 			v->vehstatus |= VS_STOPPED;
  2181 			if (v->owner == _local_player) {
  2214 			if (v->owner == _local_player) {
  2182 				StringID string;
  2215 				StringID string;
  2183 
  2216 
  2485 	if (max > 0) {
  2518 	if (max > 0) {
  2486 
  2519 
  2487 		/* Can we actually build the vehicle type? */
  2520 		/* Can we actually build the vehicle type? */
  2488 		EngineID e;
  2521 		EngineID e;
  2489 		FOR_ALL_ENGINEIDS_OF_TYPE(e, type) {
  2522 		FOR_ALL_ENGINEIDS_OF_TYPE(e, type) {
  2490 			if (HASBIT(GetEngine(e)->player_avail, _local_player)) return true;
  2523 			if (HasBit(GetEngine(e)->player_avail, _local_player)) return true;
  2491 		}
  2524 		}
  2492 		return false;
  2525 		return false;
  2493 	}
  2526 	}
  2494 
  2527 
  2495 	/* We should be able to build infrastructure when we have the actual vehicle type */
  2528 	/* We should be able to build infrastructure when we have the actual vehicle type */
  2537 								}
  2570 								}
  2538 							} else {
  2571 							} else {
  2539 								scheme = LS_FREIGHT_WAGON;
  2572 								scheme = LS_FREIGHT_WAGON;
  2540 							}
  2573 							}
  2541 						} else {
  2574 						} else {
  2542 							bool is_mu = HASBIT(EngInfo(engine_type)->misc_flags, EF_RAIL_IS_MU);
  2575 							bool is_mu = HasBit(EngInfo(engine_type)->misc_flags, EF_RAIL_IS_MU);
  2543 
  2576 
  2544 							switch (rvi->engclass) {
  2577 							switch (rvi->engclass) {
  2545 								default: NOT_REACHED();
  2578 								default: NOT_REACHED();
  2546 								case EC_STEAM:    scheme = LS_STEAM; break;
  2579 								case EC_STEAM:    scheme = LS_STEAM; break;
  2547 								case EC_DIESEL:   scheme = is_mu ? LS_DMU : LS_DIESEL;   break;
  2580 								case EC_DIESEL:   scheme = is_mu ? LS_DMU : LS_DIESEL;   break;
  2558 			}
  2591 			}
  2559 
  2592 
  2560 			case VEH_ROAD: {
  2593 			case VEH_ROAD: {
  2561 				const RoadVehicleInfo *rvi = RoadVehInfo(engine_type);
  2594 				const RoadVehicleInfo *rvi = RoadVehInfo(engine_type);
  2562 				if (cargo_type == CT_INVALID) cargo_type = rvi->cargo_type;
  2595 				if (cargo_type == CT_INVALID) cargo_type = rvi->cargo_type;
  2563 				if (HASBIT(EngInfo(engine_type)->misc_flags, EF_ROAD_TRAM)) {
  2596 				if (HasBit(EngInfo(engine_type)->misc_flags, EF_ROAD_TRAM)) {
  2564 					/* Tram */
  2597 					/* Tram */
  2565 					scheme = IsCargoInClass(cargo_type, CC_PASSENGERS) ? LS_PASSENGER_TRAM : LS_FREIGHT_TRAM;
  2598 					scheme = IsCargoInClass(cargo_type, CC_PASSENGERS) ? LS_PASSENGER_TRAM : LS_FREIGHT_TRAM;
  2566 				} else {
  2599 				} else {
  2567 					/* Bus or truck */
  2600 					/* Bus or truck */
  2568 					scheme = IsCargoInClass(cargo_type, CC_PASSENGERS) ? LS_BUS : LS_TRUCK;
  2601 					scheme = IsCargoInClass(cargo_type, CC_PASSENGERS) ? LS_BUS : LS_TRUCK;
  2597 }
  2630 }
  2598 
  2631 
  2599 
  2632 
  2600 static SpriteID GetEngineColourMap(EngineID engine_type, PlayerID player, EngineID parent_engine_type, const Vehicle *v)
  2633 static SpriteID GetEngineColourMap(EngineID engine_type, PlayerID player, EngineID parent_engine_type, const Vehicle *v)
  2601 {
  2634 {
  2602 	SpriteID map = PAL_NONE;
  2635 	SpriteID map = (v != NULL) ? v->colormap : PAL_NONE;
       
  2636 
       
  2637 	/* Return cached value if any */
       
  2638 	if (map != PAL_NONE) return map;
  2603 
  2639 
  2604 	/* Check if we should use the colour map callback */
  2640 	/* Check if we should use the colour map callback */
  2605 	if (HASBIT(EngInfo(engine_type)->callbackmask, CBM_VEHICLE_COLOUR_REMAP)) {
  2641 	if (HasBit(EngInfo(engine_type)->callbackmask, CBM_VEHICLE_COLOUR_REMAP)) {
  2606 		uint16 callback = GetVehicleCallback(CBID_VEHICLE_COLOUR_MAPPING, 0, 0, engine_type, v);
  2642 		uint16 callback = GetVehicleCallback(CBID_VEHICLE_COLOUR_MAPPING, 0, 0, engine_type, v);
  2607 		/* A return value of 0xC000 is stated to "use the default two-color
  2643 		/* A return value of 0xC000 is stated to "use the default two-color
  2608 		 * maps" which happens to be the failure action too... */
  2644 		 * maps" which happens to be the failure action too... */
  2609 		if (callback != CALLBACK_FAILED && callback != 0xC000) {
  2645 		if (callback != CALLBACK_FAILED && callback != 0xC000) {
  2610 			map = GB(callback, 0, 14);
  2646 			map = GB(callback, 0, 14);
  2611 			/* If bit 14 is set, then the company colours are applied to the
  2647 			/* If bit 14 is set, then the company colours are applied to the
  2612 			 * map else it's returned as-is. */
  2648 			 * map else it's returned as-is. */
  2613 			if (!HASBIT(callback, 14)) return map;
  2649 			if (!HasBit(callback, 14)) {
  2614 		}
  2650 				/* Update cache */
  2615 	}
  2651 				if (v != NULL) ((Vehicle*)v)->colormap = map;
  2616 
  2652 				return map;
  2617 	bool twocc = HASBIT(EngInfo(engine_type)->misc_flags, EF_USES_2CC);
  2653 			}
       
  2654 		}
       
  2655 	}
       
  2656 
       
  2657 	bool twocc = HasBit(EngInfo(engine_type)->misc_flags, EF_USES_2CC);
  2618 
  2658 
  2619 	if (map == PAL_NONE) map = twocc ? (SpriteID)SPR_2CCMAP_BASE : (SpriteID)PALETTE_RECOLOR_START;
  2659 	if (map == PAL_NONE) map = twocc ? (SpriteID)SPR_2CCMAP_BASE : (SpriteID)PALETTE_RECOLOR_START;
  2620 
  2660 
  2621 	const Livery *livery = GetEngineLivery(engine_type, player, parent_engine_type, v);
  2661 	const Livery *livery = GetEngineLivery(engine_type, player, parent_engine_type, v);
  2622 
  2662 
  2623 	map += livery->colour1;
  2663 	map += livery->colour1;
  2624 	if (twocc) map += livery->colour2 * 16;
  2664 	if (twocc) map += livery->colour2 * 16;
  2625 
  2665 
       
  2666 	/* Update cache */
       
  2667 	if (v != NULL) ((Vehicle*)v)->colormap = map;
  2626 	return map;
  2668 	return map;
  2627 }
  2669 }
  2628 
  2670 
  2629 SpriteID GetEnginePalette(EngineID engine_type, PlayerID player)
  2671 SpriteID GetEnginePalette(EngineID engine_type, PlayerID player)
  2630 {
  2672 {
  3071 	switch (this->current_order.type) {
  3113 	switch (this->current_order.type) {
  3072 		case OT_LOADING: {
  3114 		case OT_LOADING: {
  3073 			uint wait_time = max(this->current_order.wait_time - this->lateness_counter, 0);
  3115 			uint wait_time = max(this->current_order.wait_time - this->lateness_counter, 0);
  3074 
  3116 
  3075 			/* Not the first call for this tick, or still loading */
  3117 			/* Not the first call for this tick, or still loading */
  3076 			if (mode || !HASBIT(this->vehicle_flags, VF_LOADING_FINISHED) ||
  3118 			if (mode || !HasBit(this->vehicle_flags, VF_LOADING_FINISHED) ||
  3077 					(_patches.timetabling && this->current_order_time < wait_time)) return;
  3119 					(_patches.timetabling && this->current_order_time < wait_time)) return;
  3078 
  3120 
  3079 			this->PlayLeaveStationSound();
  3121 			this->PlayLeaveStationSound();
  3080 
  3122 
  3081 			Order b = this->current_order;
  3123 			Order b = this->current_order;