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