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; |
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 } |
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 } |