src/roadveh_cmd.cpp
branchnoai
changeset 9574 698395509d12
parent 9517 be1775555bbd
child 9599 949374e83b78
equal deleted inserted replaced
9573:fa56261c7142 9574:698395509d12
     1 /* $Id$ */
     1 /* $Id$ */
       
     2 
       
     3 /** @file roadveh_cmd.cpp */
     2 
     4 
     3 #include "stdafx.h"
     5 #include "stdafx.h"
     4 #include "openttd.h"
     6 #include "openttd.h"
     5 #include "debug.h"
     7 #include "debug.h"
     6 #include "functions.h"
     8 #include "functions.h"
   127 	int32 cost;
   129 	int32 cost;
   128 	Vehicle *v;
   130 	Vehicle *v;
   129 	UnitID unit_num;
   131 	UnitID unit_num;
   130 	Engine *e;
   132 	Engine *e;
   131 
   133 
   132 	if (!IsEngineBuildable(p1, VEH_ROAD, _current_player)) return_cmd_error(STR_ENGINE_NOT_BUILDABLE);
   134 	if (!IsEngineBuildable(p1, VEH_ROAD, _current_player)) return_cmd_error(STR_ROAD_VEHICLE_NOT_AVAILABLE);
   133 
   135 
   134 	SET_EXPENSES_TYPE(EXPENSES_NEW_VEHICLES);
   136 	SET_EXPENSES_TYPE(EXPENSES_NEW_VEHICLES);
   135 
   137 
   136 	cost = EstimateRoadVehCost(p1);
   138 	cost = EstimateRoadVehCost(p1);
   137 	if (flags & DC_QUERY_COST) return cost;
   139 	if (flags & DC_QUERY_COST) return cost;
   531 
   533 
   532 static byte SetRoadVehPosition(Vehicle *v, int x, int y)
   534 static byte SetRoadVehPosition(Vehicle *v, int x, int y)
   533 {
   535 {
   534 	byte new_z, old_z;
   536 	byte new_z, old_z;
   535 
   537 
   536 	// need this hint so it returns the right z coordinate on bridges.
   538 	/* need this hint so it returns the right z coordinate on bridges. */
   537 	v->x_pos = x;
   539 	v->x_pos = x;
   538 	v->y_pos = y;
   540 	v->y_pos = y;
   539 	new_z = GetSlopeZ(x, y);
   541 	new_z = GetSlopeZ(x, y);
   540 
   542 
   541 	old_z = v->z_pos;
   543 	old_z = v->z_pos;
   661 {
   663 {
   662 	const Order *order;
   664 	const Order *order;
   663 
   665 
   664 	switch (v->current_order.type) {
   666 	switch (v->current_order.type) {
   665 		case OT_GOTO_DEPOT:
   667 		case OT_GOTO_DEPOT:
   666 			// Let a depot order in the orderlist interrupt.
   668 			/* Let a depot order in the orderlist interrupt. */
   667 			if (!(v->current_order.flags & OF_PART_OF_ORDERS)) return;
   669 			if (!(v->current_order.flags & OF_PART_OF_ORDERS)) return;
   668 			if (v->current_order.flags & OF_SERVICE_IF_NEEDED &&
   670 			if (v->current_order.flags & OF_SERVICE_IF_NEEDED &&
   669 					!VehicleNeedsService(v)) {
   671 					!VehicleNeedsService(v)) {
   670 				v->cur_order_index++;
   672 				v->cur_order_index++;
   671 			}
   673 			}
   721 						dest = rs->xy;
   723 						dest = rs->xy;
   722 					}
   724 					}
   723 				}
   725 				}
   724 				v->dest_tile = dest;
   726 				v->dest_tile = dest;
   725 			} else {
   727 			} else {
   726 				// There is no stop left at the station, so don't even TRY to go there
   728 				/* There is no stop left at the station, so don't even TRY to go there */
   727 				v->cur_order_index++;
   729 				v->cur_order_index++;
   728 				v->dest_tile = 0;
   730 				v->dest_tile = 0;
   729 			}
   731 			}
   730 			break;
   732 			break;
   731 		}
   733 		}
   826 	rvf.y = y;
   828 	rvf.y = y;
   827 	rvf.dir = dir;
   829 	rvf.dir = dir;
   828 	rvf.veh = v;
   830 	rvf.veh = v;
   829 	u = (Vehicle*)VehicleFromPos(TileVirtXY(x, y), &rvf, EnumCheckRoadVehClose);
   831 	u = (Vehicle*)VehicleFromPos(TileVirtXY(x, y), &rvf, EnumCheckRoadVehClose);
   830 
   832 
   831 	// This code protects a roadvehicle from being blocked for ever
   833 	/* This code protects a roadvehicle from being blocked for ever
   832 	//  If more than 1480 / 74 days a road vehicle is blocked, it will
   834 	 * If more than 1480 / 74 days a road vehicle is blocked, it will
   833 	//  drive just through it. The ultimate backup-code of TTD.
   835 	 * drive just through it. The ultimate backup-code of TTD.
   834 	// It can be disabled.
   836 	 * It can be disabled. */
   835 	if (u == NULL) {
   837 	if (u == NULL) {
   836 		v->u.road.blocked_ctr = 0;
   838 		v->u.road.blocked_ctr = 0;
   837 		return NULL;
   839 		return NULL;
   838 	}
   840 	}
   839 
   841 
   879 static bool RoadVehAccelerate(Vehicle *v)
   881 static bool RoadVehAccelerate(Vehicle *v)
   880 {
   882 {
   881 	uint spd = v->cur_speed + 1 + (v->u.road.overtaking != 0 ? 1 : 0);
   883 	uint spd = v->cur_speed + 1 + (v->u.road.overtaking != 0 ? 1 : 0);
   882 	byte t;
   884 	byte t;
   883 
   885 
   884 	// Clamp
   886 	/* Clamp */
   885 	spd = min(spd, v->max_speed);
   887 	spd = min(spd, v->max_speed);
   886 	if (v->u.road.state == RVSB_WORMHOLE && !(v->vehstatus & VS_HIDDEN)) {
   888 	if (v->u.road.state == RVSB_WORMHOLE && !(v->vehstatus & VS_HIDDEN)) {
   887 		spd = min(spd, GetBridge(GetBridgeType(v->tile))->speed * 2);
   889 		spd = min(spd, GetBridge(GetBridgeType(v->tile))->speed * 2);
   888 	}
   890 	}
   889 
   891 
   890 	//updates statusbar only if speed have changed to save CPU time
   892 	/* updates statusbar only if speed have changed to save CPU time */
   891 	if (spd != v->cur_speed) {
   893 	if (spd != v->cur_speed) {
   892 		v->cur_speed = spd;
   894 		v->cur_speed = spd;
   893 		if (_patches.vehicle_speed) {
   895 		if (_patches.vehicle_speed) {
   894 			InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, STATUS_BAR);
   896 			InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, STATUS_BAR);
   895 		}
   897 		}
   896 	}
   898 	}
   897 
   899 
   898 	// Decrease somewhat when turning
   900 	/* Decrease somewhat when turning */
   899 	if (!(v->direction & 1)) spd = spd * 3 >> 2;
   901 	if (!(v->direction & 1)) spd = spd * 3 >> 2;
   900 
   902 
   901 	if (spd == 0) return false;
   903 	if (spd == 0) return false;
   902 
   904 
   903 	if ((byte)++spd == 0) return true;
   905 	if ((byte)++spd == 0) return true;
  1151 		trackdir = DiagdirToDiagTrackdir(enterdir);
  1153 		trackdir = DiagdirToDiagTrackdir(enterdir);
  1152 		//debug("Finding path. Enterdir: %d, Trackdir: %d", enterdir, trackdir);
  1154 		//debug("Finding path. Enterdir: %d, Trackdir: %d", enterdir, trackdir);
  1153 
  1155 
  1154 		ftd = PerfNPFRouteToStationOrTile(tile - TileOffsByDiagDir(enterdir), trackdir, &fstd, TRANSPORT_ROAD, v->owner, INVALID_RAILTYPE);
  1156 		ftd = PerfNPFRouteToStationOrTile(tile - TileOffsByDiagDir(enterdir), trackdir, &fstd, TRANSPORT_ROAD, v->owner, INVALID_RAILTYPE);
  1155 		if (ftd.best_trackdir == INVALID_TRACKDIR) {
  1157 		if (ftd.best_trackdir == INVALID_TRACKDIR) {
  1156 			/* We are already at our target. Just do something */
  1158 			/* We are already at our target. Just do something
  1157 			//TODO: maybe display error?
  1159 			 * @todo: maybe display error?
  1158 			//TODO: go straight ahead if possible?
  1160 			 * @todo: go straight ahead if possible? */
  1159 			return_track(FindFirstBit2x64(trackdirs));
  1161 			return_track(FindFirstBit2x64(trackdirs));
  1160 		} else {
  1162 		} else {
  1161 			/* If ftd.best_bird_dist is 0, we found our target and ftd.best_trackdir contains
  1163 			/* If ftd.best_bird_dist is 0, we found our target and ftd.best_trackdir contains
  1162 			the direction we need to take to get there, if ftd.best_bird_dist is not 0,
  1164 			the direction we need to take to get there, if ftd.best_bird_dist is not 0,
  1163 			we did not find our target, but ftd.best_trackdir contains the direction leading
  1165 			we did not find our target, but ftd.best_trackdir contains the direction leading
  1221 
  1223 
  1222 static uint RoadFindPathToStop(const Vehicle *v, TileIndex tile)
  1224 static uint RoadFindPathToStop(const Vehicle *v, TileIndex tile)
  1223 {
  1225 {
  1224 	uint dist;
  1226 	uint dist;
  1225 	if (_patches.yapf.road_use_yapf) {
  1227 	if (_patches.yapf.road_use_yapf) {
  1226 		// use YAPF
  1228 		/* use YAPF */
  1227 		dist = YapfRoadVehDistanceToTile(v, tile);
  1229 		dist = YapfRoadVehDistanceToTile(v, tile);
  1228 	} else {
  1230 	} else {
  1229 		// use NPF
  1231 		/* use NPF */
  1230 		NPFFindStationOrTileData fstd;
  1232 		NPFFindStationOrTileData fstd;
  1231 		Trackdir trackdir = GetVehicleTrackdir(v);
  1233 		Trackdir trackdir = GetVehicleTrackdir(v);
  1232 		assert(trackdir != INVALID_TRACKDIR);
  1234 		assert(trackdir != INVALID_TRACKDIR);
  1233 
  1235 
  1234 		fstd.dest_coords = tile;
  1236 		fstd.dest_coords = tile;
  1235 		fstd.station_index = INVALID_STATION; // indicates that the destination is a tile, not a station
  1237 		fstd.station_index = INVALID_STATION; // indicates that the destination is a tile, not a station
  1236 
  1238 
  1237 		dist = NPFRouteToStationOrTile(v->tile, trackdir, &fstd, TRANSPORT_ROAD, v->owner, INVALID_RAILTYPE).best_path_dist;
  1239 		dist = NPFRouteToStationOrTile(v->tile, trackdir, &fstd, TRANSPORT_ROAD, v->owner, INVALID_RAILTYPE).best_path_dist;
  1238 		// change units from NPF_TILE_LENGTH to # of tiles
  1240 		/* change units from NPF_TILE_LENGTH to # of tiles */
  1239 		if (dist != UINT_MAX)
  1241 		if (dist != UINT_MAX)
  1240 			dist = (dist + NPF_TILE_LENGTH - 1) / NPF_TILE_LENGTH;
  1242 			dist = (dist + NPF_TILE_LENGTH - 1) / NPF_TILE_LENGTH;
  1241 	}
  1243 	}
  1242 	return dist;
  1244 	return dist;
  1243 }
  1245 }
  1275 	Direction old_dir;
  1277 	Direction old_dir;
  1276 	RoadDriveEntry rd;
  1278 	RoadDriveEntry rd;
  1277 	int x,y;
  1279 	int x,y;
  1278 	uint32 r;
  1280 	uint32 r;
  1279 
  1281 
  1280 	// decrease counters
  1282 	/* decrease counters */
  1281 	v->tick_counter++;
  1283 	v->tick_counter++;
  1282 	if (v->u.road.reverse_ctr != 0) v->u.road.reverse_ctr--;
  1284 	if (v->u.road.reverse_ctr != 0) v->u.road.reverse_ctr--;
  1283 
  1285 
  1284 	// handle crashed
  1286 	/* handle crashed */
  1285 	if (v->u.road.crashed_ctr != 0) {
  1287 	if (v->u.road.crashed_ctr != 0) {
  1286 		RoadVehIsCrashed(v);
  1288 		RoadVehIsCrashed(v);
  1287 		return;
  1289 		return;
  1288 	}
  1290 	}
  1289 
  1291 
  1290 	RoadVehCheckTrainCrash(v);
  1292 	RoadVehCheckTrainCrash(v);
  1291 
  1293 
  1292 	// road vehicle has broken down?
  1294 	/* road vehicle has broken down? */
  1293 	if (v->breakdown_ctr != 0) {
  1295 	if (v->breakdown_ctr != 0) {
  1294 		if (v->breakdown_ctr <= 2) {
  1296 		if (v->breakdown_ctr <= 2) {
  1295 			HandleBrokenRoadVeh(v);
  1297 			HandleBrokenRoadVeh(v);
  1296 			return;
  1298 			return;
  1297 		}
  1299 		}
  1626 
  1628 
  1627 		if (rs == v->u.road.slot) {
  1629 		if (rs == v->u.road.slot) {
  1628 			/* We are leaving the correct station */
  1630 			/* We are leaving the correct station */
  1629 			ClearSlot(v);
  1631 			ClearSlot(v);
  1630 		} else if (v->u.road.slot != NULL) {
  1632 		} else if (v->u.road.slot != NULL) {
  1631 			/* We are leaving the wrong station */
  1633 			/* We are leaving the wrong station
  1632 			//XXX The question is .. what to do? Actually we shouldn't be here
  1634 			 * XXX The question is .. what to do? Actually we shouldn't be here
  1633 			//but I guess we need to clear the slot
  1635 			 * but I guess we need to clear the slot */
  1634 			DEBUG(ms, 0, "Vehicle %d (index %d) arrived at wrong stop", v->unitnumber, v->index);
  1636 			DEBUG(ms, 0, "Vehicle %d (index %d) arrived at wrong stop", v->unitnumber, v->index);
  1635 			if (v->tile != v->dest_tile) {
  1637 			if (v->tile != v->dest_tile) {
  1636 				DEBUG(ms, 2, " current tile 0x%X is not destination tile 0x%X. Route problem", v->tile, v->dest_tile);
  1638 				DEBUG(ms, 2, " current tile 0x%X is not destination tile 0x%X. Route problem", v->tile, v->dest_tile);
  1637 			}
  1639 			}
  1638 			if (v->dest_tile != v->u.road.slot->xy) {
  1640 			if (v->dest_tile != v->u.road.slot->xy) {
  1690 	if (_patches.servint_roadveh == 0) return;
  1692 	if (_patches.servint_roadveh == 0) return;
  1691 	if (!VehicleNeedsService(v)) return;
  1693 	if (!VehicleNeedsService(v)) return;
  1692 	if (v->vehstatus & VS_STOPPED) return;
  1694 	if (v->vehstatus & VS_STOPPED) return;
  1693 	if (_patches.gotodepot && VehicleHasDepotOrders(v)) return;
  1695 	if (_patches.gotodepot && VehicleHasDepotOrders(v)) return;
  1694 
  1696 
  1695 	// Don't interfere with a depot visit scheduled by the user, or a
  1697 	/* Don't interfere with a depot visit scheduled by the user, or a
  1696 	// depot visit by the order list.
  1698 	 * depot visit by the order list. */
  1697 	if (v->current_order.type == OT_GOTO_DEPOT &&
  1699 	if (v->current_order.type == OT_GOTO_DEPOT &&
  1698 			(v->current_order.flags & (OF_HALT_IN_DEPOT | OF_PART_OF_ORDERS)) != 0)
  1700 			(v->current_order.flags & (OF_HALT_IN_DEPOT | OF_PART_OF_ORDERS)) != 0)
  1699 		return;
  1701 		return;
  1700 
  1702 
  1701 	// If we already got a slot at a stop, use that FIRST, and go to a depot later
  1703 	/* If we already got a slot at a stop, use that FIRST, and go to a depot later */
  1702 	if (v->u.road.slot != NULL) return;
  1704 	if (v->u.road.slot != NULL) return;
  1703 
  1705 
  1704 	if (IsRoadVehInDepot(v)) {
  1706 	if (IsRoadVehInDepot(v)) {
  1705 		VehicleServiceInDepot(v);
  1707 		VehicleServiceInDepot(v);
  1706 		return;
  1708 		return;
  1707 	}
  1709 	}
  1708 
  1710 
  1709 	// XXX If we already have a depot order, WHY do we search over and over?
  1711 	/* XXX If we already have a depot order, WHY do we search over and over? */
  1710 	depot = FindClosestRoadDepot(v);
  1712 	depot = FindClosestRoadDepot(v);
  1711 
  1713 
  1712 	if (depot == NULL || DistanceManhattan(v->tile, depot->xy) > 12) {
  1714 	if (depot == NULL || DistanceManhattan(v->tile, depot->xy) > 12) {
  1713 		if (v->current_order.type == OT_GOTO_DEPOT) {
  1715 		if (v->current_order.type == OT_GOTO_DEPOT) {
  1714 			v->current_order.type = OT_DUMMY;
  1716 			v->current_order.type = OT_DUMMY;
  1741 	AgeVehicle(v);
  1743 	AgeVehicle(v);
  1742 	CheckIfRoadVehNeedsService(v);
  1744 	CheckIfRoadVehNeedsService(v);
  1743 
  1745 
  1744 	CheckOrders(v);
  1746 	CheckOrders(v);
  1745 
  1747 
  1746 	//Current slot has expired
  1748 	/* Current slot has expired */
  1747 	if (v->current_order.type == OT_GOTO_STATION && v->u.road.slot != NULL && v->u.road.slot_age-- == 0) {
  1749 	if (v->current_order.type == OT_GOTO_STATION && v->u.road.slot != NULL && v->u.road.slot_age-- == 0) {
  1748 		DEBUG(ms, 3, "Slot expired for vehicle %d (index %d) at stop 0x%X",
  1750 		DEBUG(ms, 3, "Slot expired for vehicle %d (index %d) at stop 0x%X",
  1749 			v->unitnumber, v->index, v->u.road.slot->xy);
  1751 			v->unitnumber, v->index, v->u.road.slot->xy);
  1750 		ClearSlot(v);
  1752 		ClearSlot(v);
  1751 	}
  1753 	}